根本原因是prometheus高频拉取/metrics/cadvisor导致cadvisor频繁遍历容器和读取cgroup,引发大量系统调用、内核态cpu(%sy/%si)飙升;验证需检查cadvisor/kubelet线程cpu占用及scrape_interval是否≤10s;缓解措施包括将采集间隔调至30s–45s、超时增至15s、禁用cadvisor独立端口、关闭housekeeping,或改用/kubelet/metrics/resource等轻量接口。

这个问题本质是采集节奏与内核资源承载能力不匹配,核心矛盾在于:Prometheus高频拉取 /metrics/cadvisor 接口,触发 cAdvisor 频繁遍历容器状态、读取 cgroup 文件,导致大量系统调用和内核态时间堆积,表现为 sys 或 %si CPU 占用异常升高,但业务容器实际负载并不高。
确认是否为 cAdvisor 拉取过密所致
先做快速验证,避免误判:
- 在 Worker 节点上执行
top -H或pidstat -u 1,观察是否有cadvisor进程或kubelet线程持续占用高%sy(system)CPU - 检查 Prometheus 的
scrape_configs中对应kubelet-cadvisorjob 的scrape_interval—— 若设为10s或更短(如5s),就是典型诱因 - 在节点本地用
curl -s http://localhost:10250/metrics/cadvisor | head -n 20测试单次响应耗时,若常超 1s,说明 cAdvisor 生成指标已吃力
调整采集频率与超时参数
这是最直接有效的缓解手段。Kubernetes 官方推荐的 cadvisor 采集间隔是 30s,而非越密越好:
- 将 Prometheus 中
kubelet-cadvisorjob 的scrape_interval从10s改为30s或45s - 同步把
scrape_timeout从默认10s提升至15s,避免因瞬时延迟触发重试放大压力 - 若使用 Prometheus Operator,修改对应的
ServiceMonitor资源中的interval和timeout字段
限制 cAdvisor 自身资源消耗
cAdvisor 默认会监控所有容器和子系统,但在大规模集群中可精简:
- 为 kubelet 启动参数添加
--cadvisor-port=0(禁用独立端口),强制走/metrics/cadvisor统一入口,减少监听开销 - 通过
--no-housekeeping关闭内部周期性清理逻辑(适用于稳定环境) - 若仅需 CPU/内存基础指标,可在 kubelet 启动时加
--v=2降低日志级别,减少 I/O 压力
绕过 cAdvisor,改用更轻量的指标源
对 CPU 使用率等关键指标,cAdvisor 并非唯一选择:
- 直接采集 kubelet 暴露的
/metrics/resource(Kubernetes 1.21+),该接口只返回节点级资源用量,无容器粒度但极轻量 - 在 Pod 级别,优先使用
container_cpu_usage_seconds_total这类原始 counter 指标,而非依赖 cAdvisor 计算的衍生值 - 对于历史遗留必须用 cadvisor 的场景,考虑在 Prometheus 层用
rate()聚合降频,而不是靠高频抓取保“实时”
不复杂但容易忽略:内核态 CPU 飙升往往不是 bug,而是配置节奏压垮了采集链路的自然反馈。调松一点间隔,系统反而更稳。











