资讯动态

K8s节点监控与告警实战:从指标采集到告警收敛的完整指南

发布时间:2026/9/9 4:55:38 来源:尧图企业网站定制
最近有个朋友问我他手上几十个节点的K8s集群总是出问题但节点一宕就是十几个小时没人发现等用户投诉了才知道事儿大了。其实这个场景很典型很多团队部署了K8s但“监控告警”只做到了一半——能看到图形却没有真正能兜底的告警能力。借着“K8s节点综合监控与告警分析报告”这个题目我把这一整套从指标采集、规则配置到告警收敛、报告整理的实践经验完整梳理了一遍。这套方案不管是五个节点的小集群还是几百个节点的大集群思路都通用。本文适合正在负责K8s集群运维、以及刚上手Prometheus监控体系的同学参考。我会把监控指标怎么选、告警规则怎么写、阈值怎么设不误报、以及遇到告警风暴怎么处理这些实战中很难一次搞对的东西全部摊开讲清楚顺便附上我踩坑之后验证过的配置片段和排查技巧。1. 监控体系整体设计与指标选型思路1.1 为什么K8s节点监控首选Prometheus生态到目前为止K8s监控几乎是Prometheus的事实标准。不是说Zabbix不行而是K8s本身的数据模型、服务发现机制、以及Pod频繁重建的特点和Prometheus的拉取式采集、标签化存储、动态服务发现配合得最自然。如果你用Zabbix去监控Pod级别的指标光处理Pod IP频繁变化就够你头疼的。而Prometheus配合kubernetes_sd_configs服务发现可以自动感知Node节点、Pod、Service、Endpoints的增减新节点加进来不需要手动加主机Prometheus自己就能发现并开始采集这对规模不断变化的K8s集群尤其重要。一个标准的K8s节点监控体系由四类组件组成Prometheus Server负责指标采集、存储、告警规则计算。node-exporter跑在每个节点上暴露节点自身的CPU、内存、磁盘、网络、文件系统等指标这是节点监控的核心数据来源。kube-state-metrics从Kubernetes API获取集群对象的状态比如Pod重启次数、节点Ready状态、PVC使用率等补充纯系统指标之外的K8s对象状态信息。Alertmanager负责接收Prometheus推送的告警完成分组、抑制、静默、路由最终通过钉钉、邮件、Webhook等渠道通知到人。之所以要拆分node-exporter和kube-state-metrics是因为两者采集的维度完全不同。node-exporter看到的是节点这个“物理/虚拟机”自身的资源使用状况比如CPU idle多少、内存还剩多少而kube-state-metrics看到的是Kubernetes对象层面的期望状态与实际状态比如某个节点是不是NotReady、某个Pod是不是反复重启。两者缺一不可。1.2 节点监控到底要盯哪些指标很多刚接触监控的同学喜欢什么指标都采Prometheus页面里加几百个告警规则最后结果是天天被告警轰炸真出了问题反而没人看。我的经验是节点层面的监控先抓这几类关键指标就够用CPU类节点CPU使用率、平均负载load1/load5/load15。内存类节点内存使用率、可用内存量。注意这里必须用node_memory_MemAvailable_bytes而不是简单的MemFree因为Linux内核的缓存回收机制会导致MemFree看起来很小但实际内存并不紧张。磁盘类根分区和重要挂载点的使用率、inode使用率、磁盘读写吞吐与IOPS、以及读写延迟。网络类网卡流量、丢包率、错误包数量。节点状态类节点是否Ready、kubelet是否健康、节点上的Pod数量是否过载。温度与硬件类如果物理机有条件node_hwmon_temp_celsius这类硬件传感器指标有助于提前发现硬件故障。在实际操作中我会把指标分成两层采集层和告警层。采集层数据全部保留用于后期排查问题、做容量规划告警层只摘出能明确反映“故障”或“即将故障”的指标。比如磁盘使用率超过90%就要告警但网络流量高不一定要告警——流量高是正常的业务特征只有出现丢包和错误包才说明有问题。1.3 指标保留周期与存储规划Prometheus默认本地存储的保留周期是15天数据多了会老化的很快。对于监控告警分析报告来说我建议至少保留30天这样能看出周同比、月环比趋势。修改方式是启动Prometheus时加--storage.tsdb.retention.time30d同时根据你的监控规模估算一下需要多少磁盘空间。我维护的集群规模在80个节点左右Prometheus每秒大约接收12万到15万个样本一个月的数据量大约占用260GB到300GB的本地盘。如果你把指标采集频率调成30秒或者接入了大量自定义业务指标这个数据量会更大。建议给Prometheus单独挂一块SSD盘读写性能对查询响应影响很明显特别是后面做监控报告、拉长时间范围查询的时候。2. 核心服务部署与关键配置解析2.1 node-exporter的部署方式与参数调优node-exporter官方推荐用DaemonSet方式部署保证每个节点上都跑一个Pod。这里有一个大家容易犯的错误直接用默认的node-exporter部署没做任何参数调整。实际上在较大规模的集群中建议加上这几个参数# node-exporter DaemonSet中的启动参数示例 args: - --path.rootfs/host - --no-collector.arp - --collector.filesystem.mount-points-exclude^/(dev|proc|sys|var/lib/docker/overlay2)/.* - --collector.filesystem.fs-types-exclude^(tmpfs|overlay|squashfs|autofs|iso9660|debugfs)$解释一下为什么这样调K8s节点上有很多虚拟文件系统、临时挂载点默认采集会带进来大量无用指标比如Docker的overlay2挂载层、tmpfs临时目录。这些指标不仅浪费存储还会在Grafana画图时产生大量噪声。用挂载点和文件系统类型的排除规则把这些过滤掉每个节点暴露的指标数量能减少30%以上Prometheus的采集压力也相应降低。很多人在部署node-exporter时会忽略--path.rootfs/host这个参数。它配合hostPath挂载宿主机根目录让node-exporter能从容器里正确读取根文件系统的磁盘使用情况。如果漏掉这一项你会看到磁盘容量指标严重失真——显示的是容器自身的文件系统数据而不是宿主机真实数据。2.2 Prometheus抓取配置中容易忽略的细节Prometheus采集node-exporter的配置相对基础但有几个坑值得注意scrape_configs: - job_name: kubernetes-nodes-exporter kubernetes_sd_configs: - role: node relabel_configs: - source_labels: [__address__] regex: (.*):10254 replacement: ${1}:9100 target_label: __address__ - source_labels: [__meta_kubernetes_node_name] target_label: node_name这里最关键的思路是Kib8s节点的Prometheus地址默认是kubelet的HTTPS端口不经过relabel的话Prometheus会去抓kubelet的10250端口而不是node-exporter的9100端口。上面的relabel规则把抓取地址从kubelet端口改写成了9100端口这样Prometheus就能直接拉到node-exporter的数据了。另一个常见问题是指标抓取超时。节点数量多、或者某些节点上运行了大量业务Pod时node-exporter的响应可能变慢。建议在scrape_config中设置scrape_timeout: 30s而不是默认的10s我遇到过采集超时导致部分节点指标在Grafana上出现断点的情况调大超时时间后就没有再出现了。2.3 kube-state-metrics补充集群状态视角如果你只监控节点的资源使用率那么“节点宕机”这种事可能要等到告警规则计算发现指标抓不到才能反映出来响应太慢。kube-state-metrics能直接从Kubernetes API拿到节点状态、Pod状态信息可以更快更直接地判断集群健康状况。部署kube-state-metrics时注意它本身也是以一个Deployment运行在集群内需要给它配置RBAC权限让它能读取nodes、pods、pvc、events等资源信息。这部分官方YAML里都有现成的直接kubectl apply就行。比较有价值的几个kube-state-metrics指标kube_node_status_condition节点状态条件能直接反映节点是否Ready、磁盘是否Pressure、内存是否Pressure、PID是否Pressure。kube_pod_container_status_restarts_total容器重启次数用于快速发现异常崩溃循环。kube_node_status_allocatable节点可分配资源总量偏差计算“真实还有多少可调度资源”很有用。3. 告警规则设计与阈值调参实战3.1 节点告警规则的分级设计原则告警规则不能一把抓我的习惯是把节点告警分为三个等级每个等级对应不同的通知方式和响应时效Critical紧急节点宕机、节点NotReady、kubelet停止响应、磁盘即将写满。这类问题必须立刻处理通知到全体值班人员。Warning警告资源使用率过高CPU、内存、磁盘达到阈值、网络错误包增多、文件系统inode耗尽风险。这类问题短时间内不影响业务但如果不处理会升级为Critical。Info提示节点Pod数量偏多、容器重启次数异常增加、节点温度偏高。这类问题需要关注但不一定立刻处理。分级的作用不只是决定通知谁更重要的是在告警风暴时做降噪处理。如果Critical告警已经触发了Warning级别的告警优先让路避免同一个节点同时推几十条消息把大家的手机震爆。3.2 阈值怎么设才不容易误报阈值设定是告警设计中最见功力的部分。设太松问题被掩盖设太紧狼来了效应让所有人都麻木。分享一组我在生产环境打磨过的初始阈值大家可以在这个基础上根据自己的业务特征调整告警项计算表达式PromQL阈值持续时间级别CPU使用率过高100 - (avg(rate(node_cpu_seconds_total{modeidle}[5m])) by (instance) * 100) 9010分钟WarningCPU使用率严重过高同上 955分钟Critical内存使用率过高(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 905分钟Warning根分区磁盘使用率(1 - (node_filesystem_avail_bytes{mountpoint/} / node_filesystem_size_bytes{mountpoint/})) * 100 8510分钟Warning根分区磁盘接近写满同上 923分钟Critical节点状态异常kube_node_status_condition{conditionReady,statustrue} ! 1-2分钟Critical节点可用内存过低node_memory_MemAvailable_bytes 2GB10分钟WarningCPU和内存的持续时间建议不要低于5分钟因为业务突刺很常见比如日志备份、定时任务运行都会造成几分钟的资源占用高峰但并不会影响业务没必要让值班人员半夜爬起来。磁盘类阈值在设的时候要考虑inode使用率这和磁盘空间同样重要。inode耗尽的表现是磁盘明明有空间但无法创建文件——比磁盘满还难排查。建议单独加一条规则node_filesystem_files_free{mountpoint/} / node_filesystem_files{mountpoint/}小于10%时告警。3.3 告警收敛与抑制避免告警风暴的必杀技整个K8s监控告警体系里Alertmanager的分组、抑制、静默这三个概念一定要花时间吃透。可以说告警风暴和安静运维之间的差别基本上就是这三项配置做得好不好。我遇到过最典型的场景一个节点宕机了上面的几十个Pod全部变成Pending或者Unknown同时kube-state-metrics对每个Pod都触发一条告警再加上节点本身的宕机告警一瞬间100多条告警涌入钉钉群。值班同学根本分不清优先级真正重要的“节点宕机”消息反而被淹没。解决办法是在Alertmanager里做分组和抑制route: group_by: [alertname, node_name] group_wait: 30s group_interval: 5m repeat_interval: 4h routes: - matchers: - severity Critical receiver: critical-webhook continue: true - matchers: - severity Warning receiver: warning-webhook inhibit_rules: - source_matchers: - severity Critical target_matchers: - severity Warning equal: [node_name]这段配置做了三件事第一按告警名和节点名分组同一个节点的多个告警合并成一条消息避免刷屏。第二group_wait: 30s表示一组新告警进来后等30秒再发这30秒内产生的同类告警可以合并repeat_interval: 4h表示同样的告警恢复前最多4小时重复通知一次不会每5分钟振一次手机。第三最关键的是inhibit_rules同一节点上已经触发Critical级别告警时抑制掉所有Warning级别的告警。因为节点都出问题了再报告CPU超过90%没有任何实际意义——重点是把最严重的故障暴露出来。3.4 搭建告警规则配置到生效的完整链路Prometheus告警配置分为两个文件Prometheus这边定义规则并发送给AlertmanagerAlertmanager负责分发通知。Prometheus的rule_files配置里加载告警规则文件rule_files: - /etc/prometheus/rules/*.yml规则文件的内容写在Prometheus配置目录下的node-alerts.yml中。Prometheus默认每15秒计算一次告警规则规则触发后状态进入pending持续超过设定的for时长后变为firing然后推送到Alertmanager。这套链路里经常出的问题有两个一是规则文件格式校验不过可以用promtool check rules命令预先检查二是规则计算压力大导致Prometheus响应慢建议按节点数拆分规则文件用多个rule_files并行加载。4. 告警分析、报告呈现与可视化落地4.1 从告警到根因日常分析报告怎么做有了监控和告警等于把眼睛装上了。但监控告警只是第一步真正有价值的是把断断续续的告警转变成有体系的周报、月报和故障复盘数据。我现在维护集群的习惯是每周导出一次综合监控报告格式就是“K8s节点综合监控与告警分析报告”里面包含几个固定板块告警趋势与Top N节点统计按告警条数、告警级别、告警类型聚合列出告警最多的前10个节点。这里能很快发现那些“老出问题”的节点——通常它们要么硬件有问题要么承载的业务负载超出了预期。资源水位变化与容量预测对比本周与上周各节点的CPU、内存、磁盘峰值和均值看是否有持续增长的趋势。磁盘增长尤其重要很多故障是可以提前一周预警的。如果某个节点磁盘使用率每周增长3%以上那就要提前规划扩容或清理。故障时长与影响面分析统计告警从触发到恢复的总时长以及期间受影响的Pod数量。这一项在月度复盘会上是最有说服力的数据。4.2 Grafana监控报告生成实战说到生成监控报告可能很多人第一反应是“我画几张图截图贴到文档里”。截图做一次两次可以长期做效率太低。成熟做法是使用Grafana自带的Report功能。前提是给Grafana安装grafana-image-renderer插件它负责把Grafana面板渲染成PNG图片。我用Docker方式部署Grafana时会单独把image-renderer跑成一个独立服务docker run -d --name grafana-image-renderer \ -p 8081:8081 \ grafana/grafana-image-renderer:latest然后在Grafana的配置文件grafana.ini中指定渲染服务的地址[rendering] server_url http://localhost:8081/render callback_url http://grafana:3000/配置好之后在Grafana的Report页面选择要导出的Dashboard模板、时间范围、收件人邮箱就能定时发送PDF格式的监控报告。我目前是配置每周一早上8点自动推送内容包括节点总览、关键资源使用趋势、Top 10高负载节点、告警分布统计。这个报告直接发给整个运维团队让每个人都对集群水位有个整体感知不等告警来才发现问题。4.3 Dashboard的指标组织与展示要点如果你要从零搭建K8s节点监控Dashboard我的建议是不要试图一张图里塞所有东西而是拆成几个视角节点总览、单节点详情、集群资源池视图。节点总览视图用Table类型展示所有节点实时状态每个节点一行列上显示CPU使用率、内存使用率、磁盘使用率、网络速率、节点状态按资源使用率排序。这样一眼就能看出哪个节点是“热点”哪些节点资源还有富余。单节点详情视图选择某个节点后展示该节点历史趋势图。这一步要找问题时非常有用——比如最近内存告警频繁点进节点详情能看到内存是哪天开始上涨的判断是业务增长还是内存泄漏。集群资源池视图更偏容量分析展示整个集群汇总的CPU总容量、已分配量、实际使用量的关系。这里推荐两个基础表达式集群CPU已分配百分比sum(kube_pod_container_resource_requests_cpu_cores) / sum(kube_node_status_allocatable_cpu_cores)集群CPU实际使用百分比sum(rate(node_cpu_seconds_total{mode!idle}[5m])) / sum(kube_node_status_allocatable_cpu_cores)这两个值一个代表“调度视角的资源压力”一个代表“运行视角的资源压力”。两者差距如果特别大分配率高但实际使用率低说明集群里存在大量申请资源但实际不怎么消耗的Pod可以考虑调整request值来提升调度密度。5. 常遇到的问题与排查心得5.1 采集端故障导致的告警失真这是我对所有做监控的人说的第一句话监控系统本身也是系统它也会出问题。如果Prometheus对某个节点连续采集失败某些阈值计算会变成NoData而NoData的告警行为和正常值触发完全不同很容易被忽略。比如Prometheus对节点采集中断那么基于node_cpu_seconds_total的CPU告警规则会变成“数据不足”Alertmanager默认不发送这类告警。也就是说节点已经宕机了你的监控反而安静了。针对这个盲区一定要单独配置一条探活告警- alert: NodeExporterDown expr: up{jobkubernetes-nodes-exporter} 0 for: 2m labels: severity: Critical annotations: summary: node-exporter采集失败{{ $labels.instance }}up是Prometheus内置的指标值为1表示最近一次抓取成功为0表示失败完全不依赖被你监控的节点本身是监控可用性的最后一道防线。5.2 告警配置生效了却不推送的排查流程有相当高的比例配置了告警规则后收不到消息这时大多数人第一反应是怀疑Webhook地址写错了。我的排查顺序基本是固定的第一步到Prometheus的Alerts页面看规则状态确认规则是否已经加载、当前是pending还是firing状态这能区分出问题出在Prometheus还是Alertmanager。第二步看Alertmanager的Web界面在Status页面能看到它是否已经接收到告警如果在Alertmanager里根本没有这个告警问题出在Prometheus推送环节如果接收到了但没有发出去问题出在路由匹配或receiver配置。第三步查看Alertmanager日志。绝大多数通知发不出去的问题都能在这里看到具体原因比如Webhook返回非200状态码、网络不通、或者认证失败。第四步如果走钉钉Webhook还要确认钉钉机器人的安全设置。钉钉自定义机器人有加签、关键字、IP白名单三种安全配置方式如果设置了加签而Alertmanager这边没有在URL中带上密钥参数消息就发不出来。我的配置里必须放在最后一步检查的就是这种“看起来都对了但就是不通知”的隐蔽问题。5.3 高基数指标导致Prometheus内存爆炸指标采集的指标量是有一个隐藏风险的我把话说得直白一点如果你的集群里有上百个节点又没有做任何指标过滤和降采样Prometheus内存占用会呈线性增长甚至更糟。我遇到过最极端的情况是Prometheus单实例内存占用超过12GB查询一个跨度稍微大一点的Dashboard就超时。罪魁祸首通常是两类一类是label值不断变化的指标比如Pod名中包含随机字符串另一类是暴露给Prometheus监听的某些业务指标本身携带大量唯一的label组合。解决办法有几个层面在node-exporter层面按前面说的排除掉不关心的文件系统和挂载点。在Prometheus抓取配置里用metric_relabel_configs丢弃不需要的指标和label比如__meta_kubernetes_pod_uid这种对监控分析无用但高基数的label。在存储层面给Prometheus加--storage.tsdb.min-block-duration、调整compact块大小等参数降低磁盘和内存压力。从实际效果看做好第一层和第二层过滤通常能把指标总量降一半Prometheus查询速度提升明显。5.4 告警恢复通知与值班交接的细节最后提一个很多团队忽略但影响体验的细节告警恢复通知。默认情况下Alertmanager只在告警触发时发送消息恢复时不会自动通知。这意味着值班人员收到一个告警后还需要自己去Grafana确认现在是不是已经恢复了非常不方便。Prometheus的每条告警规则都自带恢复逻辑——规则不再满足时自动结束告警。在Alertmanager的receiver中只要配置了相应的Webhook消息模板恢复通知就能自动发出。但注意恢复消息和触发消息要区分开否则值班人员分不清楚是新的故障还是旧的恢复了。我的做法是在消息模板里根据{{ .Status }}字段分别渲染文案firing显示“【故障触发】”resolved显示“【故障恢复】”这样钉钉上扫一眼就知道状态。再补充一点值班心得如果告警消息里能带上“当前值”和“阈值”对值班人员判断优先级很有帮助。比如“磁盘使用率当前94%阈值92%”和“磁盘使用率当前86%阈值85%”两个告警的紧急程度完全不同。配置告警规则时在annotations里把当前值和持续条件拼进消息文本这个工作量不大但实际价值很高。6. 实操中总结出的几条额外建议这个主题写到这里核心的监控搭建、告警设计、报告输出都讲完了。最后再加几个我在实际运维中沉淀下来的小经验不是重复是查漏补缺第一告警规则的版本管理要和集群配置一样重视。Prometheus的规则文件、Alertmanager的配置文件全部放进Git仓库每次修改走MR评审。尤其是多人协作时没有版本历史的告警配置就是一团乱麻——改过什么、谁改的、为什么改完全无从查起。第二告警规则的“反脆弱”要定期做。我每隔一个季度会专门做一次故障演练随机找一个节点执行kubectl drain、模拟磁盘写满、手动停掉kubelet服务然后看告警是否能按时触发、消息是否准确到达、值班人员是否能在规定时间内响应。只有真的演练过才知道配置有没有漏人对告警的敏感度也需要日常保持。第三监控告警报告不要只做给自己看。给业务团队看的报告和给运维团队看的报告数据维度应该完全不同。给业务的报告突出“可用性”“受影响时长”“资源余量”给运维的报告突出“根因”“改进项”“容量风险”。同一套数据不同的解读方式价值完全不同。第四Prometheus的远程存储要提前规划。本地存储的15天或者30天保留周期对于复盘几个月前的故障来说远远不够。我现在是把Prometheus的远程写接到时序数据库中当然这是一个大工程但如果你们的集群是要长期运维的核心系统建议在一开始就规划好这一层避免后面数据迁移的阵痛。从实际操作来看一套能真正兜底的K8s监控告警体系70%的工作量不在于搭建而在于规则打磨和告警治理。节点exporter装上去很简单但把阈值调准、把告警风暴压住、让报告真的能辅助决策是靠一轮一轮的告警响应和复盘堆出来的。希望这篇内容能让你少走一些我走过的弯路尤其是告警抑制和恢复通知这两块配置好了之后值班体验真的会提升一个数量级。

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

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

免费获取报价