资讯动态

K8s监控基石:kube-prometheus-stack部署与指标采集全解析

发布时间:2026/10/13 5:34:55 来源:尧图企业网站定制
做 K8s 集群运维特别是公司内部已经有多个业务线在上面跑之后我最先意识到的问题不是“如何发布服务”而是“看不见集群里正在发生什么”。某个命名空间里的 Deployment 因为一次探活失败被不断重启节点磁盘使用率悄悄突破 90%业务高峰期 HPA 自动把副本从 2 扩到 20这些现象如果只能靠用户投诉和半夜响应来发现那排查成本会高得离谱。所以给 Kubernetes 补上可视化监控告警我把它放在了所有平台建设的前置位。整个体系的第一环就是先把 Prometheus 部署起来把指标采集链路打通只有数据进来了后面的 Grafana 面板、Alertmanager 通知才有意义。这篇内容面向的是已经能正常使用 K8s、但还没有成体系监控的团队。我会从部署前的思路、环境准备、具体安装步骤、核心配置拆解一直到常见问题的排查完整记录一次 kube-prometheus-stack 的落地过程。标题里的【1】不是套路这个系列我确实打算分几篇来写这一篇专心解决“采得到”的问题。1. 项目概述与部署前思考1.1 动态环境下的监控逻辑K8s 的调度逻辑决定了监控体系和传统服务器监控有本质区别。以前监控一台物理机只需要固定 IP、固定端口Agent 装好之后就是一个稳定目标但 K8s 里 Pod 随时可能被销毁、重建、漂移到另一台节点Service 的 Endpoint 列表也在实时变化。如果继续用“手工添加目标”的方式采集维护量会失控而且漏掉临时任务和单副本实例几乎是必然的。Prometheus 模型天然适配这种动态环境。它采用主动拉模式Pull监控服务只需要暴露一个 HTTP 的 /metrics 端点Prometheus 服务端会通过 Kubernetes API 的服务发现机制持续发现新的 Pod、Service、节点等目标并采集指标。你可以把它理解成一套“自动点名系统”不关心同学坐在哪个教室只要名单里能找到 TA 就行。更关键的是Prometheus 数据模型里每个指标都带有标签比如 Pod 名、命名空间、节点名都可以作为维度查询时能以任意维度做聚合和过滤这比传统监控的数值列表灵活得多。这也解释了为什么很多云原生监控方案都会围绕 Prometheus 来做它不只是一个监控软件更像是一套能被 K8s 原生管理的数据采集标准。我们不需要在每个 Pod 里装 Agent业务应用只要引入对应语言客户端或自己输出 Prometheus 格式指标即可成本低、接入也统一。1.2 选型用全套整合栈而不是零散组件确定用 Prometheus 之后紧接着是选择部署形态。我第一版只用 Helm 安装了单独的 Prometheus ServerServiceMonitor 和告警规则全靠手工维护结果业务隔三差五新增服务监控配置也跟着改很快就乱成一团。后来切到 kube-prometheus-stack才算是把这一块理顺。kube-prometheus-stack 本质上是一套预打包的监控解决方案核心由 Prometheus Operator 驱动。Operator 用 CRDCustomResourceDefinition把监控目标、告警规则、通知配置都抽象成了 K8s 资源。比如 ServiceMonitor 定义“采集哪些 Service”、PrometheusRule 定义“什么情况触发告警”、AlertmanagerConfig 定义“告警往哪里发”。我们提交这些 YAML 后Operator 负责把资源配置变成底层 Prometheus 实例的配置。这种声明式管理方式让监控配置和业务部署一样走 Git 流程可以 review、可以回滚。除了 Prometheus Operator这个 chart 还把 Grafana、Alertmanager、kube-state-metrics、node-exporter 都打包了。第一次部署时可能会觉得组件很多但实际运行起来会发现它们职责非常清晰Prometheus 管指标采集与存储Grafana 管展示Alertmanager 管告警分发kube-state-metrics 负责把 K8s 对象状态转换成指标node-exporter 负责暴露节点级指标。作为系列第一篇我建议不要只装一个裸 Prometheus而是直接装整套栈把后面可视化、告警需要的组件一次到位后面两篇文章就可以直奔主题不用再回过头补组件。2. 部署前环境准备2.1 版本清点与兼容性Prometheus Operator 依赖 Kubernetes API 的能力版本不匹配会直接导致 CRD 安装失败或者控制器报错。所以安装前我习惯先记录下当前集群版本和 Helm 版本kubectl version --short helm version如果你的 Kubernetes 是 1.26 或更高当前主流的 kube-prometheus-stack 版本基本都能兼容如果还在 1.20 以下就需要去 chart 的 README 里查看对应的支持矩阵。不要觉得版本检查很多余社区 issue 里最常见的一类问题就是把新版 chart 装到旧集群然后 operator 的日志里充满 unknown field。另外还需要确认当前 kubectl 权限是否可以创建命名空间、StatefulSet、CRD。有些团队里的账号是只读的装 chart 时一直卡在创建资源阶段还以为网络问题。可以先执行kubectl auth can-i create namespace来判断。2.2 持久化方案与存储类Prometheus 把时序数据写在本地磁盘所以存储是硬需求。对于单节点的测试环境可以用 emptyDir但 Pod 重启后数据就没了生产不可接受。K8s 里正确的做法是让每个 Prometheus 副本通过 PVCPersistentVolumeClaim挂一块独立存储这样即使 Pod 漂移数据也能跟着持久卷走。在部署前必须确认集群里有哪些 StorageClasskubectl get storageclass如果是空可以参考自己集群的存储方案比如本地磁盘可以部署 local-path-provisioner云环境通常自带 default 存储类。没有 StorageClass 也可以安装 chart但后续 PVC 会一直 Pending最终 Prometheus Pod 起不来。这个坑我踩过所以现在每次布置前都会先看一遍存储类。2.3 Helm仓库与命名空间用 Helm 管理监控栈最大的好处是升级、卸载干净。添加官方 chart 仓库和创建命名空间都可以用命令行完成helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update kubectl create namespace monitoring命名空间建议统一叫 monitoring方便后续配置网络策略和 RBAC。如果公司里有全局的 Helm 仓库缓存也可以直接用内部代理地址这个取决于你的网络环境。初次部署不建议在命名空间上玩花样越标准越好。2.4 资源规划与配额习惯kube-prometheus-stack 默认的资源请求其实不高但真实跑起来之后内存增长很快。一个中型集群约 200 个 Pod下Prometheus 单副本的内存很容易到 2Gi 以上如果还开了很多聚合查询4Gi 都不一定够。所以我不建议在资源紧张的小节点上直接安装。大致估算的话整套监控栈至少需要 3 个 CPU 和 4Gi 内存。其中Prometheus500m1000m CPU1Gi2Gi 内存Grafana200m500m CPU512Mi1Gi 内存Alertmanager100m300m CPU256Mi512Mi 内存node-exporter每个节点 100m CPU 和 150Mi 内存kube-state-metrics100m CPU 和 200Mi 内存建议给监控组件单独打一个 taint 节点或者至少设置单独的命名空间 ResourceQuota避免监控和业务抢资源。我见过不少集群因为监控和业务混在一起业务大促时 Prometheus 被 OOMKilled结果恰恰在最需要监控的时候监控挂了非常尴尬。3. Prometheus部署实操3.1 编写values.yaml这里开始进入实际部署。安装 kube-prometheus-stack 不用直接跑默认参数最好先准备自己的 values.yaml把存储、资源、访问方式固定下来。一个能跑起来的最小配置大概长这样# values-monitoring.yaml global: rbac: create: true prometheus: prometheusSpec: retention: 15d storageSpec: volumeClaimTemplate: spec: storageClassName: local-path accessModes: [ReadWriteOnce] resources: requests: storage: 50Gi grafana: adminPassword: admin persistence: enabled: true storageClassName: local-path size: 10Gi service: type: NodePort nodePort: 32001 alertmanager: alertmanagerSpec: storage: volumeClaimTemplate: spec: storageClassName: local-path resources: requests: storage: 10Gi prometheus-node-exporter: hostNetwork: true简单解释一下prometheus.prometheusSpec.retention设置数据保留 15 天storageSpec里的 PVC 指定使用 local-path 这个 StorageClassGrafana 开了持久化并映射到一个 NodePort 端口 32001方便临时访问Alertmanager 同理也有独立 PVC。prometheus-node-exporter.hostNetwork: true是为了让节点指标采集不走容器网络直接通过宿主机端口获取。这里要注意每个 StorageClass 名字必须和上面第2节确认的结果一致否则 PVC 创建不出来。还有如果不打算让 Grafana 用 NodePort也可以先不开 service 类型后面通过 port-forward 访问。3.2 安装命令与启动配置写好后执行安装helm upgrade --install prometheus prometheus-community/kube-prometheus-stack \ -n monitoring \ -f values-monitoring.yaml我习惯用 upgrade --install因为以后修改 values 再次执行就是更新不会破坏初次安装。如果安装成功命令会打印一段 NOTES提示 Grafana 的访问地址和 admin 密码。此时先不要急着关终端另外开一个窗口持续观察 Podkubectl get pods -n monitoring -w正常情况下能看到这些 Deployment/StatefulSet 逐步变成 Runningalertmanager-prometheus-k8s-0prometheus-k8s-0prometheus-operator-xxxgrafana-xxxnode-exporter-xxx每个节点一个kube-state-metrics-xxx如果你看到 prometheus-k8s-0 一直处于 1/2 Running不要慌这通常是它的第二容器 config-reloader 还没就绪等一会儿即可。真正要关注的是 CrashLoopBackOff 或者 Pending这两个说明有配置或资源问题后面第 5 节再展开。3.3 访问Prometheus验证采集Pod 起来了链路有没有通还另说。第一步验证可以先看 Prometheus 自身的 Web UIkubectl port-forward svc/prometheus-operated 9090:9090 -n monitoring打开浏览器访问 localhost:9090进入 Status - Targets。这里就是 Prometheus 自动发现到的所有采集目标正常情况会有几十个 target状态为 UP。如果大部分是 DOWN不要继续做后面的事情了先解决采集失败问题。在 Targets 页面里点任何一个 target都能看到具体报错比如 connection refused、context deadline exceeded 等排查方向很直接。接着在 Graph 页执行一条最简单的查询up返回结果应该是一系列时间序列每个 values 是 1 或 0。1 代表该目标最近一次采集成功。如果某个指标为 0结合 Targets 页面看它为什么失败。3.4 接入一个业务ServiceMonitor示例kube-prometheus-stack 自带的是系统组件监控业务应用不会自动出现在 Targets 里。把业务接进来的标准姿势是创建 ServiceMonitor。比如业务应用 demo-app 已经通过 Service 暴露了 8080 端口端口名是 metrics且 /metrics 接口返回 Prometheus 格式指标然后创建下面这个资源apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: demo-app-sm namespace: demo labels: release: prometheus spec: selector: matchLabels: app: demo-app endpoints: - port: metrics interval: 30s创建之后Prometheus 会在下一个 reconcile 周期自动发现它并开始采集。这个例子最关键的细节是metadata.labels.release: prometheus。因为我们安装 chart 时设置的 release 名字叫 prometheus默认创建的 Prometheus 会要求 ServiceMonitor 一定要带这个 label才能完成关联。很多人接了业务半天没数据查到最后就是少了这个 label。到这里Prometheus 部署和基本采集链路已经通了。可视化告警里“可视化”前置条件也就有了数据来源后面可以放心配置 Grafana 和 Alertmanager。4. 核心配置拆解与访问方式4.1 资源限制与数据保留第一次安装能跑不代表配置能适合生产。我一般会花两天时间观察 Prometheus 的内存和磁盘趋势再回头调整 values。至少需要关注三个参数prometheus.prometheusSpec.resources.requests给调度器一个基础保障值低于这个值不调度。prometheus.prometheusSpec.resources.limits给容器设置内存上限防止 OOM 把节点打挂。prometheus.prometheusSpec.retention/retentionSize控制数据保留长度。举一个实际配置示例prometheus: prometheusSpec: retentionSize: 40Gi resources: requests: cpu: 500m memory: 1Gi limits: cpu: 1000m memory: 3GiretentionSize配合 PVC 容量使用比较合理比如 PVC 50Gi数据保存 40Gi 就触发清理留出压缩和 WAL 的余量。如果只用retention: 15d面对突然大量指标也可能把磁盘打满所以我更推荐按体积限制。4.2 存储与PVC检查安装后记得检查 PVC 状态kubectl get pvc -n monitoring正常情况下所有 PVC 都是 Bound。如果你发现 Prometheus 的 PVC 一直 Pending大概率是 StorageClass 名不对或没有对应的 Provisioner。另外PVC 一旦被 StatefulSet 使用storageClassName就不能直接修改了因为它属于不可变字段。要换存储类只能先把 Prometheus StatefulSet 删除再把 PVC 删掉最后用新 values 重建。这个过程会导致已有的监控数据丢失所以部署前一定要确认存储方案。另一个和存储相关的细节是如果你用本地存储类的 ReadWriteOncePrometheus 那个 Pod 会固定在某台节点上这是设计使然。不要试图在单副本模式下让它“漂移”除非底层存储支持 ReadWriteMany。4.3 Ingress暴露与Grafana访问NodePort 用于临时验证还可以但生产环境更推荐通过 Ingress 暴露并加一层认证。如果集群里已经有 nginx-ingress可以在 values 里开启 Grafana Ingressgrafana: ingress: enabled: true ingressClassName: nginx hosts: - grafana.example.local path: /注意Ingress 需要正确设置host然后在本地 hosts 文件或 DNS 里解析到 Ingress Controller 的地址。否则即使 Ingress 创建成功也只是空路由。开启 Ingress 之后建议关闭 NodePort 服务避免安全组把端口暴露到公网。Prometheus 和 Alertmanager 同样可以配置 Ingress不过它们的 Web UI 通常不对普通开发开放建议保持在集群内访问需要时用 kubectl port-forward 或临时 NodePort。4.4 Alertmanager告警通道占位既然系列标题是“监控告警”Alertmanager 也必须先就位。chart 默认创建了一个 Alertmanager 实例但它的 receiver 是 null也就是说告警只产生不会发到任何地方。我不想把整篇的重点扯到告警配置上但这里先留个伏笔——后面写告警规则和通知渠道时会专门讲。就部署阶段而言我们只需要确认 Alertmanager 能正常启动并且可以在Status - Cluster Status页面看到它自身的状态。之后我们创建 PrometheusRule 时告警会经过 Alertmanager 按路由规则分发这一步先让组件存在后续留到系列第二篇再填接收器。5. 常见问题与排查实录5.1 Pod Pending与PVC绑定失败症状是 prometheus-k8s-0 一直 Pending事件里出现persistentvolumeclaim prometheus-prometheus-k8s-db-prometheus-k8s-0 not found或者waiting for a volume to be created。排查命令kubectl describe pod prometheus-k8s-0 -n monitoring kubectl get pvc -n monitoring如果 PVC 处于 Pending就去查 StorageClass 是否存在以及 Provisioner 是否正常。有时候是 local-path-provisioner 没装也有时候是云盘资源不够导致卷创建超时。不解决存储问题Prometheus 是永远起不来的。5.2 镜像Pull失败症状是 Pod 状态 ImagePullBackOffkubectl describe 里可以看到 Failed to pull image。最直接的原因就是当前节点无法访问镜像仓库或者镜像 tag 不对。在受控环境里建议把镜像提前导入节点或者在 values 中覆盖 image repository 和 tag指定为内网镜像仓库地址。例如prometheus: prometheusSpec: image: repository: registry.internal/prometheus tag: v2.54.1这里要注意不要指定latest否则 config-reloader 对比镜像版本时会因为 tag 相同而无法感知更新出现“配置变了但镜像不更新”的诡异问题。固定 tag 是生产常识。5.3 时区与Grafana显示问题监控数据的时间戳大多以 UTC 存储展示层如果按 GMT就会比本地时间早 8 小时。Grafana 页面右上角可以临时切换时区但默认还是 UTC。如果希望一打开就是你本地时间可以在 values 里设置容器环境变量grafana: env: TZ: Asia/ShanghaiPrometheus 本身不需要改时区因为它的数据时间本来就是 UTC epochs。很多新手非要把 Prometheus 容器内的时区改成北京时间完全没有必要反而会增加和其他查询系统对齐时间的复杂度。5.4 数据采集到了Grafana却一片空白这个问题的典型场景是Prometheus Targets 里能看到业务指标Grafana 的数据源也能连通但某个 Dashboard 大盘全是“No data”。排查思路从数据源和变量入手检查 Grafana 数据源 URL 是否写成了http://prometheus-operated:9090注意端口是 9090不是 80。检查 Dashboard 的 job 名与 Prometheus 中的 target 标签是否一致。如果 dashboard 期望 jobkubernetes-pods但你的 ServiceMonitor 没有设置 jobLabel序列的 job 就会默认为 ServiceMonitor 名。检查 Dashboard 用的指标名称是否已经改名。常见的是老版本 node-exporter 指标和 1.25 版本的指标命名有差异很多第三方大盘没有及时更新。遇到这种情况最好的方法是在 Grafana 的 Explore 页面手动查询{job...}看一眼标签是否正确再反推到 Dashboard 变量。5.5 高可用多副本的坑有人一上来就把 Prometheus 副本数调成 2结果两个副本都启动失败。原因是 Prometheus Operator 创建的 StatefulSet 会用不同的 PVC 名称如果存储类不支持多副本同名卷、或者节点亲和性不一致就会导致其中一个副本起不来。另外Alertmanager 多副本需要开启集群模式涉及流量复制等配置也不是加个 replica 就行。普通规模集群完全没必要一开始就上多副本。先把单副本的数据链路跑稳后续如果量大了优先考虑远端存储方案而不是单纯加副本。5.6 日常排查命令速查最后整理一组高频命令方便出了状况快速定位# 查看监控命名空间内所有Pod状态 kubectl get pods -n monitoring -o wide # 查看Prometheus StatefulSet详情 kubectl describe statefulset prometheus-k8s -n monitoring # 查看Prometheus配置是否被Operator同步 kubectl get prometheus prometheus-k8s -n monitoring -o yaml # 查看ServiceMonitor关联关系 kubectl get servicemonitor -n monitoring # 看Prometheus日志 kubectl logs prometheus-k8s-0 -c prometheus -n monitoring用这些命令基本能覆盖 90% 的启动或采集问题。真正卡住时不要凭感觉改配置先看事件和日志再回头检查 values。写到这里Prometheus 在 K8s 里的部署闭环已经完整了。我个人最大的体会是部署本身并不难难的是把“监控目标发现、数据采集、持久化、访问入口”这几条线一次理顺。很多人装完 Prometheus 后还是发现监控不可用往往不是 chart 的问题而是缺少对整个采集链路的目标感。如果你也是第一次做这件事建议按这样的顺序验证先看 Pod 都 Running再看 Targets 都 UP接着用 PromQL 查几条指标最后再看 Grafana 有没有图形。每一步都确认过了再进入下一步才不会把问题留给后面的告警阶段。下一篇我会继续整理告警规则的写法以及 Alertmanager 如何接入真实通知渠道到时候会给出可以直接套用的 PrometheusRule 示例。部署阶段留下的这些基础配置如果能固化成模板后面再搭建新的监控环境基本上就是复制粘贴和改个存储类名字的事。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑