K8s集群跑起来之后,第一件事不是写业务,也不是调优,而是把监控体系搭好。没有监控的K8s集群就像没有仪表盘的飞机,表面上在飞,实际上你完全不知道引擎温度、油量、气压是什么状态。我见过太多人等到线上Pod OOM、节点磁盘写满、API Server响应变慢之后才开始慌慌张张查指标,结果发现连历史数据都没有,排障全靠猜。Prometheus + K8s这套组合,就是目前云原生监控的绝对主流,不管你是刚把K8s跑通,还是已经在生产环境运维了大半年,都需要搞清楚这套体系是怎么工作的。
这篇文章我不打算按官方文档照本宣科,而是从实战角度把Prometheus和K8s集成的完整链路拆开讲清楚:为什么选择Prometheus、采集链路是怎么运作的、部署时有哪些坑、告警规则应该怎么配、自定义业务指标怎么接进来。适合所有正在搭建或优化K8s监控体系的人参考。
1. Prometheus凭什么成为K8s监控的事实标准
先说一个很多人问过的问题:K8s监控方案那么多,Zabbix、Datadog、SkyWalking、VictoriaMetrics,为什么最后大家都用Prometheus?这背后不是简单的"社区选型从众",而是K8s本身的架构设计和Prometheus的拉取模型天然契合。
K8s集群里的监控对象有三个层次:基础设施层(节点CPU、内存、磁盘、网络)、平台层(API Server、kubelet、etcd、Scheduler)、业务层(Pod里的容器进程、自定义业务指标)。传统监控工具比如Zabbix需要在每台机器上装Agent,然后由Agent主动推数据到Server端,这种推模型在K8s这种容器频繁创建销毁、Pod IP随时变化的环境里非常别扭。而Prometheus采用的是拉取模型——由Prometheus Server主动去各个目标抓取指标,目标列表通过服务发现动态获取,根本不关心Pod的IP是否变化。
这个设计带来的好处很明显:
- 天然适配K8s的服务发现机制:Kubernetes本身就维护着所有Pod、Service、Node的API,Prometheus可以直接通过kubelet、APIServer获取目标,不需要额外维护一份静态主机清单。
- 指标抓取与存储解耦:被监控对象只需要暴露一个
/metrics接口,Prometheus会用HTTP协议周期性拉取,没有安装Agent的负担,也基本不侵入业务进程。 - 多维数据模型:Prometheus的指标名和标签(label)组合起来,能够灵活描述"哪个命名空间的哪个Pod在哪个节点上的什么指标",这种维度正是容器环境排障最需要的。
- PromQL查询语言:告警规则、Grafana图表、临时排查都靠它,语法表达力强,后面我会重点讲。
另外,K8s社区已经把Prometheus生态的各类Exporter当作基础组件来推广:node-exporter负责节点指标、kube-state-metrics负责K8s对象状态指标、cAdvisor(内置在kubelet里)负责容器运行指标。这些组件都是在K8s官方或CNCF项目里直接推荐的,整个生态已经完全围绕Prometheus的指标格式来构建。你几乎找不到一个K8s插件或中间件不提供Prometheus metrics接口,这就是事实标准的力量。
还有一个很多人忽略的点:Pull模型天然解决了监控系统的单点风险。如果某个被监控对象挂了,Prometheus会持续记录抓取失败的状态和数据缺失,事后排查时你能清楚看到"这个Pod在什么时间点开始失联"。如果是推模型,数据推不进来的时候你往往区分不清是网络问题、客户端挂了还是服务端处理不过来。这个细节在故障追责时特别重要。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 采集链路拆解:从节点指标到Pod指标到底是谁在干活
很多教程一上来就让你直接部署Prometheus,然后看到一堆target就以为完成了。但如果你不理解采集链路里每个组件到底负责什么,后面遇到数据缺失、指标含义不清的问题会很痛苦。我把这条链路上的关键角色逐个拆开说。
2.1 node-exporter:负责"机器"视角的指标
node-exporter是部署在每个K8s节点上(通常用DaemonSet)的指标采集器,监控对象是宿主机操作系统——CPU使用率、内存使用率、磁盘空间、磁盘IO、网络收发、文件系统状态等。它采集的数据大多来自Linux的/proc和/sys文件系统,所以不需要往内核里装额外的东西,权限也只需要挂载宿主机的一些只读路径。
以磁盘告警为例,node_filesystem_avail_bytes这个指标就是node-exporter提供的。你在Prometheus里看到的node_*前缀指标,基本都来自它。
2.2 kubelet内置的cAdvisor:负责"容器"视角的指标
cAdvisor是Google开源的容器资源监控工具,从K8s早期版本开始就集成在kubelet中,你不需要单独部署它。它负责采集节点上每个容器的CPU、内存、网络、文件系统使用情况,暴露在kubelet的/metrics/cadvisor端点。
这就是为什么K8s能"开箱即用"地看到每个Pod的CPU内存占用——kubectl top pod的底层数据来源就是cAdvisor。当你在Prometheus里查询container_cpu_usage_seconds_total、container_memory_working_set_bytes这类指标时,数据就来自这里。
这里有个关键点:很多对容器监控的误解来自不清楚cAdvisor和node-exporter的分工。node-exporter看到的是"这台机器还有多少内存",cAdvisor看到的是"这个容器用了多少内存"。告警阈值应该分开设计:节点内存不足时你可能要考虑驱逐Pod或扩节点,单个Pod内存持续上涨时你要找的是业务代码问题。
2.3 kube-state-metrics:负责"K8s对象状态"的指标
node-exporter和cAdvisor都是偏物理资源维度的,但K8s运维还需要知道集群里各种对象的状态:Deployment期望副本数是多少?实际Ready几个?Pod处于什么阶段(Running、Pending、Failed)?PVC状态是否正常?Job有没有成功跑完?这些信息来自K8s API,而不是操作系统。
kube-state-metrics做的事就是监听Kubernetes API,把Deployment、Pod、Service、PVC、HPA等对象的状态翻译成Prometheus指标。比如:
kube_deployment_status_replicas_available:Deployment当前可用副本数kube_pod_status_phase:Pod当前阶段kube_persistentvolumeclaim_status_phase:PVC状态(Bound/Lost/Pending)
这些指标是编写K8s平台告警(关于副本数、Pod重启、PVC容量等)的主要数据来源。很多人部署了Prometheus但pod相关告警发不出来,原因往往就是没有部署kube-state-metrics。
2.4 服务发现:Prometheus怎么知道该抓谁的指标
传统静态配置方式在K8s环境下根本不现实,因为Pod IP和数量随时在变。Prometheus支持多种服务发现机制,K8s集成中最常用的是kubernetes_sd_configs,通过访问Kubernetes API动态获取节点、Pod、Service、Endpoints列表。
这里有个核心概念需要理解:采集目标不等于采集指标。Prometheus通过服务发现拿到的是"要抓取的target列表",每个target上可能有多个metrics端点需要通过relabel规则来区分。
举个例子,kubelet本身暴露了多个metrics路径:/metrics(kubelet自身指标)、/metrics/cadvisor(cadvisor容器指标)、/metrics/probes(探针指标)。你不能把这三个路径都配成一个target,否则数据就乱了。常见做法是通过__metrics_path__这个标签来区分,这也是初学者在配置采集规则时最容易出错的地方。
relabel_config是Prometheus服务发现里最有威力的功能,它允许你在抓取前对target的标签进行增删改。比如把__meta_kubernetes_namespace映射成namespace标签、把__meta_kubernetes_pod_name映射成pod标签,这样在查询时就能按namespace和pod维度聚合。理解relabel是玩转K8s监控的一大门槛,后面我会给一个直接可用的配置示例。
2.5 指标生命周期:从Exporter到Prometheus再到告警
完整的链路是这样的:各种Exporter(node-exporter、kube-state-metrics、业务自定义Exporter)暴露/metrics端点,Prometheus根据服务发现规则找到这些端点,周期性抓取指标并按照指标名+标签集存储到TSDB(时序数据库)中,然后通过PromQL查询引擎响应Grafana图表和告警规则。
再往上一层,Alertmanager负责接收Prometheus推送过来的告警,经过分组、抑制、静默处理后,通过Webhook、邮件、钉钉、企业微信等渠道发出通知。
3. 从零部署:用Helm把Prometheus全家桶铺起来
部署Prometheus有两种主流方式:直接用Kubernetes原生资源手写ServiceMonitor和Deployment,或者用Helm Chart一
