容器资源指标采集原理

在构建容器容量预警规则之前,必须深入理解指标数据的来源与采集机制。本章聚焦三个核心采集路径:cAdvisor 的容器级指标暴露、kubelet 内置的指标聚合端点,以及 Node Exporter 与容器指标的本质差异。只有厘清这些原理,才能设计出精准、无歧义的 PromQL 预警表达式。

3.1 cAdvisor 工作原理

cAdvisor(Container Advisor)是 Google 开源的容器资源使用分析工具,自 Kubernetes 1.2 起被直接集成到 kubelet 中。它通过读取 Linux cgroups 和 namespace 信息,实时采集每个容器的 CPU、内存、网络、磁盘 IO 等指标。

核心采集链路: cgroups 文件系统 → cAdvisor 轮询 → 指标聚合 → HTTP 端点暴露(/metrics 或 /api/v1.alpha1)

3.1.1 关键指标类型

资源类别 典型指标名(Prometheus 格式) 数据来源
CPU container_cpu_usage_seconds_total /sys/fs/cgroup/cpuacct/cpuacct.usage
内存 container_memory_working_set_bytes /sys/fs/cgroup/memory/memory.usage_in_bytes
网络 container_network_receive_bytes_total /proc/net/dev 按容器网络命名空间隔离
磁盘 IO container_fs_reads_bytes_total /sys/fs/cgroup/blkio/blkio.throttle.io_service_bytes
文件系统 container_fs_usage_bytes 容器镜像层与可写层 overlay 文件系统统计

3.1.2 采集周期与缓存

cAdvisor 默认以 10 秒 为间隔从 cgroups 读取原始计数器,并在内存中保留最近 2 分钟的历史样本。这意味着 Prometheus 拉取时获取的是瞬时快照,而非实时流。对于容量预警,建议使用 rate() 或 irate() 函数计算每秒变化率,以消除采样抖动。

注意: cAdvisor 暴露的 container_cpu_usage_seconds_total 是累计计数器,直接使用 avg() 聚合会得到错误结果。必须配合 rate() 或 increase() 函数使用。

3.2 kubelet 内置指标暴露

kubelet 作为 Kubernetes 节点代理,内置了 cAdvisor 实例,并通过以下两个端点对外暴露容器指标:

  • /metrics/cadvisor:直接透传 cAdvisor 的原始容器指标,包含完整的容器级标签(pod、namespace、container 等)。
  • /metrics/resource:Kubernetes 1.18+ 引入的优化端点,仅暴露 Pod 级别的资源指标(CPU、内存),减少标签基数,适合大规模集群。

Prometheus 通过 kubernetes_sd_configs 自动发现 kubelet 目标时,通常配置两个采集任务:

# 采集完整容器指标(用于详细诊断)
- job_name: 'kubelet-cadvisor'
  kubernetes_sd_configs:
    - role: node
  relabel_configs:
    - source_labels: [__meta_kubernetes_node_name]
      target_label: node
  metric_path: /metrics/cadvisor

# 采集精简资源指标(用于容量预警)
- job_name: 'kubelet-resource'
  kubernetes_sd_configs:
    - role: node
  metric_path: /metrics/resource
最佳实践: 容量预警场景优先使用 /metrics/resource 端点,其指标基数更低,Prometheus 内存占用更小;排查单个容器异常时再回退到 /metrics/cadvisor。

3.3 Node Exporter 与容器指标的差异

Node Exporter 是 Prometheus 生态中用于采集宿主机级别指标的组件。很多 SRE 新手会混淆 Node Exporter 指标与 cAdvisor 指标,导致预警规则误判。下表列出核心差异:

对比维度 Node Exporter cAdvisor / kubelet
采集范围 宿主机整体(所有进程共享) 单个容器或 Pod(cgroup 隔离)
CPU 指标 node_cpu_seconds_total(按 mode 分) container_cpu_usage_seconds_total(按容器分)
内存指标 node_memory_MemTotal_bytes / MemAvailable_bytes container_memory_working_set_bytes / container_memory_rss
网络指标 node_network_receive_bytes_total(宿主机网卡) container_network_receive_bytes_total(容器 veth 对)
磁盘指标 node_disk_io_time_seconds_total(物理磁盘) container_fs_io_time_seconds_total(容器文件系统)
适用场景 节点容量规划、硬件故障检测 容器资源限制、Pod 水平扩缩容、预警
常见误区: 不要用 node_memory_MemAvailable_bytes 判断容器内存是否充足。容器内存受 cgroup 限制和 page cache 共享影响,必须使用 container_memory_working_set_bytes 作为预警依据。

3.4 采集架构总览

下图展示了从容器运行时到 Prometheus 的完整指标采集链路:

容器资源指标采集架构 容器运行时 Docker / containerd / CRI-O Linux cgroups cpuacct / memory / blkio cAdvisor 轮询 /sys/fs/cgroup kubelet 内置 cAdvisor 实例 /metrics/cadvisor 完整容器指标 /metrics/resource Pod 级精简指标 Prometheus Server scrape /metrics/* 端点 关键说明 • cAdvisor 读取 cgroups • kubelet 封装两个端点 • Node Exporter 采集宿主机 • 容器预警用 resource 端点 • 诊断用 cadvisor 端点

3.5 Node Exporter 与容器指标的对比图

为了更直观地理解两者在内存指标上的差异,下图展示了同一台宿主机上 Node Exporter 和 cAdvisor 对内存视图的不同呈现:

Node Exporter vs cAdvisor:内存指标视图对比 Node Exporter 宿主机视图 node_memory_MemTotal_bytes(总物理内存) MemAvailable(可用内存) 已使用(含 page cache) page cache 可回收 → 无法区分哪个容器使用了多少内存 cAdvisor 容器视图 container_memory_working_set_bytes Pod A:container_memory_rss Pod B:container_memory_cache Pod C:container_memory_swap → 每个容器独立统计,支持 Pod 级别预警

3.6 采集原理对预警设计的影响

理解上述原理后,在设计容量预警规则时需注意以下要点:

  • 指标延迟: cAdvisor 采集周期为 10 秒,Prometheus 默认拉取间隔为 15 秒,预警评估窗口建议 ≥ 1 分钟,避免因采样错位产生误报。
  • 标签基数: /metrics/cadvisor 会为每个容器生成大量时间序列(每个容器约 50+ 指标),大规模集群建议使用 /metrics/resource 或通过 relabel 过滤非必要容器。
  • 计数器 vs 仪表盘: CPU 指标是计数器(counter),必须用 rate() 转换;内存指标是仪表盘(gauge),可直接聚合。
  • 容器重启影响: 容器重启后 cAdvisor 指标会重置,预警规则中应使用 rate() 配合 increase() 避免重启瞬间的尖刺。
核心结论: 容器容量预警的指标源应优先选择 kubelet 的 /metrics/resource 端点,配合 container_memory_working_set_bytes 和 rate(container_cpu_usage_seconds_total) 作为基础指标。Node Exporter 仅用于节点级别的容量规划,不可直接用于容器预警。