cAdvisor —— 容器资源与性能采集器(cgroup → /metrics → Prometheus)

运维监控软件手册 06-容器与云原生监控 27.3 KB 原文

cAdvisor —— 容器资源与性能采集器(cgroup → /metrics → Prometheus)

分类:06 容器与云原生监控 适用:Docker / containerd / CRI-O 单机容器监控、K8s 每节点容器资源指标;每节点一个实例 一句话:读取 cgroup 与 /proc 暴露 container_* Prometheus 指标,是 K8s 容器资源指标的事实来源 官方:https://github.com/google/cadvisor 授权:Apache License 2.0(开源)

版本说明:官方镜像自 v0.53.0 起为 ghcr.io/google/cadvisor,更早为 gcr.io/cadvisor/cadvisor;版本/tag 一律写「以官方最新稳定版为准」。K8s 现状:kubelet 自 2015 年起内嵌 cAdvisor,v1.7 起把容器指标拆到独立 /metrics/cadvisor 端点,v1.12 移除了独立 cAdvisor Web UI 与 --cadvisor-port 参数,但内嵌 cAdvisor 仍在、指标仍由 /metrics/cadvisor 暴露;当前官方系统指标文档仍明确列出该端点。

1. 它解决什么问题

痛点 做法
docker stats 只有瞬时值、无法留存与集中 以 HTTP /metrics 持续暴露 container_* 指标,由 Prometheus 拉取入 TSDB
容器 CPU / 内存 / 磁盘 / 网络口径不统一 统一从 cgroup v1/v2 与 /proc 现读,按容器、Pod、机器维度打标签
不知道容器是否撞上 CPU quota 或内存 limit container_spec_*_limit/quota + container_cpu_cfs_throttled_*、container_memory_failcnt、OOM 事件
每节点自采脚本难维护 Go 单二进制 / 单容器,DaemonSet 批量部署,无需改业务镜像
K8s 里 Pod 资源用量无处查 kubelet 内嵌 cAdvisor 的 /metrics/cadvisor,Prometheus 按 node 自动发现
只想看容器,不想自己解析 cgroup 内置 Web UI(/)与版本化 REST API(/api/v1.3/...)直接可读

不适合:业务应用自定义指标(用 Prometheus client library);K8s 对象状态如副本数/Pod Phase(用 kube-state-metrics);kubectl top/HPA 所需的 Metrics API(用 metrics-server);主机硬件/OS 全局指标(用 node_exporter)。cAdvisor 自身不存储、不告警、不画图,这三者分别交给 Prometheus、Alertmanager、Grafana。

2. 核心概念与架构

术语 含义
cgroup v1 / v2 内核资源控制与统计数据源(/sys/fs/cgroup),CPU/内存/IO/网络/进程计数均来自此;v2 层级统一,PSI 指标需 v2
Container / cgroup path cAdvisor 按层级发现容器(继承 lmctfy 抽象),容器嵌套,指标带 id、name、image、pod、namespace、container 等标签
/metrics 默认 Prometheus 文本端点(可用 -prometheus_endpoint 改),一次抓取返回全部启用指标
-disable_metrics / -enable_metrics 按类别开关指标(cpu、memory、disk、diskIO、network、process、percpu、referenced_memory、resctrl…)
Housekeeping 周期性采集:全局发现新容器(默认 1m)、逐容器取 stats(默认 1s);动态间隔可降开销
REST API / Web UI /api/v1.3/containers/... 原始与聚合数据;/ 内置 Web UI;/healthz 健康检查
Kubelet 内嵌 K8s 节点上由 kubelet 内置 cAdvisor 提供 /metrics/cadvisor、/metrics/resource、/metrics/probes
Metrics API / metrics-server 聚合层 API,仅提供 kubectl top 与 HPA 所需 CPU/内存,不是完整监控管线
 Linux 内核(每台宿主机)            cAdvisor / kubelet :8080/:10250        Prometheus / 消费
┌──────────────────────┐  读取   ┌────────────────────────────┐  pull  ┌──────────────┐
│ /sys/fs/cgroup        │────────►│ 容器发现(cgroup 层级)      │ /metrics│  scrape      │
│  cpu.stat / memory.*  │         │  Housekeeping: 1s/容器      │────────►│ manager      │
│  blkio / net_cls      │         │  聚合: container_*/machine_* │        └──────┬───────┘
│ /proc/*/stat, /proc/net│────────►│  Web UI /  /api/v1.3/...    │               ▼
│ /dev/disk, docker.sock│         │  可选 storage_driver 推送   │     TSDB → Grafana /
└──────────────────────┘         └────────────────────────────┘     Alertmanager 告警

数据链路:cgroup 数据来源 → /metrics → Prometheus 抓取。cAdvisor 是无状态旁路进程,每次抓取现读内核数据;只在内存里保留很短历史(--storage_duration 默认 2m)用于 UI 曲线;持久化、阈值告警、可视化全部由外部承担。

K8s 中 kubelet 内置 cAdvisor 的现状(重点)

阶段 / 现状 说明
2015(K8s 1.6 前) cAdvisor 被集成进 kubelet,早期可用 --cadvisor-port=4194 开独立 Web UI
v1.7 kubelet /metrics 不再含 cAdvisor 指标,改由独立端点 /metrics/cadvisor 暴露
v1.12 移除 --cadvisor-port 与内嵌 cAdvisor Web UI;若需独立部署,用 DaemonSet(https://github.com/google/cadvisor/tree/master/deploy/kubernetes)
当前 kubelet 仍内嵌 cAdvisor,/metrics/cadvisor、/metrics/resource、/metrics/probes 由官方「系统组件指标」文档明确列出;Prometheus 直接抓 kubelet :10250(HTTPS + Bearer Token)或经 apiserver 代理 /api/v1/nodes/<node>/proxy/metrics/cadvisor
新版增补 cgroup v2 + KubeletPSI(v1.34 Beta / v1.36 GA)下 /metrics/cadvisor 额外暴露 container_pressure_* PSI 压力指标
只读端口 :10255 已废弃/关闭,勿再依赖;抓 :10250 并配 ServiceAccount RBAC

结论:K8s 集群通常不需要单独部署 cAdvisor,Prometheus 抓 kubelet 即可;独立 cAdvisor 主要用于裸 Docker / containerd 主机、需要 Web UI 或 kubelet 指标被裁剪的场景。

3. 安装与部署

3.1 环境准备

项 要求
内核 / cgroup / 端口 Linux,挂载 /sys/fs/cgroup(v1/v2 均可),运行时 Docker/containerd/CRI-O/Podman;独立实例默认 :8080,K8s kubelet 指标在 :10250 HTTPS
权限 / 必需只读挂载 官方快速上手用 --privileged + --device=/dev/kmsg(生产按第 10 章收紧);挂载 /:/rootfs:ro、/var/run:/var/run:ro、/sys:/sys:ro、/var/lib/docker/:/var/lib/docker:ro、/dev/disk/:/dev/disk:ro
运行时 socket / 资源 --docker=unix:///var/run/docker.sock(默认)、--podman=unix:///var/run/podman/podman.sock;Go 单进程,开销随容器数与 1s 采集频率增长
依赖 无外部数据库;Prometheus 抓取需网络可达 :8080 / :10250

3.2 多种安装方式

# 版本一律以官方最新稳定版为准
export CADVISOR_VER=<以官方最新稳定版为准>
# A. 官方 Docker 镜像(README 快速上手,裸 Docker 主机每机一个)
sudo docker run --volume=/:/rootfs:ro --volume=/var/run:/var/run:ro --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro --volume=/dev/disk/:/dev/disk:ro \
  --publish=8080:8080 --detach=true --name=cadvisor --privileged --device=/dev/kmsg \
  ghcr.io/google/cadvisor:${CADVISOR_VER}
# 注:v0.53.0 之前用 gcr.io/cadvisor/cadvisor:${CADVISOR_VER}
# B. 二进制 + systemd(物理机 / VM)
curl -fsSL -o /usr/local/bin/cadvisor <官方 Releases 资产 URL> && chmod +x /usr/local/bin/cadvisor
cat >/etc/systemd/system/cadvisor.service <<'EOF'
[Service]
Type=simple
ExecStart=/usr/local/bin/cadvisor --port=8080 --housekeeping_interval=5s --logtostderr
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload && systemctl enable --now cadvisor
# C. Docker Compose(单机调试)
# docker-compose.yaml —— tag 以官方最新稳定版为准
services:
  cadvisor:
    image: ghcr.io/google/cadvisor:${CADVISOR_VER}
    container_name: cadvisor
    privileged: true
    devices: ["/dev/kmsg"]
    volumes: ["/:/rootfs:ro", "/var/run:/var/run:ro", "/sys:/sys:ro", "/var/lib/docker/:/var/lib/docker:ro", "/dev/disk/:/dev/disk:ro"]
    ports: ["8080:8080"]
    restart: unless-stopped
docker compose up -d && docker compose ps
# D. K8s:优先抓 kubelet /metrics/cadvisor(见 4.4),无需部署;确需独立 DaemonSet 时用官方清单
kubectl apply -k github.com/google/cadvisor/deploy/kubernetes/<以官方目录为准>
kubectl -n cadvisor get ds,pod -o wide

⚠️ K8s 里独立部署 cAdvisor 时,旧版 kubelet 可能占用 hostPort 4194,需按官方 deploy/kubernetes 说明调整端口映射;且 DaemonSet 与 kubelet 内置指标会双份采集,注意去重与额外开销。

3.3 首次启动与验证

curl -sS -o /dev/null -w 'Web UI HTTP %{http_code}\n' http://localhost:8080/          # 预期 200
curl -sS http://localhost:8080/healthz                                                # 预期 ok
curl -sS http://localhost:8080/metrics | grep -m1 '^container_cpu_usage_seconds_total'  # 预期带标签样本行
curl -sS http://localhost:8080/api/v1.3/containers/ | head -c 300                     # 预期 JSON 容器树
curl -sS http://localhost:8080/metrics | grep -c '^container_'                        # 预期 > 0;浏览器 :8080 看 CPU/Memory/Network/Filesystem 子页

4. 配置文件详解

cAdvisor 没有主配置文件,全部通过命令行参数 / 环境变量(容器用 command:)配置;本节给出启动参数表与「独立部署 + Prometheus 抓取」的完整可运行最小示例。

4.1 启动参数关键项(来自官方 docs/runtime_options.md)

参数 默认值 说明
--port / --listen_ip / --prometheus_endpoint 8080 / 全部 IP / /metrics HTTP 监听与 Prometheus 暴露路径
--disable_metrics / --enable_metrics 空 按类别关/开指标(cpu、memory、disk、diskIO、network、process、percpu、tcp、udp、oom_event 等)
--housekeeping_interval / --global_housekeeping_interval / --max_housekeeping_interval / --allow_dynamic_housekeeping 1s / 1m0s / 1m0s / true 逐容器采集、全局发现间隔、动态间隔上限与开关
--docker_only / --raw_cgroup_prefix_whitelist / --disable_root_cgroup_stats false / 空 / false 只报容器 cgroup、白名单前缀例外、关闭根 cgroup 统计
--store_container_labels / --whitelisted_container_labels / --env_metadata_whitelist true / 空 / 空 容器 label 转指标标签开关与白名单、环境变量白名单(仅 containerd/docker)
--storage_duration / --storage_driver / --storage_driver_host 2m0s / 空 / localhost:8086 内存历史时长;可选推送 bigquery/elasticsearch/influxdb/kafka/redis/statsd/stdout,生产推荐不配,走 Prometheus 拉取
--http_auth_file / --http_digest_file / --http_auth_realm / --url_base_prefix / --profiling / --version 空 / 空 / localhost / / / false / false Web UI Basic/Digest 认证、反代前缀、pprof、打印版本
--docker / --podman unix:///var/run/docker.sock / unix:///var/run/podman/podman.sock 运行时 socket
--logtostderr / --v / --log_dir false / 0 / 空 日志输出与级别(glog)

4.2 完整可运行最小示例:独立部署命令

# 带常用调优参数的最小启动(对应 3.2 A,替换镜像 tag 即可运行)
docker run -d --name cadvisor -p 8080:8080 --privileged --device=/dev/kmsg \
  -v /:/rootfs:ro -v /var/run:/var/run:ro -v /sys:/sys:ro \
  -v /var/lib/docker/:/var/lib/docker:ro -v /dev/disk/:/dev/disk:ro \
  ghcr.io/google/cadvisor:${CADVISOR_VER} \
  --port=8080 --housekeeping_interval=5s --storage_duration=2m0s \
  --disable_metrics=percpu,tcp,udp,advtcp --logtostderr

4.3 完整可运行最小示例:Prometheus 抓取(裸 Docker 主机)

# prometheus.yml —— 抓独立 cAdvisor
scrape_configs:
  - job_name: cadvisor
    static_configs:
      - targets: ['<HOST1>:8080', '<HOST2>:8080']
    metrics_path: /metrics
    scrape_interval: 15s

4.4 完整可运行最小示例:K8s 抓 kubelet 内置 cAdvisor

# prometheus.yml —— K8s 场景,抓 kubelet :10250 的 /metrics/cadvisor(无需独立部署 cAdvisor)
scrape_configs:
  - job_name: kubernetes-cadvisor
    scheme: https
    metrics_path: /metrics/cadvisor
    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:
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)
# 所需 RBAC(官方系统指标文档最小形态,以集群版本官方文档为准)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata: { name: prometheus-cadvisor }
rules: [{ nonResourceURLs: ["/metrics", "/metrics/cadvisor"], verbs: ["get"] }]

也可经 apiserver 代理抓取:/api/v1/nodes/<node>/proxy/metrics/cadvisor(需相应 RBAC)。⚠️ 不要再依赖已废弃的 :10255 只读端口或 --cadvisor-port。

5. 核心使用方法

5.1 命令与查询集(编号 1~22 + 5.2 指标表)

# --- 部署与参数 ---
# 1) 官方镜像启动(完整挂载,见 4.2)
docker run -d --name cadvisor -p 8080:8080 --privileged --device=/dev/kmsg \
  -v /:/rootfs:ro -v /var/run:/var/run:ro -v /sys:/sys:ro \
  -v /var/lib/docker/:/var/lib/docker:ro -v /dev/disk/:/dev/disk:ro \
  ghcr.io/google/cadvisor:${CADVISOR_VER}
# 2) 版本 / 3) 改端口与采集间隔
/usr/local/bin/cadvisor --version
/usr/local/bin/cadvisor --port=9091 --housekeeping_interval=10s
# 4) 关闭高基数指标类别 / 5) 只保留容器 cgroup
/usr/local/bin/cadvisor --disable_metrics=percpu,tcp,udp,advtcp,resctrl
/usr/local/bin/cadvisor --docker_only --raw_cgroup_prefix_whitelist=/kubepods
# 6) 标签基数 / 7) 环境变量白名单
/usr/local/bin/cadvisor --store_container_labels=false --whitelisted_container_labels=app,env
/usr/local/bin/cadvisor --env_metadata_whitelist=APP_ENV,JAVA_OPTS
# 8) Podman socket / 9) Basic 认证 / 10) 反代前缀与 pprof
/usr/local/bin/cadvisor --podman=unix:///var/run/podman/podman.sock
/usr/local/bin/cadvisor --http_auth_file=/etc/cadvisor/htpasswd --http_auth_realm=cadvisor
/usr/local/bin/cadvisor --url_base_prefix=/cadvisor --profiling
# --- 端点验证 ---
# 11) Web UI / 健康检查 / 版本化 REST API
curl -sS -o /dev/null -w '%{http_code}\n' http://<HOST>:8080/
curl -sS http://<HOST>:8080/healthz
curl -sS http://<HOST>:8080/api/v1.3/containers/ | jq '.subcontainers[0].name'
# 12) 抓全量指标 / 只看 CPU / 只看内存
curl -sS http://<HOST>:8080/metrics > /tmp/cadvisor.metrics
grep '^container_cpu_usage_seconds_total' /tmp/cadvisor.metrics | head
grep '^container_memory_working_set_bytes' /tmp/cadvisor.metrics | head
# 13) 看机器级指标 / 指标类别数
grep '^machine_cpu_cores' /tmp/cadvisor.metrics
grep '^container_' /tmp/cadvisor.metrics | wc -l
# --- K8s 端点 ---
# 14) 直接查 kubelet(需 token,示例用 kubectl proxy 转发)
kubectl get --raw "/api/v1/nodes/<node>/proxy/metrics/cadvisor" | grep '^container_memory_working_set_bytes' | head
# 15) 另两个 kubelet 端点
kubectl get --raw "/api/v1/nodes/<node>/proxy/metrics/resource" | head
kubectl get --raw "/api/v1/nodes/<node>/proxy/metrics/probes" | head
# 16) 服务管理
systemctl status cadvisor && journalctl -u cadvisor -f
docker logs -f cadvisor 2>&1 | grep -iE 'error|failed'
# --- 常用 PromQL(在 Prometheus/Grafana 执行)---
# 17) 容器 CPU 使用率(核数)
sum by (name) (rate(container_cpu_usage_seconds_total{name!=""}[5m]))
# 18) CPU 节流占比(quota 撞限)
sum by (name) (rate(container_cpu_cfs_throttled_periods_total[5m])) / sum by (name) (rate(container_cpu_cfs_periods_total[5m]))
# 19) 内存工作集 / limit 使用率(排除无 limit 容器)
container_memory_working_set_bytes{name!=""} / (container_spec_memory_limit_bytes{name!=""} > 0)
# 20) 容器网络收发速率
sum by (name) (rate(container_network_receive_bytes_total[5m]))
sum by (name) (rate(container_network_transmit_bytes_total[5m]))
# 21) OOM 事件与最近存活
increase(container_oom_events_total[10m]) > 0
time() - container_last_seen > 120
# 22) 文件系统用量 / 丢包
container_fs_usage_bytes / container_fs_limit_bytes
sum by (name) (rate(container_network_receive_packets_dropped_total[5m]))

5.2 关键指标清单(官方 docs/storage/prometheus.md)

指标 类型 / 含义 典型用途
container_cpu_usage_seconds_total / _user_seconds_total / _system_seconds_total Counter,累计 CPU 秒 CPU 使用率、用户/内核态拆分
container_cpu_cfs_periods_total / _throttled_periods_total / _throttled_seconds_total Counter,CFS 周期/被节流周期/秒数 CPU 限额节流诊断
container_spec_cpu_quota / _period / _shares / container_spec_memory_limit_bytes / _reservation_limit_bytes Gauge,CPU/内存限额 计算可用量、节流分母与内存使用率;无 limit 时为 0
container_memory_usage_bytes / _working_set_bytes / _rss / _cache / _swap Gauge,内存口径 OOM 判断以 working_set 为准
container_memory_failcnt / container_memory_failures_total / container_oom_events_total Counter 触限与 OOM 告警
container_fs_usage_bytes / _limit_bytes / _reads_bytes_total / _writes_bytes_total Gauge / Counter 磁盘容量与 IO
container_network_receive/transmit_bytes_total / _packets_dropped_total / _errors_total Counter 网络吞吐与丢包
container_last_seen / container_start_time_seconds / container_tasks_state / container_processes / container_threads Gauge 存活、启停时间、进程状态
container_pressure_*_stalled/waiting_seconds_total(cgroup v2 + KubeletPSI) Counter CPU/内存/IO 压力停滞(PSI)
machine_cpu_cores / machine_memory_bytes / machine_cpu_physical_cores Gauge,机器级 容量上限与节点对比

container_* 标签常见 id(cgroup 路径)、name、image、container、pod、namespace、device、interface;K8s 场景以 pod/namespace/container 聚合,空 name 常是根/暂停容器,查询时注意过滤。

6. 告警与通知

cAdvisor 无内置告警,用 Prometheus container_* 规则 + Alertmanager 通知。注意 container_spec_memory_limit_bytes 可能为 0(无 limit),除法必须加 > 0 保护。

# prometheus/rules.yml —— 容器资源告警(limit 可能为 0,除法加 >0 保护)
groups:
  - name: container-resources
    rules:
      - { alert: ContainerMemoryNearLimit, expr: '(container_memory_working_set_bytes{name!=""} / (container_spec_memory_limit_bytes{name!=""} > 0)) > 0.85', for: 5m, labels: {severity: warning} }
      - { alert: ContainerCpuThrottled, expr: '(sum by (name) (rate(container_cpu_cfs_throttled_periods_total[5m])) / sum by (name) (rate(container_cpu_cfs_periods_total[5m]))) > 0.25', for: 10m, labels: {severity: warning} }
      - { alert: ContainerOOM, expr: 'increase(container_oom_events_total[10m]) > 0', for: 0m, labels: {severity: critical} }
      - { alert: ContainerFsNearFull, expr: '(container_fs_usage_bytes{name!=""} / (container_fs_limit_bytes{name!=""} > 0)) > 0.9', for: 10m, labels: {severity: warning} }
# alertmanager.yml —— 多通道通知 + 噪声抑制
route:
  group_by: [alertname, namespace, pod]
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: webhook-default
  routes:
    - { matchers: ['severity="critical"'], receiver: wechat-p0 }
receivers:
  - name: webhook-default
    webhook_configs:
      - url: http://<告警网关_HOST>:<PORT>/cadvisor/alarm   # 网关转发钉钉/飞书/邮件
  - name: wechat-p0
    webhook_configs:
      - url: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=<企业微信机器人key>
  - name: email-p2
    email_configs:
      - { to: <值班邮箱>, from: <发件邮箱>, smarthost: '<SMTP_HOST>:587', auth_username: <账号>, auth_password: <密码> }
inhibit_rules:
  - { source_matchers: ['severity="critical"'], target_matchers: ['severity="warning"'], equal: [namespace, pod] }
# 钉钉由告警网关按 Alertmanager JSON 渲染后转发
curl -sS -X POST 'https://<钉钉机器人Webhook URL>' -H 'Content-Type: application/json' -d '{"msgtype":"text","text":{"content":"容器告警:<alerts>"}}'

降噪:for 持续时长、group_by 按 namespace/pod 聚合、repeat_interval 重发间隔、inhibit_rules 抑制、按 severity 分级路由;滚动更新的瞬时抖动用 for 与 absent() 配合削掉。

7. 实战场景

7.1 接入一个 Java 服务并采集其容器指标

  • 目标:Java 服务容器化后,在 Prometheus 看到其 CPU/内存/网络指标。步骤:起 cAdvisor → 跑 Java 容器 → 配抓取 job → 造流量。
docker run -d --name cadvisor -p 8080:8080 --privileged --device=/dev/kmsg \
  -v /:/rootfs:ro -v /var/run:/var/run:ro -v /sys:/sys:ro \
  -v /var/lib/docker/:/var/lib/docker:ro -v /dev/disk/:/dev/disk:ro \
  ghcr.io/google/cadvisor:${CADVISOR_VER}
docker run -d --name order-java --memory=1g --cpus=1 -p 8081:8080 <Java业务镜像:tag>
# prometheus.yml 加 4.3 的 cadvisor job,reload 后查:
# sum by (name) (rate(container_cpu_usage_seconds_total{name=~".*order-java.*"}[5m]))
  • 验证:curl -sS http://<HOST>:8080/metrics | grep 'name="order-java"' 有样本;Prometheus /targets 中 cadvisor job 为 UP。
  • 回滚:停掉 Java 容器与 Prometheus 中该 job;cAdvisor 继续留着无副作用。⚠️ 设了 --memory/--cpus 才有 container_spec_*_limit_bytes,否则限额类 PromQL 分母为 0。

7.2 定位一次慢调用(CPU 节流 / 内存压力)

  • 目标:接口偶发变慢,判断是 CPU quota 撞限还是内存回收。步骤:看 CPU 节流率 → 看 working_set/limit → 看 OOM 与 PSI → 调整 limit。
# 1) 节流率(>0.25 说明 CPU 配额不足)
sum by (name) (rate(container_cpu_cfs_throttled_periods_total{name="<容器名>"}[5m]))
  / sum by (name) (rate(container_cpu_cfs_periods_total{name="<容器名>"}[5m]))
# 2) 内存工作集占限额比例
container_memory_working_set_bytes{name="<容器名>"} / (container_spec_memory_limit_bytes{name="<容器名>"} > 0)
# 3) OOM / failcnt / PSI 压力(cgroup v2)
increase(container_oom_events_total{name="<容器名>"}[30m])
container_memory_failcnt{name="<容器名>"}
container_pressure_cpu_stalled_seconds_total{container="<容器名>"}
# 4) 对照业务 P99 曲线,确认时段吻合;再调 --cpus / resources.limits
  • 验证:节流率或 working_set 尖峰与慢调用时段重合;提高 limit 后节流率下降、P99 回落。
  • 回滚:把 --cpus / resources.limits 调回原值并重启容器;⚠️ 调整 limits 会触发容器重建,先在非高峰执行。

7.3 单机 Docker 主机接入 Prometheus

  • 目标:一台裸 Docker 主机纳入监控。步骤:装 cAdvisor(4.2)→ 写 4.3 的 prometheus.yml → 热重载 → Grafana 导入容器仪表盘。
curl -X POST http://<PROM_HOST>:9090/-/reload      # 需 Prometheus 启用 --web.enable-lifecycle
curl -sS 'http://<PROM_HOST>:9090/api/v1/query?query=up{job="cadvisor"}'   # 预期 up=1
  • 验证:Prometheus /targets UP;container_cpu_usage_seconds_total 有该主机样本。
  • 回滚:从 scrape_configs 删除 cadvisor job 并 reload;⚠️ 不要直接删历史数据。

7.4 K8s 集群通过 kubelet 内置 cAdvisor 抓取

  • 目标:不部署额外组件,采集全集群 Pod 容器指标。步骤:配 4.4 的 RBAC 与 kubernetes_sd_configs(role: node)→ reload。
kubectl apply -f prometheus-rbac.yaml
kubectl get --raw "/api/v1/nodes/<node>/proxy/metrics/cadvisor" | grep -c '^container_'
curl -sS 'http://<PROM_HOST>:9090/api/v1/query?query=count(container_memory_working_set_bytes{pod!=""})'
  • 验证:/targets 中 kubernetes-cadvisor job 每个节点 UP,指标带 pod/namespace/container 标签。
  • 回滚:删除该 scrape job 与 ClusterRoleBinding 并 reload;⚠️ 不要误删 kubelet 自身 :10250 的健康探针路径。

8. 日常运维与故障排查

systemctl status cadvisor && journalctl -u cadvisor -f       # 服务管理 / 二进制日志
docker logs -f cadvisor 2>&1 | grep -iE 'error|failed'       # 容器日志
curl -sS http://<HOST>:8080/healthz                          # 健康检查
curl -sS http://<HOST>:8080/metrics | grep -c '^container_'  # 指标产出计数
curl -sS http://<HOST>:8080/api/v1.3/machine                  # 机器信息
kubectl -n <ns> get pod -l app=cadvisor -o wide               # K8s DaemonSet 状态
现象 原因 处置
/metrics 无 container_* 未挂 /sys、/rootfs 或权限不足 补齐 3.1 只读挂载;检查 --privileged / cgroup 命名空间
Web UI 有数据但无某容器 容器由非默认运行时管理 / --docker_only 过滤 配对应 socket;用 --raw_cgroup_prefix_whitelist 放行 cgroup 前缀
内存指标突然全为 0 cgroup v2 路径变化 / 内核升级后挂载点不同 确认 /sys/fs/cgroup 挂载与版本;升级 cAdvisor 到支持 v2 的版本
Prometheus 抓 kubelet 报 401/403 缺 ServiceAccount token 或 RBAC 配 bearer_token_file 与 nonResourceURLs: [/metrics,/metrics/cadvisor] 的 ClusterRole
抓 kubelet 报证书错误 节点证书 CN/SAN 不含 node IP 用 insecure_skip_verify: true(测试)或改 kubelet 服务证书 / relabel 用 hostname
指标基数暴涨、Prometheus 内存高 开了 percpu、tcp、udp 或把全部容器 label 转指标 --disable_metrics=percpu,tcp,udp,advtcp;--store_container_labels=false + 白名单
cAdvisor 自身 CPU 偏高 容器多 + 1s housekeeping 调大 --housekeeping_interval、--global_housekeeping_interval;保留 dynamic housekeeping
Web UI 曲线断断续续 --storage_duration 仅 2m 内存历史 曲线看 Prometheus/Grafana;cAdvisor 只做短历史预览
K8s 中指标重复两份 同时抓 kubelet 与独立 DaemonSet 去掉其中一个 job 或按标签去重

9. 性能、容量与高可用

维度 建议
采集开销 开销随容器数与采集频率增长;默认 1s/容器,容器数百时调到 5~15s,开 --allow_dynamic_housekeeping 让空闲容器降频
指标基数 默认禁掉 percpu、tcp、udp、advtcp、resctrl、referenced_memory 等高基数类别;--store_container_labels=false 并用 --whitelisted_container_labels 只留必要标签
存储容量估算 由 Prometheus 侧承担:序列数 ≈ 容器数 × 每容器指标数 × 标签组合数;日增量 ≈ 序列数 × (86400 / scrape_interval) × 样本字节。先小规模试跑 7 天,实测 TSDB 日增磁盘再外推,注意容器频繁重建导致序列流失(churn)
数据保留 cAdvisor 仅内存保留 --storage_duration=2m0s(UI 用);长期留存、降采样由 Prometheus --storage.tsdb.retention.time 或 Thanos/VictoriaMetrics 负责
高可用 本身无状态、每节点单实例即可;K8s 用 DaemonSet(或直接用 kubelet 内嵌,天然随节点存在);Prometheus 多副本抓取 + 远端存储实现采集侧 HA
自监控 用 up{job="cadvisor"}、scrape_duration_seconds、scrape_samples_scraped 监控抓取;container_last_seen 判断容器消失;cAdvisor 容器自身也出现在指标中
抓取节奏 15s 常规、30s 大规模;与 Prometheus scrape_interval 对齐,避免短于 housekeeping 造成重复读

10. 安全加固、备份与升级

项 做法
认证鉴权 / TLS cAdvisor 默认无认证;用 --http_auth_file / --http_digest_file 加 Basic/Digest,或置于 Nginx/Ingress 反代后加 SSO/TLS;--url_base_prefix 配子路径。K8s 抓 kubelet 用 ServiceAccount token + RBAC
网络暴露面 只让 Prometheus 网段访问 :8080;Web UI/REST API 与 /debug/pprof/ 不对外;K8s 用 NetworkPolicy 限制 :10250 来源。⚠️ /metrics 会泄露容器名、镜像、环境变量(若开了白名单)与资源用量
最小权限 官方示例用 --privileged,生产逐步收紧:优先 --device=/dev/kmsg + 只读挂载 + 必要 capability;避免写挂载;非 root 运行;--env_metadata_whitelist 只放非敏感变量
敏感数据 --store_container_labels=false 防止把含密钥的容器 label 变成指标标签;--env_metadata_whitelist 谨慎设置;关闭 --profiling
数据保留与备份 cAdvisor 无持久化数据可备份;备份对象是 Prometheus TSDB 快照与 prometheus.yml、rules.yml、DaemonSet/Compose 清单、systemd unit,全部入 Git
版本兼容 注意 cgroup v1 → v2 迁移:内核升级后 cgroup 挂载结构变化,需确认所用 cAdvisor 支持 v2(PSI 指标仅 v2);镜像仓库从 gcr.io/cadvisor/cadvisor 迁到 ghcr.io/google/cadvisor
升级与回滚 滚动替换 DaemonSet / 逐台重启容器 → 验证 /metrics 指标齐全与标签不变 → 观察 Prometheus 序列数;保留上一版镜像 tag。⚠️ 升级后若指标名/标签变化,Grafana 面板与告警规则需同步校验

11. 常见坑

# 现象 原因 解决
1 ⚠️ 容器起来后 /metrics 全空 漏挂 /sys、/rootfs 或权限不足 按官方 3.1 补齐 5 个只读挂载与 --privileged/--device=/dev/kmsg
2 ⚠️ 生产把 :8080 暴露公网 默认无认证,Web UI/REST/pprof 可读容器清单 内网隔离 + 反代鉴权;关闭 --profiling
3 内存使用率算出 +Inf 或告警误报 container_spec_memory_limit_bytes=0(无 limit) 表达式加 > 0 保护;K8s 里显式设 resources.limits.memory
4 CPU 节流率分母为 0 未设 CPU quota,container_cpu_cfs_periods_total 为 0 设 --cpus/resources.limits.cpu;查询过滤分母 > 0
5 指标基数暴涨、Prometheus OOM 开 percpu、把全部容器 label/env 转指标 --disable_metrics=percpu,tcp,udp;--store_container_labels=false + 白名单
6 cgroup v2 主机上部分指标消失 老版本 cAdvisor 或旧面板按 v1 路径写死 升级到支持 v2 的版本;核对指标名与标签;PSI 仅 v2
7 K8s 抓 /metrics/cadvisor 报 401/403 缺 token 或 RBAC / 用了废弃的 :10255 配 bearer_token_file + ClusterRole(nonResourceURLs: [/metrics,/metrics/cadvisor]);只用 :10250
8 ⚠️ 在 K8s 又部署 DaemonSet 又抓 kubelet 双份采集、序列翻倍 二选一:通常只抓 kubelet 内嵌端点
9 容器重建后 Grafana 面板断线 容器名/ID 变化导致序列 churn 用 pod/namespace/container 等稳定标签聚合,少用 id/name
10 UI 曲线只有 2 分钟 --storage_duration 仅内存短历史 长期趋势看 Prometheus/Grafana,不要指望 cAdvisor 存历史
11 独立 cAdvisor 在 K8s 起不来 旧 kubelet 占用 hostPort 4194 按官方 deploy/kubernetes 清单调整端口映射或改用 kubelet 端点

12. 速查表

项目 值 / 命令
分类 / 授权 06 容器与云原生监控 / Apache License 2.0
官网 / 仓库 https://github.com/google/cadvisor
镜像(v0.53.0+) ghcr.io/google/cadvisor:<版本>;更早 gcr.io/cadvisor/cadvisor
默认端口 / 路径 :8080;Web UI /、健康检查 /healthz
Prometheus 端点 /metrics(-prometheus_endpoint 可改)
REST API /api/v1.3/containers/、/api/v1.3/machine
K8s 端点 kubelet :10250(HTTPS)/metrics/cadvisor、/metrics/resource、/metrics/probes
官方启动挂载 /:/rootfs:ro、/var/run:/var/run:ro、/sys:/sys:ro、/var/lib/docker/:/var/lib/docker:ro、/dev/disk/:/dev/disk:ro
关键启动参数 / 标签控制 --port=8080、--housekeeping_interval=1s、--disable_metrics、--docker_only、--logtostderr;--store_container_labels=false + --whitelisted_container_labels
运行时 socket --docker=unix:///var/run/docker.sock、--podman=unix:///var/run/podman/podman.sock
关键 CPU / 内存指标 container_cpu_usage_seconds_total、container_cpu_cfs_throttled_periods_total / _periods_total;container_memory_working_set_bytes、container_spec_memory_limit_bytes、container_oom_events_total
关键磁盘/网络 / 机器级指标 container_fs_usage_bytes、container_network_receive/transmit_bytes_total;machine_cpu_cores、machine_memory_bytes
常用 PromQL rate(container_cpu_usage_seconds_total[5m])、节流率、working_set/limit
数据保留 cAdvisor --storage_duration=2m0s;长期由 Prometheus TSDB 负责
告警位置 Prometheus rules.yml + Alertmanager(cAdvisor 无内置告警)
高可用形态 每节点一个 DaemonSet / 直接用 kubelet 内嵌;无状态

13. 选型建议与同类对比

维度 cAdvisor kube-state-metrics metrics-server node_exporter
数据来源 cgroup / /proc(容器实际用量) Kubernetes API(对象期望/状态) kubelet Summary API 聚合 /proc、/sys(主机硬件/OS)
关注对象 容器/Pod CPU、内存、磁盘、网络用量 Deployment 副本数、Pod Phase、重启次数、资源 request/limit 节点与 Pod 的 CPU/内存当前值 主机 CPU、内存、磁盘、网络、文件系统
是否存储历史 / 主要消费者 否(仅 2m 内存)/ Prometheus、Grafana、告警 否 / Prometheus、Grafana、告警 否(内存窗口)/ kubectl top、HPA、VPA 否 / Prometheus、Grafana、告警
K8s 部署 通常不需单独部署(kubelet 内嵌) Deployment(全集群一个) Deployment(全集群一个) DaemonSet(每节点一个)
端点 :8080/metrics 或 kubelet /metrics/cadvisor :8080/metrics Metrics API(聚合层,非 /metrics) :9100/metrics
指标前缀 container_* / machine_* kube_* metrics.k8s.io API node_*

何时选 cAdvisor:需要容器/Pod 级真实资源用量、CPU 节流与 OOM 诊断、容器网络/磁盘 IO;裸 Docker/containerd 主机监控;K8s 里通过抓 kubelet /metrics/cadvisor 拿 Pod 用量。 何时不选:只要 kubectl top/HPA(用 metrics-server);只要对象状态与副本健康(用 kube-state-metrics);只要宿主机硬件/OS(用 node_exporter);要业务黄金指标或链路(用 APM / OTel);要开箱即用的存储与告警(cAdvisor 必须配 Prometheus 全家桶)。 组合建议:K8s 标准管线 = kubelet /metrics/cadvisor(用量)+ node_exporter(宿主机)+ kube-state-metrics(对象状态)+ kube-state-metrics/metrics-server 各司其职,统一进 Prometheus → Grafana → Alertmanager;四者指标前缀不同,不重叠也不互相替代。

14. 参考链接

cAdvisor —— 容器资源与性能采集器(cgroup → /metrics → Prometheus) - 知识库 - 起航社区