news 2026/9/29 1:11:30

K8s集群监控部署:Prometheus与Grafana安装配置实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
K8s集群监控部署:Prometheus与Grafana安装配置实战

1. 为什么集群监控绕不开 Prometheus 和 Grafana 这套组合

我在几个不同规模的 K8s 集群里都部署过监控栈,从最开始用一堆零散脚本凑合,到后来老老实实上 prometheus + grafana,踩的坑足够写一本小册子。Prometheus 负责采集和存储时序数据,Grafana 负责把这些数据画成能看懂的图,两者搭起来,基本就是 K8s 集群监控的事实标准。你会发现,不管是官方文档、社区文章,还是大厂分享出来的方案,绕来绕去最后都回到这套东西上。

标题里说的“k8s集群部署Grafana安装和配置”,本质上要解决三件事:第一,集群里跑着成百上千个容器,它们的状态、资源、请求延迟怎么拿到;第二,拿到的数据放在哪、怎么查;第三,怎么让这些冷冰冰的指标变成一眼能判断问题的大盘。Prometheus 管前两件,Grafana 管第三件。这套方案适合谁呢?适合刚把 K8s 集群搭起来、准备上生产或者已经在小规模跑业务、但又不想花大钱买商业监控的团队。也适合运维、DevOps、SRE 这些每天跟集群打交道的朋友,哪怕你之前只会在 Docker 里跑个端口映射,这篇文章也能让你把整套监控栈在集群里跑起来。

我先说一个很多人会疑惑的点:为什么不在每个节点上装个传统的监控 agent,比如 exporter + 自建时序库就完事?真实原因是 K8s 里的资源是动态的,Pod 会漂移、会重建,IP 会变,服务往往还是通过 Service 暴露的。传统方式要么写死地址,要么手工维护采集目标,集群一扩容就乱套。而 Prometheus 的设计天然适配这种动态环境——它有一套服务发现的机制,能自动从 API Server 里感知到新的目标,配合 Operator 还能用声明式的方式管理采集规则,这才是它能在 K8s 里站稳脚跟的根本原因。

再聊聊 Grafana 为什么不能省。有人觉得自己写个脚本调 Prometheus 的 HTTP API 拿数据就够了。我试过,前期看着挺美,但一旦指标维度变多、查询逻辑变复杂,脚本会迅速失控。Grafana 真正的价值在于:它把查询、聚合、展示、告警这四件事统一到一个界面里,而且社区里有大量现成的仪表盘模板,导入就能用。比如 node_exporter 的标准大盘,直接导入 ID 为 1860 的模板,几十个指标图立马就有了,省下的是整周的工作量。所以本文的路线是:先把 Prometheus 在集群里跑通、采集到数据,再接 Grafana 做可视化,最后顺带把告警链路的思路理一遍。

2. 部署前必须理清的整体架构与选型思路

2.1 两种主流部署路线:Operator 还是手写清单

在 K8s 里部署 Prometheus,社区主要有两条路:一条是手动写 Deployment、Service、ConfigMap,自己拼装各个组件;另一条是用 kube-prometheus-stack 这个 Helm chart,它底层基于 Prometheus Operator。我两种都做过,给你一个明确的结论:除非你所在的环境有严格的依赖管控,否则优先上 Operator 这套。

原因很实际。手写清单的时候,每一个采集目标、每一条告警规则、每一份 Grafana 面板,你都得通过 ConfigMap 挂载进容器,改一次重启一次,而且 Prometheus 的配置文件是原生的 YAML 格式,跟 K8s 的 CRD(自定义资源)完全是两套语法。一旦集群里服务数量上来,维护成本会呈指数级增长。而 Prometheus Operator 把“要监控什么”抽象成了 ServiceMonitor 和 PodMonitor 这类声明式资源——你只要写一个 ServiceMonitor,选中带特定标签的 Service,Operator 就会自动把它转换成 Prometheus 的采集配置,全程不用碰原生配置。

当然,Operator 也不是没代价。它引入了一层抽象,排错时你需要多理解几个 CRD 的含义,而且版本兼容性有时候会出幺蛾子。但我个人的经验是,学 Operator 的成本远远低于长期手工维护配置的成本。

2.2 各组件的职责和联动关系

在正式动手前,咱们把这条链路上的角色一个个摆清楚,不然后面看 YAML 会晕。Prometheus Server是核心,负责抓取、存储、提供查询接口;Alertmanager是告警分发中心,Prometheus 自己只负责判断规则是否触发,真正的去重、分组、发通知是 Alertmanager 干的;Grafana是前端,它不存数据,只从 Prometheus 查;node-exporter部署在每个节点上,采集主机级别的 CPU、内存、磁盘、网络;kube-state-metrics则负责把 K8s 对象的状态,比如 Deployment 的副本数、Pod 的 Phase,翻译成指标暴露出来。

这几者之间的关系可以用一句话概括:exporter 和各类 target 提供原始数据,Prometheus 定时去拉,Alertmanager 接收 Prometheus 推来的告警,Grafana 从 Prometheus 拉数据画图。理解了这个数据流向,你在配置 ServiceMonitor 或者调 Grafana 数据源的时候,心里就有谱了。

2.3 存储和资源规划要提前想清楚

Prometheus 默认把数据存在容器本地目录,Pod 一重建数据就没了。生产环境一定要挂持久卷。我见过一个案例,某团队图省事没挂 PVC,结果节点重启导致半个月的历史数据全丢,出故障时连个对比基线都没有。所以在部署前,先给 Prometheus 和 Grafana 各规划一块 PVC,大小根据你的采集规模和保留周期来。一个经验值:单节点、采集 1000 个左右时间序列、保留 15 天,大概需要 20 到 30 GB。Grafana 那边主要存面板和用户配置,1 到 2 GB 足够。

资源这块,Prometheus 对内存比较敏感,每 100 万个活跃时间序列大约吃 1 到 2 GB 内存,这个数量级心里要有数。可以先给 Prometheus 2 核 4G 的 requests 起步,观察一周再调。Grafana 相对轻量,1 核 1G 就能跑得不错。

3. 从零开始的集群环境准备与命名空间规划

3.1 集群基础检查

动手前先确认你的集群状态正常,这是老生常谈但每次都有人跳过。用下面几条命令过一遍:

kubectl get nodes -o wide kubectl get cs kubectl version --short

节点必须是 Ready 状态,几个核心组件健康,客户端和服务端版本不要差太多。我之前遇到过一次诡异的问题,kubectl 版本比 API Server 高了两三个小版本,导致某些资源的 apply 行为不一致,排查了半天。所以版本对齐这件事别嫌烦。

如果你的集群是通过 kubeadm 搭的,还要确认 API Server 的聚合层相关配置别被改乱了,因为 Prometheus Operator 依赖 apiserver 的一些指标接口。不过一般标准安装的集群都没问题,这一步更多是排除历史遗留的个性化配置。

3.2 命名空间和 Helm 环境准备

监控组件我习惯单独放到一个命名空间,比如monitoring,好处是资源隔离清晰,删起来也干净。

kubectl create namespace monitoring

接着确认 helm 可用。Helm 版本建议 3.x 以上:

helm version

如果没有 helm,去官方渠道按你的操作系统装一个,这一步不展开。然后添加 prometheus-community 仓库:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update

这里插一句,拉取 chart 的时候,如果网络环境导致部分资源下载慢,可以先把 chart 下载到本地再安装,命令是helm pull prometheus-community/kube-prometheus-stack,下载完是一个 tar 包,解压后可以按自己的需要改 values。我强烈建议第一次安装前把 values.yaml 拉下来通读一遍,不是照抄,而是搞清楚默认打开了哪些组件、默认的告警规则都有哪些,后续出问题至少知道去哪找。

3.3 存储类的确认

如果你的集群有默认 StorageClass,创建 PVC 时可以不写 storageClassName,直接走默认。检查方式:

kubectl get storageclass

输出里带(default)字样的就是默认存储类。如果没有默认存储类,你就得在安装时显式指定名字,或者在 values 里给每个组件单独配 storageClass。这一点如果搞错,PVC 会一直 Pending,Pod 起不来,报错信息还比较隐晦,很多时候只看到挂载失败,其实根子在存储类上。

4. Prometheus 部署全流程与核心配置拆解

4.1 用 Helm 安装 kube-prometheus-stack

基础环境就绪后,一条命令就能把整套栈铺下去。但别急着直接 install,先写一份精简的 values 文件,控制关键参数。下面是我常用的一个最小可用配置:

# values-monitoring.yaml grafana: enabled: true persistence: enabled: true storageClassName: "" size: 2Gi adminPassword: "改成一个强密码" service: type: NodePort nodePort: 32000 prometheus: prometheusSpec: retention: 15d storageSpec: volumeClaimTemplate: spec: storageClassName: "" resources: requests: storage: 30Gi resources: requests: cpu: 500m memory: 2Gi limits: memory: 4Gi alertmanager: enabled: true alertmanagerSpec: storage: volumeClaimTemplate: spec: resources: requests: storage: 5Gi

几个点解释一下。retention: 15d是数据保留时长,按你的磁盘和查询需求权衡,太短看不到趋势,太长磁盘吃不消。storageClassName: ""表示用集群默认的存储类,如果集群没有默认类,这里要填实际名字。Prometheus 的内存 limits 建议设得比 requests 高一档,因为它在大查询时会有内存尖峰。

安装命令:

helm install monitoring prometheus-community/kube-prometheus-stack \ -n monitoring \ -f values-monitoring.yaml

装完看 Pod:

kubectl get pods -n monitoring

正常的话会看到 prometheus-0、alertmanager-0、grafana-xxx、kube-state-metrics、各个 node-exporter 的 DaemonSet Pod,还有 operator 和 admission webhook。如果某几个 Pod 一直 CrashLoopBackOff,先看 describe 和 logs,最常见的原因就是存储没挂上或者 RBAC 权限不足。

4.2 ServiceMonitor 是怎么把服务接入采集的

这套栈装完后,集群核心组件(apiserver、kubelet、node-exporter、kube-state-metrics)的监控其实已经默认配好了。但你自己的业务服务要接入监控,就得靠 ServiceMonitor。它的原理我在前面提过,再展开说一下。

假设你有个服务叫order-service,暴露了一个/metrics端点,端口是 8080。你需要先有一个 Service 指向它,然后写一个 ServiceMonitor:

apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: order-service-monitor namespace: monitoring labels: release: monitoring spec: namespaceSelector: matchNames: - default selector: matchLabels: app: order-service endpoints: - port: metrics interval: 30s path: /metrics

这里有个非常容易踩的坑:ServiceMonitor 上的release: monitoring标签必须和 Operator 配置里的serviceMonitorSelector匹配,否则 Operator 根本不会理你。默认情况下,kube-prometheus-stack 会挑选带有自身 release 名字标签的 ServiceMonitor。很多人写完 ServiceMonitor 发现没数据,排查半天,问题就出在这个标签上。另一个坑是endpoints.port填的是 Service 里端口的名字,不是端口号,这两个概念别搞混。

验证采集是否生效,可以进 Prometheus 的 UI,在 Status -> Targets 页面看目标是不是 UP。也可以用 PromQL 查一下,比如up{job="order-service"},返回 1 就说明采集正常。

4.3 访问 Prometheus 做一次数据验证

默认情况下 Prometheus 的 Service 是 ClusterIP,集群外访问不了。临时验证可以端口转发:

kubectl port-forward -n monitoring svc/monitoring-kube-prometheus-prometheus 9090:9090

然后浏览器访问本机 9090。进去之后建议先干两件事:一是在 Graph 页面执行up查询,看看有多少目标、状态是否正常;二是在 Status -> Configuration 里确认你的采集配置有没有生效。我习惯用count(up == 1)和count(up == 0)对比,一眼就能看出有多少目标挂了。

如果你想让 Prometheus 长期可访问,可以把它的 Service 类型改成 NodePort 或者配 Ingress。生产环境我更推荐 Ingress 加认证,直接暴露 NodePort 有安全风险。说到安全,Prometheus 2.24 以后支持了基础的 web 认证,可以通过配置开启,别把没认证的 Prometheus 直接暴露到公网。

5. Grafana 安装配置与看板落地实操

5.1 确认 Grafana 部署并首次登录

kube-prometheus-stack 默认已经把 Grafana 装好了,我们前面也配了 NodePort。查看服务:

kubectl get svc -n monitoring | grep grafana

然后用节点IP:32000访问,默认用户名 admin,密码就是我们在 values 里设的那个。第一次登录强烈建议立刻改密码并创建单独的只读账号给团队成员用。我碰到过团队成员之间共用 admin 账号的情况,有人不小心删了大盘或者改了数据源,追责都追不到。

如果 NodePort 方式访问不了,先确认防火墙和节点安全组有没有放行。另外如果是云环境,还得看节点本身的网络策略。排查顺序是:Service 的 NodePort 是否正确、kube-proxy 是否正常、节点端口是否被占用。这几个排查完基本就能定位。

5.2 对接 Prometheus 数据源

Grafana 装好后数据源一般自动配好了,指向集群内的 Prometheus Service。你可以在 Configuration -> Data Sources 里确认。如果发现数据源连接失败,最常见的原因有两个:一是 URL 写错,集群内访问要用完整的 Service 名加命名空间,形如http://monitoring-kube-prometheus-prometheus.monitoring:9090;二是网络策略或者命名空间隔离导致 Grafana 访问不到 Prometheus。

我还遇到过一种情况,Grafana 报 “failed to upgrade legacy queries datasource ... was not found”,这通常是因为之前手动删除过数据源,或者数据源 ID 变化导致旧面板引用的数据源失效。解决办法是重新创建一个数据源,然后把老面板里的数据源引用批量替换过来。Grafana 新版本支持在数据源设置里指定一个固定的 UID,给数据源设一个稳定的 UID,以后就算删了重建,只要 UID 不变,面板就不会失效,这个习惯我强烈建议养成。

数据源配好后,点 “Save & Test”,看到绿色的成功提示才算真正通了。这一步别偷懒,很多人面板导入后一片空白,就是因为数据源压根没连通。

5.3 导入现成大盘模板

Grafana 的社区大盘模板是它最大的优势之一。导入路径是左侧菜单 Dashboards -> Import,然后输入模板 ID。几个我常用且口碑不错的:

模板 ID用途说明
1860Node Exporter Full主机级资源监控,CPU、内存、磁盘、网络一应俱全
315Kubernetes Cluster集群整体视角,包含节点、Pod、容器资源
6417Kubernetes Cluster (via Prometheus)另一套常用的 K8s 集群大盘
13332Kube State Metrics v2面向 K8s 对象状态,副本、重启次数等

导入的时候要注意选择正确的数据源。如果模板里的变量和你的环境不匹配,比如集群名对不上,可以在模板的变量设置里调整datasource和cluster这类查询变量。导入后先别急着用,花十分钟把每个面板点一遍,确认数据都有值,尤其是那些依赖特定 label 的面板,很容易因为 label 命名不同而空白。

5.4 告警接入的基本链路

标题里没细说告警,但既然上了监控,告警早晚要做。链路是:Prometheus 根据告警规则判断,把触发的告警推给 Alertmanager,Alertmanager 做去重、分组、静默,然后发到邮件、企业微信、钉钉或 webhook。kube-prometheus-stack 里默认带了一批告警规则,你也可以通过 PrometheusRule 这个 CRD 加自己的规则。

写告警规则时,for 字段很关键,它表示条件持续多久才真正触发。比如 CPU 使用率超过 80%,如果是瞬时触发,告警会响个不停;设成for: 5m,只有持续 5 分钟才告警,噪音会少很多。另一个经验是给告警加好 severity 标签,区分 warning 和 critical,前端 Alertmanager 就能按级别分开发送,不至于半夜被一个 warning 吵醒。

Alertmanager 的配置在 values 里通过alertmanager.config注入,接入企业微信或者 webhook 需要写 receiver,这部分内容比较多,本文先点到,核心是先保证 Prometheus 能触发告警、Alertmanager 能收到,再逐步对接具体的通知渠道。

6. 常见问题排查与实操避坑清单

6.1 高频问题速查

下面这些是我和身边朋友在实际部署中反复遇到的,整理成表方便对照:

现象可能原因处理方向
PVC 一直 Pending没有默认 StorageClass 或 storageClassName 写错检查 storageclass,显式指定正确类名
Prometheus Pod 启动后反复重启内存 limit 太小或存储挂载失败调大 limits,检查 PVC 状态
ServiceMonitor 加了但没数据release 标签不匹配 Operator 选择器补上正确的 release label
Grafana 面板全空白数据源没连通或时间范围选错检查数据源 Save & Test,调整时间区间
目标大量 DOWN采集目标网络不通或端口名写错检查 Service 端口名与 endpoints.port 一致
告警一直重复for 字段没设或设得太短合理设置 for 时长,配置分组
数据源删后大盘失效数据源 UID 变化重建时固定 UID,或批量替换引用

6.2 几个文档里不会写的经验

第一,资源和存储永远比你想的吃得多。我刚开始部署时,给 Prometheus 配了 1G 内存,结果集群里 service 一多,采集目标涨到几千个,Prometheus 直接被 OOM Kill。后来学乖了,先按经验值给足,观察一周再调。监控系统本身要是挂了,那真是雪上加霜。

第二,采集间隔别设太短。有人为了“实时”,把 scrape interval 设成 5s,结果时间序列数量暴涨,磁盘和内存都吃不消。15s 到 30s 对绝大多数业务场景足够了,除非你有明确的亚秒级需求。缩短采集间隔带来的成本是线性的甚至更高的,收益却往往有限,这笔账要算清楚。

第三,标签基数要控制。Prometheus 的 label 组合会形成独立的时间序列。如果你在指标里塞了个用户 ID 或者请求 URL 这种高基数标签,时间序列数量会爆炸,内存和查询都会崩。别把订单号、UUID 这类东西做成 label,这是把 Prometheus 玩坏的最快方式,没有之一。

第四,升级要谨慎。kube-prometheus-stack 的版本升级偶尔会带来 CRD 变更,升级前先看 changelog,在测试环境走一遍。生产集群直接helm upgrade一路绿灯的情况不多,我至少遇到过两次因为 CRD 不兼容导致 Operator 起不来的情况,回滚还算顺利,但心跳是实打实加速了。

6.3 让这套栈长期稳定运行的建议

最后分享几个我坚持的习惯。给监控组件本身也加监控,用 Prometheus 的 self metrics 监控它自己的抓取耗时、目标数量、内存使用,做到早发现早处理。定期检查磁盘水位,Prometheus 的 TSDB 目录增长是持续的,磁盘满了会导致写入失败。把 Grafana 的大盘和告警规则纳入版本管理,用 Git 存起来,别只存在 Grafana 的数据库里,机器一坏配置全没的教训太深刻了。

我个人在实际操作中的体会是,这套组合的上手门槛其实不高,真正难的是长期运维中的细节把控——采集什么、不采集什么、告警怎么调、资源怎么扩。把这些想明白,你的集群监控才算是真正立住了,而不是装完就忘、出事才发现没数据。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 1:09:18

Ubuntu安装Anaconda全攻略:隔离环境、镜像加速与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:09:09

边缘AI芯片选型:从场景反推才是落地第一课

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:09:04

eWebEditor 11.0 中文商业版实战:Word导入清洗与IIS部署避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:08:56

STM32+FPGA工业控制器分级存储设计:EEPROM/NOR Flash/SD卡实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:08:56

台达A2-M伺服驱动器CN3口Modbus RTU串口控制实战详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:08:24

Python泛型实战:从TypeVar到Protocol的数据转换服务

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华