cAdvisor (container advisor) — демон, который собирает метрики контейнеров и отдаёт их в формате Prometheus. Он читает cgroups, считает процессор, память, сеть и файловые системы для каждого контейнера, а рядом публикует простой веб-интерфейс для быстрой проверки. В связке с Prometheus и Grafana это самый доступный способ увидеть, что происходит внутри Docker-хоста, не строя собственный агент. Ниже — запуск, конфигурация scrape, рабочие запросы и диагностика типичных сбоев.
Что именно собирает cAdvisor
Демон работает на хосте и видит все контейнеры локального движка. Данные берутся из cgroups и каталогов runtime, поэтому контейнеру нужны примонтированные в режиме чтения корень системы, /sys, сокет и хранилище Docker. Метрики отдаются по адресу /metrics, проверка живости — по /healthz, список контейнеров — в веб-интерфейсе на порту 8080.
cAdvisor не заменяет node_exporter. Он отвечает за контейнерный уровень, а состояние дисков, температуры, загрузки ядра и сетевых интерфейсов хоста даёт node_exporter. В Grafana эти два источника дополняют друг друга: один показывает, что делает контейнер, второй — хватает ли ему ресурсов машины.
Запуск в Docker
Для проверки достаточно одного контейнера. Все каталоги монтируются только для чтения, а устройство /dev/kmsg нужно для событий ядра. Запускать с --privileged не нужно: современным версиям хватает перечисленных томов.
docker run -d --name=cadvisor --restart=unless-stopped \
-p 8080:8080 \
-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 \
--device=/dev/kmsg \
gcr.io/cadvisor/cadvisor:latest
После старта проверьте три вещи: контейнер не перезапускается, /healthz отвечает, а в /metrics есть строки container_. Если последнее не выполняется, почти всегда виноват неверный путь к хранилищу Docker или отсутствие доступа к сокету.
docker ps --filter name=cadvisor
curl -s http://localhost:8080/healthz
curl -s http://localhost:8080/metrics | grep -c '^container_'
curl -s http://localhost:8080/api/v1.3/containers | head -c 300
Подключение к Prometheus
Prometheus опрашивает cAdvisor как обычную цель. Интервал в 15–30 секунд достаточен: чаще собирать имеет смысл только при отладке, иначе растут нагрузка и размер базы. Если cAdvisor слушает только локальный адрес, публикуйте порт на конкретном интерфейсе, а не на всех сразу.
scrape_configs:
- job_name: cadvisor
scrape_interval: 15s
static_configs:
- targets: ['10.0.0.5:8080']
metric_relabel_configs:
- action: labeldrop
regex: id
Удаление метки id заметно сокращает число временных рядов: идентификатор контейнера уникален при каждом перезапуске, и без очистки база растёт быстрее, чем хотелось бы. Метки name и image при этом остаются, так что графики не ломаются. Не удаляйте name без причины: именно по ней строятся почти все запросы.
Docker Compose
Постоянная установка удобнее описывается файлом. Явно задайте интервал опроса и режим только Docker: на хостах с другими движками это убирает лишние цели и снижает нагрузку.
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
restart: unless-stopped
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:/dev/kmsg
command:
- --housekeeping_interval=15s
- --docker_only=true
Проверка конфигурации занимает секунду: docker compose config показывает итоговый YAML, а docker compose logs -f cadvisor — ошибки монтирования. Если порт 8080 уже занят, смените внешний на 8081:8080 и поправьте цель в Prometheus.
Ключевые метрики и запросы
Для процессора используется счётчик container_cpu_usage_seconds_total, поэтому его нужно оборачивать в rate. Для памяти берётся container_memory_working_set_bytes — она ближе к реальному потреблению, чем container_memory_usage_bytes, потому что учитывает активные страницы. Лимит хранится в container_spec_memory_limit_bytes и равен нулю, если ограничение не задано.
sum by (name) (rate(container_cpu_usage_seconds_total{name!=""}[5m]))
sum by (name) (container_memory_working_set_bytes{name!=""})
sum by (name) (container_memory_working_set_bytes{name!=""})
/ sum by (name) (container_spec_memory_limit_bytes{name!=""} > 0)
sum by (name) (rate(container_network_receive_bytes_total{name!=""}[5m]))
Фильтр name!="" убирает служебные строки с пустым именем. Отношение памяти к лимиту удобно выводить в процентах и ставить порог предупреждения на 85–90 процентах: заполнение выше почти всегда заканчивается убийством процесса ядром. Для файловой системы container_fs_usage_bytes стоит читать осторожно: на overlay она может включать слои образа и не совпадать с тем, что видит df внутри контейнера.
Если контейнер недавно перезапустился, часть счётчиков начинается с нуля. Это нормально: rate сам обработает сброс, а для подсчёта перезапусков используют метрику container_start_time_seconds и функцию changes.
Нагрузка и настройка
По умолчанию cAdvisor опрашивает cgroups примерно раз в секунду. На хосте с сотней контейнеров это заметный расход, поэтому интервал увеличивают до 10–30 секунд. Часть метрик можно отключить: список задаётся флагами --disable_metrics или, в новых версиях, --enable_metrics. Начните с отключения per-CPU и подробных дисковых серий, если они не нужны на дашбордах.
docker run -d --name=cadvisor -p 8080:8080 \
--volume=/:/rootfs:ro --volume=/var/run:/var/run:ro \
--volume=/sys:/sys:ro --volume=/var/lib/docker/:/var/lib/docker:ro \
gcr.io/cadvisor/cadvisor:latest \
--housekeeping_interval=30s --docker_only=true
Помните, что latest удобен для знакомства, но не для продакшена: зафиксируйте конкретный тег и обновляйте его осознанно. Перед обновлением проверьте, что новая версия поддерживает вашу версию cgroups и формат хранения контейнеров.
Диагностика
- Метрик контейнеров нет — проверьте, что смонтирован каталог хранилища Docker и что запуск идёт на хосте, а не внутри другого контейнера без доступа к сокету.
- В системе cgroups v2, а версия cAdvisor старая — обновите образ; проверьте тип через
stat -fc %T /sys/fs/cgroup. - Высокая нагрузка от самого cAdvisor — увеличьте
--housekeeping_intervalи включите--docker_only. - Пустые имена контейнеров — фильтруйте
container!=""и сверьте меткиnameиcontainerв вашей версии. - Слишком много рядов в Prometheus — удалите метку
id, ограничьте набор метрик и проверьте retention. - Порт недоступен с другой машины — cAdvisor слушает не тот интерфейс либо мешает межсетевой экран.
stat -fc %T /sys/fs/cgroup
docker info | grep -i cgroup
curl -s http://localhost:8080/metrics | grep container_last_seen | head
docker logs --tail 50 cadvisor
Итог
cAdvisor — минимальный по усилиям способ получить метрики контейнеров в Prometheus: один контейнер, несколько точек монтирования и стандартный scrape. Дальше всё зависит от дисциплины: фиксированная версия образа, разумный интервал опроса, очистка лишних меток и разделение ролей с node_exporter. Начните с одного хоста, сравните графики с docker stats, и только потом разворачивайте сбор на всей инфраструктуре.