在 Kubernetes 上部署 Prometheus + Grafana 监控栈(kube-prometheus-stack)
给 Kubernetes 集群上监控,最怕的是从零拼组件:Prometheus、node-exporter、kube-state-metrics、Alertmanager、Grafana 一个都不能少,还要自己写抓取配置和仪表盘。kube-prometheus-stack 把这套组件打包成一个 Helm Chart,并用 Operator 管理抓取目标与告警规则,是目前社区事实标准。本文完成一次可上生产的安装,并讲清怎么给业务加监控、怎么让告警真正发得出来。
适用环境:Kubernetes 1.26+ 集群,有可用的 StorageClass(示例用默认存储类),节点资源能给监控栈预留约 4 核 8G(Prometheus 的内存占用随目标数增长,先紧后松均可,但要给它留出增长空间)。
前置条件
- kubectl 已配置好目标集群上下文,当前账号有创建命名空间与 CRD 的权限(安装会写入大量 CustomResourceDefinition)。
- 已安装 Helm 3。
- 集群已部署 Ingress 控制器(如 ingress-nginx),用于对外暴露 Grafana;没有也可以用端口转发先体验。
- 告警通知渠道已准备:一个企业微信/钉钉机器人的 Webhook,或一个可用的 SMTP 邮箱(本文以 Webhook 转接思路说明,Alertmanager 原生支持邮箱与 Webhook)。
第一步:用 Helm 安装
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
kubectl create namespace monitoring
helm install kps prometheus-community/kube-prometheus-stack \
-n monitoring -f values.yaml
先不要裸装,values.yaml 决定了它是玩具还是生产件。
第二步:values 关键配置
prometheus:
prometheusSpec:
retention: 15d
retentionSize: 45GB
replicas: 1
storageSpec:
storageClassName: standard
resources:
requests:
storage: 50Gi
resources:
requests:
cpu: 500m
memory: 2Gi
limits:
memory: 4Gi
grafana:
adminPassword: '请改成强密码并妥善保存'
persistence:
enabled: true
size: 5Gi
ingress:
enabled: true
ingressClassName: nginx
hosts:
- grafana.example.com
alertmanager:
alertmanagerSpec:
replicas: 1
storage:
volumeClaimTemplate:
spec:
storageClassName: standard
resources:
requests:
storage: 2Gi
关键点说明:第一,Prometheus 必须开持久化,否则 Pod 一重启历史数据全丢,趋势图和告警的 for 持续时间判断都没有意义;存储类建议选 SSD 型云盘或本地盘,Prometheus 对磁盘延迟敏感。第二,retention 与 retentionSize 双限同时生效,先到先清;容量按「日增量 × 天数」估算,并用 retentionSize 托底防数据盘被写满。第三,Grafana 密码不要用 Chart 默认值,也不要把 values.yaml 提交进公开仓库;更规范的做法是用 admin.existingSecret 引用一个预先创建的 Secret。第四,Grafana 开持久化是为保住用户自建的仪表盘与数据源改动。
第三步:认识自带组件与仪表盘
安装完成后,栈里自带了集群层面的完整视图:节点 CPU/内存/磁盘、工作负载与 Pod 资源用量、API Server 状态、网络收发等。Grafana 预置的 "Kubernetes / Compute Resources / Namespace (Pods)" 适合按命名空间看资源占用,"Node Exporter / Nodes" 适合看单机水位。建议上线第一周先把基线摸清:节点内存常态水位、API Server 延迟、etcd 盘延迟,再谈自定义仪表盘。排查指标先用 Grafana 的 Explore 确认指标存在,再去配图和告警。
第四步:给业务加监控的两种方式
Operator 模式下不要去改 Prometheus 的抓取配置文件,而是提交自定义资源,Operator 会自动生成配置。两种常用资源:
ServiceMonitor:通过标签选择一组 Service,适合「服务已经有 Service 入口、指标从固定端口暴露」的常规场景,是首选:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: myapp
namespace: monitoring
labels:
release: kps
spec:
selector:
matchLabels:
app: myapp
namespaceSelector:
matchNames:
- prod
endpoints:
- port: metrics
path: /metrics
interval: 30s
这里有个几乎人人踩的坑:ServiceMonitor 必须带上与 Helm release 对应的标签(本例 release: kps),Operator 默认只认领带该标签的资源,漏了标签资源提交成功也不会生效,且不报任何错。另外,被选中的 Service 必须有名为 metrics 的端口,且其标签与 selector 对得上。
PodMonitor:绕过 Service、直接按标签抓 Pod,适合没有 Service、或每个 Pod 都要单独抓(如 DaemonSet 组件)的场景,字段结构与 ServiceMonitor 类似,只是 selector 作用于 Pod。选型原则:有 Service 就用 ServiceMonitor,只有确定要按 Pod 抓时才用 PodMonitor,避免同一目标被两条路径重复抓取导致数据翻倍。
第五步:告警规则与 Alertmanager 路由(最简可用版)
告警规则用 PrometheusRule 资源下发。先加一条最实用的:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: myapp-rules
namespace: monitoring
labels:
release: kps
spec:
groups:
- name: myapp
rules:
- alert: PodHighCpu
expr: sum(rate(container_cpu_usage_seconds_total{namespace="prod",pod=~"myapp-.*"}[5m])) > 2
for: 10m
labels:
severity: warning
annotations:
summary: "myapp 整体 CPU 持续偏高"
同样要带 release 标签。Alertmanager 的路由与接收器在 Chart 里通过 alertmanager.config 段配置,最简结构是按 severity 分流:critical 走电话或值班群,warning 走普通群。接收器以企业微信为例,一般经一个 webhook 转换服务把 Alertmanager 的 JSON 转成机器人格式;用邮箱则直接用 email_configs。配置时记住三点:group_wait 与 group_interval 保持默认量级,告警聚合本身就是降噪手段;repeat_interval 建议 4 小时以上,避免同一故障刷屏;新规则先以 warning 级别观察一周再升 critical,误报是常态。
验证
kubectl -n monitoring get pods
kubectl -n monitoring port-forward svc/kps-kube-prometheus-stack-prometheus 9090:9090
浏览器打开 http://127.0.0.1:9090 的 Status → Targets 页面,确认内置目标为 UP;提交业务的 ServiceMonitor 后,能在 Targets 里看到新目标且样本能查到。再打开 Grafana 确认预置仪表盘有数据。最后把一条测试规则的阈值调到必然触发,确认 Alertmanager 出现该告警且通知送达,监控才算真正闭环。
常见问题
1. ServiceMonitor 提交了但 Target 列表里没有。九成是标签问题:检查是否带 release 标签、selector 是否匹配 Service 的标签、Service 的端口名是否为 metrics,任一不符都会静默不生效,用 kubectl -n monitoring get servicemonitor myapp -o yaml 对照即可。
2. Target 显示 DOWN,报错被连接拒绝或超时。先在 Prometheus Pod 内看具体错误:connection refused 多为目标端口没在监听 /metrics 或路径写错;超时多为网络策略(NetworkPolicy)拦截——集群启用默认拒绝策略时,需放行 monitoring 命名空间到业务目标端口的入站流量,这是此类集群最常见的抓取失败原因。
3. Prometheus Pod 反复 OOMKilled 或 CrashLoop。目标数或标签基数暴涨是主因:业务指标里带用户 ID、请求 ID 这类高基数标签会把内存打爆。先看 Status → TSDB Status 定位高基数指标源头,推动业务下掉违规标签;同时把 memory limit 适当放大只能救急,不能代替治理。
4. 数据盘写满,Prometheus 报 out of space。保留策略没估准或容量给小了。紧急处理是调小 retention 后重启使之清数据;长期要给数据盘单独接使用率告警(可用空间小于 20% 提前报警)——监控系统自己的可用性也要被监控。
小结
kube-prometheus-stack 的价值在于把抓取、规则、仪表盘都变成可版本管理的资源。上线要点:安装前先把持久化、保留时长、Grafana 暴露在 values 里定死;加监控优先 ServiceMonitor 且牢记 release 标签;告警先少后多、先观察后升级,并亲手触发一次验证通知链路。这样搭出来的监控栈,才经得起第一次真正的故障。







