1. 为什么要搭这套监控:三件套各管一摊,谁也替不了谁
先说个真实的场景。你在K8s集群里跑了一批应用,表面上Pod都是Running状态,但突然某天业务侧反馈接口变慢了。你登上节点一看,CPU快被打满,内存也告急,可是K8s自身的kubectl get pods根本看不出来问题——它只告诉你Pod活着,不告诉你Pod活得累不累。这就像体检报告只写"人还在",不写血压血脂,那要这体检报告有什么用。
所以K8s监控这件事,本质上要回答两个问题:集群里有什么,以及集群跑得怎么样。前者是资源对象的期望状态和实际状态,比如Deployment期望3个副本,实际是不是3个;后者是运行时资源的真实消耗,比如某个容器CPU用了多少、内存涨了多少。这两个问题恰好对应了kube-state-metrics和CAdvisor各自负责的领域,而Prometheus负责把这两类数据统一采集、存储、查询,再交给Grafana做可视化或接告警。
1.1 一套K8s集群里,到底需要监控什么
很多人上来就抓瞎,因为K8s的监控对象实在是多:集群层面有节点状态、控制平面组件,工作负载层面有Deployment、StatefulSet、Pod,资源层面有CPU、内存、磁盘、网络,事件层面还有各种Warning。如果眉毛胡子一把抓,要么Prometheus配置写得又臭又长,要么采集目标满天飞,到最后告警轰炸到没人看。
我一般会把监控对象分成三层来梳理:
- 集群基础设施层:节点的CPU、内存、磁盘、网络,kubelet自身状态,etcd、kube-apiserver等控制面组件。这层除了节点指标基本都归CAdvisor和kubelet管,控制面组件需要单独暴露指标端口。
- 工作负载状态层:Deployment的副本数是否达标、Pod是否处于Running状态、Job是否完成、Ingress服务是否被正确代理。这层是kube-state-metrics的核心价值区。
- 容器运行资源层:每个容器的CPU使用率、内存使用量、文件系统占用、网络收发字节数。这层是CAdvisor的主场。
注意第三层和第二层的区别:CAdvisor告诉你容器用了多少资源,kube-state-metrics告诉你Pod想跑几个、状态对不对。一个管"健康程度",一个管"期望一致性",两者缺一不可。
1.2 kube-state-metrics、CAdvisor、Prometheus的分工逻辑
可以用一个类比来记:K8s集群像一家公司,节点是办公室,Pod是工位上的员工,容器是员工正在干的活。
- CAdvisor是每个工位上装的监测仪,贴着员工测心率和耗氧量。它知道这个容器吃了多少CPU、多少内存,但它不知道公司的组织架构——它连你在这个项目里负责什么角色都不关心。
- kube-state-metrics是人力资源部的考勤专员,它不测你干了多少活,它只盯着花名册:这个部门编制是5个人,现在实际到了几个人?谁请假了?谁转岗了?这些数据来自K8s API Server里各种资源的实时状态。
- Prometheus是总部的数据中心,它定期从考勤专员和各工位的监测仪那儿收报表,统一存起来,供你随时查。
所以这三者不是重复造轮子,而是各管一段。CAdvisor藏在kubelet进程里,kube-state-metrics是一个独立的Deployment,Prometheus是调度中心。明白了这个分工,后面配置采集规则时就不会搞混。
1.3 先搞明白:哪些指标是"状态"、哪些指标是"资源"
这是新手最容易犯迷糊的地方。拿kube_node_status_condition和container_cpu_usage_seconds_total两个指标举例:
kube_node_status_condition表示节点的状态条件,比如Ready是True还是False,这属于状态指标,由kube-state-metrics产生,它描述的是"节点当前所处的状态是否符合预期"。container_cpu_usage_seconds_total表示容器的CPU累计使用秒数,这是资源指标,由CAdvisor产生,它描述的是"容器实际消耗了多少资源"。
前者用于回答"节点是不是准备好了",后者用于回答"这个容器是不是太吃CPU了"。一个是逻辑判断的依据,一个是容量规划的输入。后面配置PromQL查询和告警规则时,必须先分清楚你要查的是哪一类,否则组合出来的表达式含义会非常奇怪。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 部署前必须搞清的采集目标与环境准备
很多人拿着YAML直接往集群里一扔,结果要么ServiceMonitor抓不到,要么RBAC权限报错,要么Prometheus配置动态发现失败。其实这些问题九成都可以在部署前通过梳理采集目标来规避。
2.1 采集目标和访问端点梳理
假设你已经有一套K8s集群(不管是用kubeadm自建,还是用某发行版),部署前先在纸上画一个采集矩阵,把每个采集目标的访问方式和端口列清楚。最标准的做法是:
| 采集目标 | 数据源组件 | 端点 | 说明 |
|---|---|---|---|
| kube-state-metrics自身指标 | kube-state-metrics Deployment | :8080/metrics |
包含自身运行状态和暴露出的K8s对象指标 |
| kube-state-metrics的业务指标 | kube-state-metrics | :8080/metrics |
同一端点,但指标前缀是kube_* |
| kubelet内置CAdvisor指标 | kubelet | https://<node-ip>:10250/metrics/cadvisor |
需要kubelet的匿名认证或证书配置 |
| kubelet自身指标 | kubelet | https://<node-ip>:10250/metrics |
非CAdvisor,是kubelet进程自身的指标 |
| 节点资源指标 | 节点导出器(可选) | :9100/metrics |
如果你还想看宿主机指标,可另装node-exporter |
这里要特别提一句:CAdvisor并不是一个可以单独安装的Pod,它是kubelet的一个内置模块。所有节点的/metrics/cadvisor端点都是由kubelet对外提供的,因此采集CAdvisor指标,本质上就是采集kubelet暴露的指标端点。
如果你搭建集群时用了kubeadm,默认情况下kubelet已经把CAdvisor相关的指标收集功能打开了,你真正要关心的是Prometheus访问这个端点时是否被TLS认证拦住,这个问题后面专门讲。
2.2 命名空间规划
监控组件的命名空间,我建议单独开一个,比如monitoring,不要混进业务命名空间。原因很实际:
- 权限隔离:监控组件的RBAC只绑定在
monitoring命名空间,不会影响业务。 - 资源配额:监控组件属于基础架构,应该和业务资源配额分开管理。
- 清理便捷:如果哪天要重装监控体系,
kubectl delete namespace monitoring一键清场,不伤业务。
实测下来,很多人图省事把Prometheus部署到default命名空间,等到要清理或升级时各种扯皮,最后悔不当初。
2.3 镜像版本和兼容性
kube-state-metrics的版本和K8s版本有对应关系,别拿一个很老的版本去跑新集群,有的API字段已经废弃会导致权限报错或抓不到部分指标。在部署前建议去kube-state-metrics的官方发布页核对一下版本兼容表。
我常用的版本组合:
- K8s 1.26+:kube-state-metrics v2.10.x 或更新
- K8s 1.24~1.25:kube-state-metrics v2.7.x 或更新
- Prometheus:v2.45+(注意Prometheus 2.x和3.x对配置文件格式略有差异)
CAdvisor因为是内嵌在kubelet里的,不需要单独挑版本,跟着K8s版本走就行。但要注意的是,有些K8s发行版可能默认关闭了CAdvisor的部分指标,比如--containerd和--docker的运行时差异,这个后面说。
3. kube-state-metrics部署实操:从YAML到RBAC权限
kube-state-metrics部署本身不复杂,但涉及的文件不少。这里我不用Helm或者Operator,直接用手写YAML的方式带你过一遍,这样你能理解每个文件在干什么。
3.1 最小部署清单拆解
一个最小可运行的kube-state-metrics需要四件套:Deployment(跑主程序)、Service(提供内部访问)、ServiceAccount(跑起来要身份)、RBAC(允许它读API Server的资源状态)。
先看Deployment,核心配置:
yaml复制apiVersion: apps/v1
kind: Deployment
metadata:
name: kube-state-metrics
namespace: monitoring
spec:
selector:
matchLabels:
app.kubernetes.io/name: kube-state-metrics
replicas: 1
template:
metadata:
labels:
app.kubernetes.io/name: kube-state-metrics
spec:
serviceAccountName: kube-state-metrics
containers:
- name: kube-state-metrics
image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.10.1
ports:
- name: http-metrics
containerPort: 8080
- name: telemetry
containerPort: 8081
args:
- --resources=certificatesigningrequests,configmaps,cronjobs,daemonsets,deployments,endpoints,horizontalpodautoscalers,ingresses,jobs,limitranges,mutatingwebhookconfigurations,namespaces,networkpolicies,nodes,persistentvolumeclaims,persistentvolumes,poddisruptionbudgets,pods,replicasets,replicationcontrollers,resourcequotas,secrets,services,statefulsets,storageclasses,validatingwebhookconfigurations,volumeattachments
这里重点解释arg里的--resources参数。这个参数指定kube-state-metrics要监视哪些K8s资源对象。如果你不指定,默认会监视所有支持的对象,但那样会白白增加API Server的压力,而且会暴露很多你根本用不到的指标。我一般是做减法,按需配置。
3.2 RBAC权限:ServiceAccount、ClusterRole、ClusterRoleBinding
kube-state-metrics要正常工作,必须通过K8s API Server读取集群里所有命名空间的资源状态,所以它需要ClusterRole(集群级别权限),而不是只读某个命名空间的Role。
常用的RBAC清单如下:
yaml复制apiVersion: v1
kind: ServiceAccount
metadata:
name: kube-state-metrics
namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kube-state-metrics
rules:
- apiGroups: [""]
resources: ["configmaps", "secrets", "nodes", "pods", "services", "resourcequotas", "replicationcontrollers", "limitranges", "persistentvolumeclaims", "persistentvolumes", "namespaces", "endpoints"]
verbs: ["list", "watch"]
- apiGroups: ["apps"]
resources: ["statefulsets", "daemonsets", "deployments", "replicasets"]
verbs: ["list", "watch"]
- apiGroups: ["batch"]
resources: ["cronjobs", "jobs"]
verbs: ["list", "watch"]
- apiGroups: ["autoscaling"]
resources: ["horizontalpodautoscalers"]
verbs: ["list", "watch"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses", "networkpolicies"]
verbs: ["list", "watch"]
- apiGroups: ["policy"]
resources: ["poddisruptionbudgets"]
verbs: ["list", "watch"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses", "volumeattachments"]
verbs: ["list", "watch"]
- apiGroups: ["admissionregistration.k8s.io"]
resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"]
verbs: ["list", "watch"]
- apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests"]
verbs: ["list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kube-state-metrics
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kube-state-metrics
subjects:
- kind: ServiceAccount
name: kube-state-metrics
namespace: monitoring
这段配置我只给了list和watch两个动词,严格遵循最小权限原则。kube-state-metrics只需要监听资源变化,不需要创建、修改、删除任何对象。
注意: 如果你在--resources参数里加了某个资源,但ClusterRole里没有对应权限,kube-state-metrics启动后会在日志里反复报错,指标也不会生成。典型的报错就是热词里提到的kube-state-metrics cannot list resource ingress——原因就是networking.k8s.io组的ingresses没在ClusterRole里授权。这个我在第6章会专门展开讲排查思路。
3.3 直接访问验证
部署完成后,先别急着接Prometheus,直接用端口转发验证一下:
bash复制kubectl -n monitoring port-forward svc/kube-state-metrics 8080:8080
然后本地访问:
bash复制curl http://localhost:8080/metrics | head -n 30
你会看到一堆kube_*开头的指标,比如kube_deployment_status_replicas_available、kube_pod_status_phase、kube_node_status_condition。看到这些就说明kube-state-metrics已经成功从API Server读到了状态数据。
如果curl出来是空的,大概率是RBAC没配好,kube-state-metrics读不到数据。这时看Pod日志:
bash复制kubectl -n monitoring logs <kube-state-metrics-pod-name>
日志里会有msg="Failed to list *v1.Pod"之类的报错,跟着报错去补RBAC权限即可。
4. CAdvisor指标采集:不装二进制的内置采集器
CAdvisor的全称是Container Advisor,本来是Google开源的独立项目,后来直接以模块形式内置进了kubelet。所以你在节点上找不到单独的进程,但每个节点的kubelet 10250端口上,都挂着CAdvisor的指标端点。
4.1 CAdvisor在kubelet中的位置
kubelet启动时,会自动启动内部的CAdvisor模块,负责采集宿主机上所有容器的CPU、内存、文件系统、网络等指标。这些指标通过https://<node-ip>:10250/metrics/cadvisor暴露出来。
这里的关键问题是:Prometheus访问这个端点时需要认证,默认情况下kubelet的10250端口要求客户端提供证书,或者允许匿名访问(取决于kubelet配置)。很多人的Prometheus配好了Static配置,也加到了Target里,但抓取结果全是401 Unauthorized或403 Forbidden,就是这个原因。
解决办法有三种方向:
- 方案一:给Prometheus挂上kubelet的客户端证书,走双向TLS认证。这是最安全的做法,但需要在Prometheus的部署里挂载证书文件,运维成本稍高。
- 方案二:修改kubelet启动参数,增加
--anonymous-auth=true,同时用--authorization-mode=AlwaysAllow关闭鉴权。这个只在测试环境建议用,生产环境不推荐。 - 方案三:最常见的企业实践——让Prometheus以ServiceAccount的方式访问K8s API Server,通过TokenReview做认证。这要配合Prometheus Operator的组件来搞,比较复杂。
文本场景下,我建议用方案一(正规)或者方案二(快速验证)。正文是带读者动手为主,我先把方案二快速跑通,再给出方案一的进阶说明。
4.2 快速验证CAdvisor端点能通
在集群节点上执行:
bash复制curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://localhost:10250/metrics/cadvisor | head -n 20
如果你能看到container_cpu_usage_seconds_total、container_memory_usage_bytes这些指标,说明kubelet已经暴露了CAdvisor指标。注意-k跳过了证书校验,仅用于验证。
如果你连的是带认证的kubelet,记得用--cacert指定CA证书,或者把/etc/kubernetes/pki/ca.crt挂载到Prometheus容器里。
4.3 CAdvisor的指标特点
CAdvisor的指标前缀大多是container_*,也有machine_*(宿主机层)。常用的有:
container_cpu_usage_seconds_total:容器CPU累计使用秒数(Counter类型)container_memory_usage_bytes:容器内存使用量(Gauge类型)container_network_receive_bytes_total:容器网络接收累计字节数(Counter类型)container_network_transmit_bytes_total:容器网络发送累计字节数(Counter类型)container_fs_usage_bytes:容器文件系统使用量(Gauge类型)
一个典型的使用场景:想查某个Pod的CPU实时使用率,可以这样写PromQL:
promql复制rate(container_cpu_usage_seconds_total{namespace="default", pod="my-app-xxxxx"}[5m])
配合kube_pod_container_info还可以做很多维度过滤,比如只看某个Deployment下的Pod:
promql复制sum(rate(container_cpu_usage_seconds_total{namespace="default"}[5m])) by (pod)
5. Prometheus部署与采集配置:静态发现与权限配置
Prometheus的部署方式有很多,我建议从最简单的单机部署入手,把采集链路跑通,再考虑高可用和Operator化。
5.1 二选一:自己部署 vs Prometheus Operator
如果你的集群里还没有任何监控体系,直接裸部署一个Prometheus上来是最快的。等规模大了,再迁移到Prometheus Operator。
裸部署的核心组件就一个Deployment加一份配置文件。配置文件用ConfigMap挂载进去,内容大致如下:
yaml复制apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: monitoring
data:
prometheus.yml: |
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app]
regex: 'prometheus'
action: keep
但如果你追求自动化,那还是建议上Prometheus Operator。它会自动创建ServiceMonitor对象,你只需要定义一个ServiceMonitor声明要采集哪些Service,Prometheus Operator会自动生成采集配置。热词里出现了servicemonitor,说明很多人已经在用Operator方案了。
5.2 静态配置采集kube-state-metrics和CAdvisor
先假设你还是直接部署Prometheus,那么关键配置在scrape_configs。
采集kube-state-metrics:
yaml复制scrape_configs:
- job_name: 'kube-state-metrics'
static_configs:
- targets:
- 'kube-state-metrics.monitoring.svc:8080'
因为kube-state-metrics的Service在monitoring命名空间,所以DNS名称是kube-state-metrics.monitoring.svc。如果你把Prometheus部署在同一个命名空间,可以直接写kube-state-metrics:8080。
采集CAdvisor:
CAdvisor在每台节点上都有,所以最简单的办法是使用节点发现:
yaml复制- job_name: 'kubelet-cadvisor'
scheme: https
tls_config:
insecure_skip_verify: true
static_configs:
- targets:
- '10.0.0.11:10250'
- '10.0.0.12:10250'
metrics_path: /metrics/cadvisor
如果节点是动态扩缩容的,可以改成节点发现:
yaml复制- job_name: 'kubelet-cadvisor'
scheme: https
tls_config:
insecure_skip_verify: true
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:10250'
target_label: __address__
metrics_path: /metrics/cadvisor
这里insecure_skip_verify: true意味着跳过TLS证书校验,生产环境建议把CA证书挂进来,不要图省事。
5.3 验证Target是否正常
配置好以后,重启Prometheus或热加载配置:
bash复制kill -HUP <prometheus-pid>
然后打开Prometheus UI的Targets页面,你会看到kube-state-metrics和kubelet-cadvisor两个Target。状态是UP,说明采集链路已经通了。
如果状态是DOWN,大概率是网络不通、端口不对、认证失败这三大类。后面章节展开说。
6. 实战中踩过的坑:从endpoint down到权限炸裂
这部分是本文的精华。所有坑我都真实踩过,先讲现象,再讲排查链路,最后给修复方案。
6.1 kube-state-metrics的endpoint显示0/1 up:最常见的拉胯现场
现象:Prometheus Target面板里,kube-state-metrics这个Job显示down,点进去看错误是连接被拒绝。但kube-state-metrics的Pod看日志是一切正常,kubectl get svc也显示有Endpoint。
排查链路:
- 先确认Pod是否为Running状态:
kubectl -n monitoring get pods。如果Pod一直CrashLoopBackOff,看日志,大概率是RBAC没配好。 - 如果Pod正常,
kubectl -n monitoring get ep kube-state-metrics,看Endpoint有没有IP。如果显示无Endpoint,说明Service的selector没有匹配到Pod的label。 - 如果Endpoint有IP,但Prometheus仍然连不上,检查Prometheus部署所在的命名空间能否解析
kube-state-metrics.monitoring.svc这个DNS名。用kubectl exec进去ping一下,或者nslookup一下。
实际案例中,很多是因为Service的port名称写错了,或者Prometheus配置里target端口写成了8081(telemetry端口)而不是8080(http-metrics端口)。看起来是个小问题,但真能卡你一下午。
6.2 cannot list resource ingress:RBAC权限缺失的经典报错
如果你在kube-state-metrics的日志里看到:
code复制E0101 12:00:00.000000 1 reflector.go:147] k8s.io/client-go/tools/cache/reflector.go:229:
Failed to watch *v1.Ingress: failed to list *v1.Ingress: ingress.networking.k8s.io is forbidden:
User "system:serviceaccount:monitoring:kube-state-metrics" cannot list resource "ingresses" in API group "networking.k8s.io"
这就说明ClusterRole里缺少对networking.k8s.io组ingresses资源的list和watch权限。修复方法:在ClusterRole的rules里补上:
yaml复制- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["list", "watch"]
补完以后,重启kube-state-metrics Pod:
bash复制kubectl -n monitoring rollout restart deployment kube-state-metrics
这里有一个经验:好多人习惯在--resources参数里加了一堆资源,但RBAC配置没同步,导致一堆权限报错。记住一个原则:kube-state-metrics的--resources参数和RBAC rules必须一一对应,漏一个都不行。
6.3 抓不到CAdvisor指标:kubelet认证和TLS的坑
Prometheus配置好CAdvisor采集后,Targets显示DOWN,错误是server returned HTTP status 401 Unauthorized或403 Forbidden。
排查链路:
- 先用curl在节点上直接访问一次,确认kubelet本身是通的:
bash复制curl -k https://localhost:10250/metrics/cadvisor | head
如果能返回指标,说明kubelet没问题,问题出在Prometheus访问时的认证。
-
检查kubelet的启动参数。在
/var/lib/kubelet/config.yaml或/etc/kubernetes/kubelet.conf里看authentication和authorization部分。默认kubelet开启了Webhook鉴权模式,意味着它会把Prometheus的请求拿去做SubjectAccessReview。如果没有正确的ServiceAccount Token,就会403。 -
快速解法:在Prometheus的配置里加TLS配置和Token。下面是一个可以用的示例:
yaml复制- job_name: 'kubelet-cadvisor'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:10250'
target_label: __address__
metrics_path: /metrics/cadvisor
这里的bearer_token_file指向Prometheus Pod内挂载的ServiceAccount Token文件。只要这个ServiceAccount有权限做节点metrics的访问,就能通过kubelet的认证。
如果你用的Prometheus版本较老,可能不支持bearer_token_file,也可以用bearer_token直接塞Token进去,但不推荐,因为Token容易过期,还是ServiceAccount Token文件的方式更持久。
6.4 指标重复采集:kube-state-metrics和node-exporter的边界
有些人会在每个节点上再装一个node-exporter,然后又开了CAdvisor的machine_*指标,结果发现节点CPU指标出现了两份:一份来自node-exporter的node_cpu_seconds_total,一份来自CAdvisor的machine_cpu_cores。这不算故障,但会让人混乱,而且浪费存储。
我的建议是:节点层系统指标用node-exporter,容器层指标用CAdvisor。两者职责不重叠。如果你用达到的目的只是监控K8s集群和Pod,那可以完全不装node-exporter,CAdvisor的指标也够用;如果还要看宿主机层面的磁盘IO、网络带宽,node-exporter更全面。
7. 监控数据的实际用法:面板展示与个人系统对接
采集链路通了以后,手里全是指标,怎么展示是个问题。Grafana是标配,但很多人不知道kube-state-metrics的指标和CAdvisor的指标在Grafana里应该怎么组合着用。
7.1 一套立即可用的Grafana面板思路
Grafana官方社区有很多现成的仪表盘ID,但直接导入不一定匹配你的监控体系。我建议自己搭一个简单的,核心就三个面板:
- 集群节点状态面板:用
kube_node_status_condition{condition="Ready",status="true"}统计Ready节点数。 - 工作负载副本状态面板:用
kube_deployment_status_replicas_available / kube_deployment_spec_replicas计算Deployment的可用副本比例。 - Pod资源使用Top面板:用CAdvisor的
container_cpu_usage_seconds_total和container_memory_usage_bytes排序。
这里有个小技巧:kube-state-metrics的指标通常带namespace、pod、deployment这些标签,当你把它和CAdvisor的指标做联合查询时,必须用on(namespace, pod)或group_left做标签匹配。比如查某个Deployment下所有Pod的平均内存:
promql复制sum(
container_memory_usage_bytes{namespace="default"}
* on(namespace, pod) group_left(deployment)
kube_pod_info{namespace="default"}
) by (deployment)
这个PromQL第一次写会有点绕,但理解了on和group_left之后,你就可以自由组合状态指标和资源指标。
7.2 对接到个人系统的思路
如果你的需求是"prometheus监控部署 对接到个人系统",其实核心就是把Prometheus的Alertmanager或API接口暴露给外部系统。通常有两种方式:
- 方式一:Grafana的Webhook通知,把告警推到企业微信、钉钉、飞书或自己的系统。
- 方式二:直接调Prometheus的Alertmanager API,把告警事件POST到你的业务系统,由业务系统自己决定通知策略和工单流转。
Alertmanager的webhook配置示例:
yaml复制route:
receiver: 'custom-webhook'
receivers:
- name: 'custom-webhook'
webhook_configs:
- url: 'http://your-system.example.com/api/prometheus/alert'
send_resolved: true
提醒一下:webhook接收方必须支持POST JSON格式的数据,Alertmanager的字段说明可以参考官方文档,这里不展开,但对接时最容易踩的坑是字段名不匹配——Alertmanager把status、alerts、groupLabels这些字段嵌套在顶层,你的接收系统解析时要注意结构。
8. 部署顺序与日常维护的几条心得
最后分享几条我在实际项目中总结出的操作顺序和日常维护经验,按这个顺序做,能少踩很多坑。
8.1 我推荐的部署顺序
- 先部署kube-state-metrics,验证
kube_*指标能正常拉取。 - 再验证CAdvisor指标可以从kubelet上拉取。
- 然后部署Prometheus,把前面两个Target加到
scrape_configs。 - 调通后再部署Grafana,导入或手写仪表盘。
- 最后配Alertmanager和告警规则。
这个顺序好在哪里?每一步都有明确的验证点,不会出现全部部署好以后,不知道问题出在哪一环的窘境。
8.2 Prometheus存储和资源限制
Prometheus默认配置下,本地存储的保留时间是15天,但生产环境建议把--storage.tsdb.retention.time调长一点,同时配上--storage.tsdb.retention.size限制磁盘占用:
bash复制--storage.tsdb.retention.time=30d
--storage.tsdb.retention.size=20GB
这样既能保证有足够的历史数据进行排障,又不会把磁盘撑爆。
Prometheus容器本身建议设置resources.requests和resources.limits,我一般给2核CPU、4Gi内存起步。如果你的集群规模较大,要适当增加。不要裸奔,否则一旦指标量大,Prometheus容易OOM。
8.3 关于指标量级
kube-state-metrics和CAdvisor组合起来,指标数量很可观。一个20节点的集群,每天可能产生几千万条时间序列,这对存储和查询压力都不小。所以scrape_interval不要设太短,15秒足够,新建目标直接拉取所有指标可以,但长期运行建议在Prometheus里用metric_relabel_configs或Recording Rule做聚合,减少存储开销。
以container_cpu_usage_seconds_total为例,可以先把高频查询的CPU使用率预聚合:
yaml复制groups:
- name: container.rules
interval: 30s
rules:
- record: cluster:container_cpu_usage:rate5m
expr: sum by (namespace, pod) (rate(container_cpu_usage_seconds_total[5m]))
这样Grafana里直接查cluster:container_cpu_usage:rate5m,而不是每次实时计算全量指标,查询性能会好很多。
最后再分享一个小技巧
用这套体系跑一段时间后,你会发现kube-state-metrics产生的状态指标对日常运维帮助非常大。我最常用的一个查法是:把所有异常的Deployment副本状态一次性拉出来。
promql复制kube_deployment_status_replicas_available{namespace="default"}
- on(deployment, namespace)
kube_deployment_spec_replicas{namespace="default"}
结果不为0的,就是有副本没起来的Deployment,配合CAdvisor的container_restart_count和容器日志,通常能快速定位问题。这两个指标一个从状态层面发现问题,一个从资源层面定位症结,这就是K8s监控里"状态+资源"双轨思路最实用的落地场景。
