cAdvisor —— 容器资源与性能采集器(cgroup → /metrics → Prometheus)
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
/targetsUP;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. 参考链接
- 主仓库:https://github.com/google/cadvisor
- 运行参数:https://github.com/google/cadvisor/blob/master/docs/runtime_options.md
- Prometheus 指标清单:https://github.com/google/cadvisor/blob/master/docs/storage/prometheus.md
- Web UI / REST API / 独立运行说明:https://github.com/google/cadvisor/blob/master/docs/web.md | https://github.com/google/cadvisor/blob/master/docs/api.md | https://github.com/google/cadvisor/blob/master/docs/running.md
- K8s DaemonSet 清单:https://github.com/google/cadvisor/tree/master/deploy/kubernetes
- K8s 系统组件指标(
/metrics/cadvisor现状与 RBAC):https://kubernetes.io/docs/concepts/cluster-administration/system-metrics/ - K8s 可观测性(指标管线):https://kubernetes.io/docs/concepts/cluster-administration/observability/
- Kubelet PSI 指标(
/metrics/cadvisor新增container_pressure_*):https://kubernetes.io/blog/2025/09/04/kubernetes-v1-34-introducing-psi-metrics-beta - Prometheus 配置 / Exporter 生态:https://prometheus.io/docs/operating/configuration/ | https://prometheus.io/docs/instrumenting/exporters/