在 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 标签;告警先少后多、先观察后升级,并亲手触发一次验证通知链路。这样搭出来的监控栈,才经得起第一次真正的故障。

发表回复

后才能评论