Prometheus+Grafana:K8s 监控告警实战

Prometheus 是云原生监控的事实标准。它用 Pull 模型周期性抓取 Kubernetes 集群指标,配合 Grafana 把数据变成可读看板,再用 Alertmanager 把异常推送到钉钉、飞书或邮件。本文从部署到告警,手把手带你搭一套能跑在生产环境的 Prometheus + Grafana 监控告警体系。

Prometheus 为什么是云原生监控首选

传统监控(如 Zabbix)多为 Push 模型:被监控端主动上报。但在 Kubernetes 里,Pod 随时扩缩、IP 不断变化,Push 模型很难跟上拓扑。Prometheus 反过来——服务端主动去拉(Pull),并借助 Kubernetes 服务发现自动感知每一个新 Pod,无需手动登记。指标以时间序列(TSDB)存储,天然适合做”过去 5 分钟 CPU 涨了多少”这类查询。

四种核心指标类型

类型语义典型场景
Counter只增不减的累加值请求总数、错误数
Gauge可增可减的瞬时值CPU、内存、队列长度
Histogram样本分布 + 分桶计数请求延迟分布
Summary分位数近似计算P95 / P99 延迟

写埋点时先想清要算什么:算”速率”用 Counter,算”当前值”用 Gauge,算”延迟分布”用 Histogram。选错类型,后面的 PromQL 会非常别扭。

在 Kubernetes 部署监控栈

手动拼 Prometheus、Alertmanager、Grafana、node-exporter 很繁琐。社区把这一整套封装成了 kube-prometheus-stack(Operator 形式),开箱即带大量 ServiceMonitor 与官方看板。用 Helm 一条命令即可拉起:

# 添加仓库并部署整套监控栈
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install kps prometheus-community/kube-prometheus-stack \
  -n monitoring --create-namespace

# 验证核心组件都起来
kubectl get pods -n monitoring
kubectl get svc -n monitoring | grep -E 'prometheus|grafana|alertmanager'

装好后,集群节点、控制面、核心组件的指标已经被自动抓取。你只需关心”自己的业务怎么暴露 /metrics”。若你的服务跑在 Docker Compose 而非 K8s,可参考我们之前的《Docker Compose 一键编排》先把服务稳定跑起来,再考虑上 K8s 监控。

配置抓取:从 Node 到 Pod

Prometheus 通过 scrape_configs 决定抓谁。在 Operator 体系里,你不用改 Prometheus 主配置,而是声明一个 ServiceMonitor 自定义资源,Operator 会自动把它翻译成抓取规则。下面让 Prometheus 每 15 秒抓取带 app: my-app 标签的服务的 /metrics:

# ServiceMonitor:让 Prometheus 自动抓取某服务的 /metrics
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: my-app
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: my-app
  endpoints:
  - port: http
    path: /metrics
    interval: 15s

业务侧只要用客户端库(如 Java 的 Micrometer、Go 的 promhttp)在 /metrics 暴露指标,并给 Service 打上对应 label,数据就会自动流入 Prometheus。

写第一条告警规则

告警规则用 PromQL 表达”什么算异常”。for 表示持续多久才触发,避免抖动误报。下面两条覆盖了最常见的两个场景:实例失联与 Pod 频繁重启——后者往往连着《CrashLoopBackOff 排查》里提到的容器反复崩溃。

groups:
- name: k8s-alerts
  rules:
  - alert: 实例宕机
    expr: up == 0
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "{{ $labels.instance }} 已失联 2 分钟"
  - alert: Pod频繁重启
    expr: increase(kube_pod_container_status_restarts_total[10m]) > 3
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "{{ $labels.namespace }}/{{ $labels.pod }} 近 10 分钟重启超过 3 次"

规则写好用 promtool check rules 校验语法,再热加载。想看哪些 Pod 卡在调度阶段导致没指标,可对照《K8s Pod Pending 排查》一起排查。

用 Grafana 把指标变成看板

Prometheus 自带的表达式浏览器适合临时查数,但日常盯盘靠 Grafana。Grafana 接上 Prometheus 数据源后,导入官方看板(Node Exporter Full 编号 1860、K8s 集群概览 315)就能直接看到节点与集群水位。数据源可以用配置即代码(provisioning)落库,避免人工点界面:

apiVersion: 1
datasources:
- name: Prometheus
  type: prometheus
  url: http://kps-kube-prometheus-stack-prometheus:9090
  access: proxy
  isDefault: true

Grafana 的数据库密码、钉钉机器人 token 这类敏感信息,建议用《External Secrets Operator》从云厂商密钥管理同步进来,而不是写死在明文的 ConfigMap 里。监控体系本身也应纳入 GitOps——可参考《ArgoCD 实战》把上述 YAML 全部版本化管理。

告警触达:Alertmanager 路由

Prometheus 只负责”产生告警”,真正去重、分组、静默、路由到接收端的是 Alertmanager。下面把 critical 级别单独路由到一个”加急”钉钉群,普通告警走默认群,group_wait 控制合并窗口,避免告警风暴刷屏:

route:
  receiver: dingtalk
  group_by: ['alertname', 'namespace']
  group_wait: 30s
  routes:
  - match:
      severity: critical
    receiver: dingtalk-urgent
receivers:
- name: dingtalk
  webhook_configs:
  - url: https://oapi.dingtalk.com/robot/send?access_token=xxxx
- name: dingtalk-urgent
  webhook_configs:
  - url: https://oapi.dingtalk.com/robot/send?access_token=yyyy

除了钉钉,Alertmanager 原生支持 Email、Slack、Webhook、PagerDuty 等。把监控接进《GitHub Actions》这类 CI 流水线后,还能在发布后自动校验关键指标是否异常波动。

上线前检查清单

  • Prometheus 的 Targets 页面里,业务 endpoint 状态为 UP;
  • Alertmanager 里能看到告警在 Pending / Firing 切换,而非一直空;
  • Grafana 面板有真实曲线,不是空图;
  • 故意触发一次告警,确认接收端真的收到消息(先小流量验证,再全量);
  • 用 kubectl port-forward 临时暴露 UI 排障,长期应走 Ingress + 鉴权,别裸奔公网。

PromQL 实战:从速率到分位数

监控真正值钱的是”会查”。Prometheus 查询语言 PromQL 里,rate() 算区间平均速率,irate() 看瞬时变化更灵敏,适合做实时图表。下面几条是日常最高频的查询,建议直接存进 Grafana 看板:

# 过去 5 分钟每秒请求数(QPS)
rate(http_requests_total[5m])

# 请求成功率(排除 5xx 后占比)
sum(rate(http_requests_total{code!~"5.."}[5m]))
  / sum(rate(http_requests_total[5m]))

# P95 请求延迟(依赖 Histogram 分桶)
histogram_quantile(0.95,
  rate(http_request_duration_seconds_bucket[5m]))

# 节点 CPU 使用率(扣除 idle)
1 - avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m]))

两个坑必须提醒:Histogram 的分桶要在埋点端提前规划好,否则 histogram_quantile 算不出真实分位数;Counter 永远配 rate() 使用,直接对 Counter 做加减会得到被重启重置污染的错误结果。指标类型选错,PromQL 就会处处别扭。

指标保留与长期存储

默认 Prometheus 本地 TSDB 只保留 15 天,且单机容量有上限。生产环境建议把 retention 调到 30 天,关键指标再通过 remote_write 转存到长期存储(Thanos、Cortex 或 Grafana Mimir),既能降采样省钱,又能跨集群统一查询。示意配置如下:

# Prometheus 远程写(接入 Mimir 长期存储,示意)
remoteWrite:
- url: https://mimir.example.com/api/v1/push
  queue_config:
    max_samples_per_send: 2000
  write_relabel_configs:
  - source_labels: [__name__]
    regex: 'node_.*|kube_.*'
    action: keep

长期存储本身也应纳入前面的 Grafana 看板与告警体系,形成”采集 — 存储 — 可视化 — 告警”的完整闭环。监控不是一次性工程,而是随业务演进持续调参的能力。

监控体系的四个常见误区

搭好栈只是第一步,很多团队倒在”用”上。避开下面四个坑,监控才真正有用:

  • 只监控不告警:看板做得漂亮却没人盯,异常发生时一片静默,等于没监控。监控的终点是”该知道的人知道”。
  • 阈值拍脑袋:CPU 80% 一刀切,正常抖动也狂叫,久而久之告警被静音(告警疲劳)。阈值应基于历史基线,对核心服务用多档分级。
  • 指标基数爆炸:每个接口都打全维度 label,基数失控会把 TSDB 直接打挂。只保留真正用于聚合与下钻的标签。
  • 当一次性工程:业务变了规则没变,等出事才发现看板早失效。告警规则要随发布一起评审、一起进 Git。

小结

一套可落地的云原生监控 = Prometheus 抓数据 + Grafana 做可视化 + Alertmanager 管触达。先用 kube-prometheus-stack 快速起栈,再用 ServiceMonitor 接入业务指标,最后用 PromQL 把”异常”定义成告警规则。监控不是上线后的点缀,而是你敢在凌晨改生产、出了问题能 5 分钟定位的底气。

上一篇 Superset 实战:用开源 BI 搭建数据可视化看板
下一篇 程序员成长:从码农到资深工程师的实战路径
最新评论
Docker 网络模式详解:bridge/host 生产选型 - FSData
Docker 网络模式详解:bridge/host 生产选型 - FSData
8月20日
[…] 注意最后那条:把端口绑定到 127.0.0.1,再由宿主机上的 Nginx 反代进来,比直接 -p 80:80 暴露安全得多,也方便统一做
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
8月20日
[…] Pinia 的工程化用法,可以参考我们之前的实战文章 《Vue3 组合式 API + Pinia:状态管理从入门到实战》,那里覆盖了 Sto
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
8月19日
[…] 状态,点一下就能起停容器,配合我们讲过的 Docker Compose 编排 […]
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
8月19日
[…] 缓存三大坑的本质都是”缓存失效导致请求穿透到数据库”。记住口诀:穿透用布隆、击穿用锁、雪崩用错峰。配合合理的过期策略
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
8月19日
[…] Docker 镜像部署。结合我们之前写的 Docker Compose 一键编排实战,可以在 CI […]