技术博客

Docker 监控体系:cAdvisor + Prometheus + Grafana 完整部署与核心指标

系统讲解 Docker 容器监控体系的完整搭建:cAdvisor 采集容器 CPU/内存/网络/磁盘 IO 指标原理、Prometheus 抓取配置与 Docker Daemon 指标启用、Grafana 仪表板配置(推荐 Dashboard ID)、核心告警规则(OOM/容器异常退出/资源使用率过高),以及生产环境的监控数据保留与存储优化方案。

Docker监控cAdvisorPrometheusGrafana告警生产运维

容器运行后,如何知道它是否健康、资源是否充足、哪个容器消耗最多 CPU?没有监控的容器等于盲飞。本文搭建以 cAdvisor + Prometheus + Grafana 为核心的 Docker 监控体系,这也是业界最主流的方案。

监控体系架构

数据采集层:
  cAdvisor          → 容器级指标(CPU/内存/网络/IO)
  node-exporter     → 宿主机级指标(磁盘/CPU/内存/网络)
  Docker Daemon     → Docker 引擎指标(镜像/容器/volume 数量)

数据存储层:
  Prometheus        → 时序数据库(抓取、存储、查询)

可视化/告警层:
  Grafana           → 仪表板(图形化展示)
  Alertmanager      → 告警路由(邮件/钉钉/Slack)

数据流向:
  cAdvisor ─┐
  node-exporter ─┤→ Prometheus → Grafana
  Docker Daemon ─┘      ↓
                    Alertmanager → 通知

一、cAdvisor 部署

cAdvisor(Container Advisor)是 Google 开源的容器指标采集器,通过读取 cgroup 和 /proc 获取每个容器的资源使用情况。

# docker-compose.yml(监控栈)

services:
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:v0.49.1
    container_name: cadvisor
    restart: unless-stopped
    privileged: true                         # 需要访问 cgroup 和设备信息
    ports:
      - "8080:8080"
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      - /dev/disk/:/dev/disk:ro
    devices:
      - /dev/kmsg
    command:
      - --housekeeping_interval=10s          # 采集间隔
      - --max_housekeeping_interval=15s
      - --event_storage_event_limit=default=0
      - --event_storage_age_limit=default=0
      - --disable_metrics=percpu,sched,tcp,udp,disk,diskIO,hugetlb,referenced_memory,cpu_topology,resctrl
      # 禁用不需要的指标,减少 Prometheus 存储压力
    networks:
      - monitoring

cAdvisor 核心指标:

# CPU 使用率(%)
rate(container_cpu_usage_seconds_total{name!=""}[5m]) * 100

# 内存使用量(字节)
container_memory_usage_bytes{name!=""}

# 内存使用率(%)
container_memory_usage_bytes{name!=""} / container_spec_memory_limit_bytes{name!=""} * 100

# 网络接收速率(bytes/s)
rate(container_network_receive_bytes_total{name!=""}[5m])

# 网络发送速率(bytes/s)
rate(container_network_transmit_bytes_total{name!=""}[5m])

# 磁盘读速率(bytes/s)
rate(container_fs_reads_bytes_total{name!=""}[5m])

# 磁盘写速率(bytes/s)
rate(container_fs_writes_bytes_total{name!=""}[5m])

# 容器重启次数
container_start_time_seconds{name!=""}

二、Docker Daemon 指标启用

Docker 19.03+ 支持直接暴露 Prometheus 指标。

// /etc/docker/daemon.json
{
  "metrics-addr": "0.0.0.0:9323",
  "experimental": true
}
systemctl restart docker

# 验证
curl http://localhost:9323/metrics | grep engine_daemon
# engine_daemon_container_states_containers{state="running"} 12
# engine_daemon_container_states_containers{state="stopped"} 3
# engine_daemon_image_actions_seconds_count{action="pull"} 47

Docker Daemon 核心指标:

# 运行中的容器数
engine_daemon_container_states_containers{state="running"}

# 停止的容器数
engine_daemon_container_states_containers{state="stopped"}

# 镜像总数
engine_daemon_images_total

# pull 操作耗时(p99)
histogram_quantile(0.99, rate(engine_daemon_image_actions_seconds_bucket{action="pull"}[5m]))

三、Prometheus 配置

# prometheus.yml

global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - /etc/prometheus/rules/*.yml

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['alertmanager:9093']

scrape_configs:
  # Prometheus 自身
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # cAdvisor — 容器指标
  - job_name: 'cadvisor'
    scrape_interval: 10s
    static_configs:
      - targets: ['cadvisor:8080']
    metric_relabel_configs:
      # 只保留有容器名的指标(过滤掉宿主机层的数据)
      - source_labels: [container_label_com_docker_compose_service]
        target_label: service
      # 丢弃无用标签,减少存储
      - regex: 'container_label_.*'
        action: labeldrop

  # node-exporter — 宿主机指标
  - job_name: 'node-exporter'
    static_configs:
      - targets: ['node-exporter:9100']

  # Docker Daemon 指标
  - job_name: 'docker-daemon'
    static_configs:
      - targets: ['172.17.0.1:9323']    # docker0 网关 IP
# docker-compose.yml(接上)
  prometheus:
    image: prom/prometheus:v2.54.0
    container_name: prometheus
    restart: unless-stopped
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./prometheus/rules:/etc/prometheus/rules:ro
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=30d'    # 保留 30 天数据
      - '--storage.tsdb.retention.size=20GB'   # 最多 20GB
      - '--web.enable-lifecycle'               # 允许热重载配置
    networks:
      - monitoring

  node-exporter:
    image: prom/node-exporter:v1.8.2
    container_name: node-exporter
    restart: unless-stopped
    network_mode: host                         # host 模式采集宿主机指标
    pid: host
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)'

四、Grafana 配置

# docker-compose.yml(接上)
  grafana:
    image: grafana/grafana:11.2.0
    container_name: grafana
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=Admin@123
      - GF_USERS_ALLOW_SIGN_UP=false
      - GF_SERVER_ROOT_URL=https://grafana.company.com
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    networks:
      - monitoring

volumes:
  prometheus_data:
  grafana_data:

networks:
  monitoring:
# grafana/provisioning/datasources/prometheus.yml
apiVersion: 1
datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
    editable: false

推荐 Grafana Dashboard(直接导入 ID):

Dashboard ID    名称                            说明
────────────────────────────────────────────────────────
193             Docker & System Dashboard        容器+宿主机综合视图
3662            Prometheus 2.0 Overview          Prometheus 自身监控
1860            Node Exporter Full               宿主机详细指标
14282           Docker Containers               容器资源对比
# 导入方式:Grafana UI → + → Import → 输入 Dashboard ID → Load

五、告警规则

# prometheus/rules/docker-alerts.yml
groups:
  - name: docker-container-alerts
    interval: 30s
    rules:

      # 容器 OOM 被杀(最高优先级)
      - alert: ContainerOOMKilled
        expr: |
          kube_pod_container_status_last_terminated_reason{reason="OOMKilled"} == 1
          OR
          container_oom_events_total > 0
        for: 0m                          # 立即告警
        labels:
          severity: critical
        annotations:
          summary: "容器 OOM 被杀:{{ $labels.name }}"
          description: "容器 {{ $labels.name }} 因内存超限被 OOM Kill,请检查内存使用情况"

      # 容器不断重启
      - alert: ContainerRestarting
        expr: |
          rate(container_start_time_seconds{name!=""}[15m]) > 0
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "容器频繁重启:{{ $labels.name }}"
          description: "容器 {{ $labels.name }} 在过去 15 分钟内频繁重启"

      # CPU 使用率超过 80%
      - alert: ContainerCpuHigh
        expr: |
          rate(container_cpu_usage_seconds_total{name!=""}[5m]) * 100 > 80
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "容器 CPU 使用率高:{{ $labels.name }}"
          description: "容器 {{ $labels.name }} CPU 使用率 {{ $value | printf \"%.1f\" }}%,持续 10 分钟"

      # 内存使用率超过 85%
      - alert: ContainerMemoryHigh
        expr: |
          container_memory_usage_bytes{name!=""}
          / container_spec_memory_limit_bytes{name!=""}
          * 100 > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "容器内存使用率高:{{ $labels.name }}"
          description: "容器 {{ $labels.name }} 内存使用率 {{ $value | printf \"%.1f\" }}%"

      # 容器停止运行
      - alert: ContainerDown
        expr: |
          absent(container_last_seen{name="nginx-prod"})
          OR
          (time() - container_last_seen{name="nginx-prod"}) > 60
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "关键容器停止:{{ $labels.name }}"

  - name: docker-host-alerts
    rules:
      # 宿主机磁盘使用率超过 85%
      - alert: HostDiskUsageHigh
        expr: |
          (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"})
          / node_filesystem_size_bytes{mountpoint="/"} * 100 > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "宿主机磁盘使用率高:{{ $value | printf \"%.1f\" }}%"

      # Docker 数据目录磁盘使用率
      - alert: DockerStorageLow
        expr: |
          (node_filesystem_size_bytes{mountpoint="/var/lib/docker"} - node_filesystem_free_bytes{mountpoint="/var/lib/docker"})
          / node_filesystem_size_bytes{mountpoint="/var/lib/docker"} * 100 > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Docker 存储空间不足,使用率 {{ $value | printf \"%.1f\" }}%"

六、Alertmanager 配置(钉钉告警)

# alertmanager/alertmanager.yml
global:
  resolve_timeout: 5m

route:
  group_by: ['alertname', 'instance']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'dingtalk'
  routes:
    - match:
        severity: critical
      receiver: 'dingtalk-critical'
      repeat_interval: 30m         # 严重告警每 30 分钟重复

receivers:
  - name: 'dingtalk'
    webhook_configs:
      - url: 'http://dingtalk-webhook:8060/dingtalk/ops_general/send'
        send_resolved: true

  - name: 'dingtalk-critical'
    webhook_configs:
      - url: 'http://dingtalk-webhook:8060/dingtalk/ops_critical/send'
        send_resolved: true

七、监控运维常用查询

# Top 5 CPU 消耗最高的容器
topk(5,
  rate(container_cpu_usage_seconds_total{name!=""}[5m]) * 100
)

# Top 5 内存消耗最高的容器
topk(5, container_memory_usage_bytes{name!=""})

# 容器网络流量排行
topk(5,
  rate(container_network_receive_bytes_total{name!=""}[5m])
  + rate(container_network_transmit_bytes_total{name!=""}[5m])
)

# 最近 1 小时内曾经重启过的容器
changes(container_start_time_seconds{name!=""}[1h]) > 0

# 容器资源使用率(CPU 超过 limit 的 70%)
rate(container_cpu_usage_seconds_total{name!=""}[5m])
/ (container_spec_cpu_quota{name!=""} / container_spec_cpu_period{name!=""})
* 100 > 70

# 内存接近 limit(超过 90%)
container_memory_usage_bytes{name!=""}
/ container_spec_memory_limit_bytes{name!=""} * 100 > 90

小结

Docker 监控三件套的职责分工:cAdvisor 负责从 cgroup 读取容器资源数据(每 10 秒),Prometheus 负责抓取和存储时序指标(保留 30 天),Grafana 负责可视化和告警展示。

生产中最重要的四个告警:OOM Kill(容器内存超限被杀)、容器频繁重启、CPU/内存使用率持续过高、磁盘空间不足。这四个问题如果没有监控,往往在造成业务中断后才被发现。