Мониторинг дискового пространства в Docker и Kubernetes: настройка cAdvisor, kube-state-metrics и Alertmanager | AdminWiki

Мониторинг дискового пространства в Docker и Kubernetes: настройка cAdvisor, kube-state-metrics и Alertmanager

24 июля 2026 11 мин. чтения

Почему мониторинг дисков в контейнерах - это критично

Заполненный до нуля диск на узле Kubernetes или Docker-хосте - это не предупреждение, а уже авария. Pod'ы переходят в статус Evicted или CrashLoopBackOff, контейнеры теряют возможность писать логи, базы данных останавливаются с ошибкой 'No space left on device'. Восстановление занимает часы, а причина часто банальна: закончилось место на Persistent Volume или раздулся каталог /var/lib/docker.

Практика показывает три типовых сценария. Первый: разработчик развернул приложение с записью логов внутрь контейнера без ротации, и через неделю PV на 20 ГБ заполнен под завязку. Второй: CI/CD пайплайн собирает образы, а старые не удаляются - Docker-хост уходит в отказ. Третий: StatefulSet с PostgreSQL работает без мониторинга, и в пиковый момент база падает из-за нехватки места под WAL-файлы. Каждый из этих сценариев предотвращается за 15 минут настройки.

Стек для полного контроля дискового пространства выглядит так: cAdvisor собирает метрики использования файловой системы контейнеров, kube-state-metrics отдаёт состояние Persistent Volumes и Persistent Volume Claims, Node Exporter показывает занятость дисков на уровне узлов. Prometheus агрегирует все метрики, а Alertmanager рассылает оповещения до того, как место закончится. В этом руководстве - проверенная на рабочих средах инструкция по развёртыванию и настройке каждого компонента.

Если вы ещё не знакомы с базовым мониторингом контейнеров, начните с нашего руководства по мониторингу Docker-контейнеров для продакшена. Там разобраны основы Prometheus, Grafana и Loki, которые мы используем здесь как данность.

Архитектура мониторинга: кто за что отвечает

Мониторинг дисков в контейнерной среде требует трёх уровней сбора метрик: уровень контейнера, уровень оркестрации и уровень узла. Каждый уровень закрывает свой экспортер, и путать их зоны ответственности - верный путь пропустить критичный инцидент.

cAdvisor: мониторинг контейнеров изнутри

cAdvisor (Container Advisor) - это агент с открытым исходным кодом, встроенный в kubelet и доступный как standalone-контейнер для Docker. Он анализирует cgroups и выдаёт детальные метрики по каждому контейнеру: использование CPU, памяти, сети и файловой системы.

Для мониторинга дисков ключевые метрики cAdvisor:

  • container_fs_usage_bytes - фактически занятое место файловой системой контейнера (слои образа плюс записанные данные);
  • container_fs_limit_bytes - лимит, установленный для контейнера (размер диска узла или квота);
  • container_fs_writes_bytes_total - счётчик записанных байт, полезен для выявления аномальной активности записи.

cAdvisor интегрируется с Docker автоматически: он монтирует сокет Docker и читает данные напрямую из демона. В Kubernetes kubelet запускает cAdvisor на каждом узле по умолчанию, и метрики доступны через API kubelet на порту 10250. Ограничение: cAdvisor видит только файловую систему контейнера, но не имеет информации о Persistent Volumes, смонтированных через CSI-драйверы. Для PV нужен отдельный инструмент.

kube-state-metrics и Node Exporter: покрытие Kubernetes

kube-state-metrics - это сервис, который слушает API Kubernetes и генерирует метрики о состоянии объектов кластера: подов, деплойментов, нод, PV и PVC. Он не смотрит внутрь контейнеров, а опрашивает control plane. Для дисков это означает:

  • kube_persistentvolume_capacity_bytes - общая ёмкость PV;
  • kube_persistentvolume_status_phase - статус тома (Available, Bound, Released, Failed);
  • kube_persistentvolumeclaim_resource_requests_storage_bytes - запрошенный размер PVC.

Эти метрики критичны для обнаружения PV, которые скоро заполнятся, или PVC, которые не могут зарезервировать том. kube-state-metrics не показывает, сколько места занято внутри PV - только ёмкость и статус. Фактическое использование даёт cAdvisor или агент внутри пода.

Node Exporter закрывает третий уровень - метрики самого узла. Он работает как DaemonSet на каждой ноде и отдаёт:

  • node_filesystem_avail_bytes - доступное место на файловой системе;
  • node_filesystem_size_bytes - общий размер;
  • node_filesystem_free_bytes - свободное место (с учётом зарезервированных блоков);
  • node_disk_io_time_seconds_total - время операций ввода-вывода.

Разница между метриками контейнеров и инфраструктуры принципиальна. container_fs_usage_bytes показывает, сколько занято внутри образа контейнера. node_filesystem_avail_bytes - сколько осталось на физическом диске. Если первое растёт, проблема в приложении. Если второе падает - проблема на уровне хоста: логи, снапшоты, временные файлы.

Prometheus агрегирует все три источника метрик по единой модели: pull-сбор с интервалом 15-30 секунд, хранение в TSDB, оценка правил алертинга. Alertmanager получает алерты от Prometheus, группирует, маршрутизирует и отправляет в Slack, Telegram, email или PagerDuty. Схема взаимодействия линейна: экспортеры → Prometheus → Alertmanager → канал уведомлений.

Для глубокого понимания метрик всего кластера, включая нагрузку на CPU и сеть, обратитесь к нашему руководству по мониторингу кластеров серверов. Там разобраны дашборды Grafana и специфичные решения для HA-кластеров.

Настройка мониторинга дисков в Docker с помощью cAdvisor и Prometheus

Для standalone Docker-хоста связка cAdvisor + Prometheus - минимально достаточное решение. cAdvisor собирает метрики со всех контейнеров, Prometheus сохраняет и оценивает их. Разворачивается за 5 минут через Docker Compose.

Запуск cAdvisor через Docker Compose

Создайте файл docker-compose.yml в отдельной директории, например /opt/monitoring:

version: '3.8'

services:
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:v0.47.2
    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
    privileged: true
    devices:
      - /dev/kmsg

  prometheus:
    image: prom/prometheus:v2.52.0
    container_name: prometheus
    restart: unless-stopped
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=15d'

volumes:
  prometheus_data:

Маппинг томов для cAdvisor критичен: /rootfs даёт доступ ко всей файловой системе хоста (read-only), /var/run - к сокету Docker, /sys - к cgroups, /var/lib/docker - к данным контейнеров. Без privileged: true и /dev/kmsg cAdvisor не сможет читать системные метрики. Порт 8080 используется для веб-интерфейса и отдачи метрик Prometheus по эндпоинту /metrics.

Запустите стек командой:

docker-compose up -d

Проверьте, что cAdvisor отдаёт метрики: curl http://localhost:8080/metrics | grep container_fs_usage_bytes. Вы увидите строки с лейблами контейнеров и текущими значениями в байтах.

Интеграция cAdvisor с Prometheus

Создайте файл prometheus.yml рядом с docker-compose.yml:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']
    metric_relabel_configs:
      - source_labels: ['container_label_com_docker_compose_service']
        target_label: 'service'
      - source_labels: ['container_label_com_docker_compose_project']
        target_label: 'project'

job_name 'cadvisor' указывает Prometheus опрашивать контейнер cadvisor по внутреннему DNS-имени в сети Docker Compose. metric_relabel_configs упрощают лейблы: вместо длинных container_label_com_docker_compose_service вы получаете короткий service. После перезапуска Prometheus (docker-compose restart prometheus) проверьте targets в веб-интерфейсе http://localhost:9090/targets - статус cadvisor должен быть UP.

Пример PromQL-запроса для получения процента использования диска конкретным контейнером:

(container_fs_usage_bytes{name="myapp"} / container_fs_limit_bytes{name="myapp"}) * 100

Этот запрос вернёт процент заполнения файловой системы контейнера myapp. Используйте его для отладки или как основу для правила алертинга.

Мониторинг дисков в Kubernetes: установка kube-state-metrics и Node Exporter

В кластере Kubernetes мониторинг дисков требует двух дополнительных экспортеров: kube-state-metrics для объектов PV/PVC и Node Exporter для метрик узлов. Оба устанавливаются через Helm - это стандартный и поддерживаемый способ.

Установка kube-state-metrics

Добавьте репозиторий и установите чарт в namespace monitoring:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install kube-state-metrics prometheus-community/kube-state-metrics \
  --namespace monitoring \
  --create-namespace \
  --set metricLabelsAllowlist='pods=[*],persistentvolumes=[*],persistentvolumeclaims=[*]'

Параметр metricLabelsAllowlist важен: по умолчанию kube-state-metrics не добавляет все лейблы к метрикам для экономии ресурсов. Для мониторинга дисков нужны лейблы persistentvolume и persistentvolumeclaim - они позволяют связать PV с PVC и пространством имён. Проверьте, что поды запустились:

kubectl get pods -n monitoring -l app.kubernetes.io/name=kube-state-metrics

Если Prometheus Operator уже развёрнут в кластере, kube-state-metrics автоматически создаст ServiceMonitor. Проверьте в Prometheus UI (обычно доступен через порт-форвард: kubectl port-forward -n monitoring svc/prometheus-kube-prometheus-prometheus 9090) по адресу /targets - фильтр по job kube-state-metrics покажет все эндпоинты.

Настройка сбора метрик Persistent Volumes

Ключевая метрика для алертинга - процент заполнения PV. Прямого показателя использования внутри PV у kube-state-metrics нет, но есть ёмкость. Фактическое использование получают через cAdvisor (kubelet) или sidecar-агент. PromQL-запрос для расчёта процента заполнения PV, смонтированного в под:

(kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes) * 100

kubelet_volume_stats_used_bytes - это метрика kubelet, доступная в Prometheus при сборе метрик с узлов. Она показывает, сколько байт занято внутри PV. Для сопоставления с PVC используйте лейбл persistentvolumeclaim. Пример запроса с фильтрацией по namespace:

(kubelet_volume_stats_used_bytes{namespace="production"} 
  / kubelet_volume_stats_capacity_bytes{namespace="production"}) * 100

Этот запрос вернёт процент заполнения для каждого PV в namespace production. Значение выше 80% - повод для предупреждения, выше 90% - критический алерт.

Развертывание Node Exporter для метрик узлов

Node Exporter устанавливается как DaemonSet - по одному поду на каждый узел кластера. Используйте официальный чарт:

helm install node-exporter prometheus-community/prometheus-node-exporter \
  --namespace monitoring \
  --set prometheus.monitor.enabled=true \
  --set prometheus.monitor.relabelings[0].targetLabel=node \
  --set prometheus.monitor.relabelings[0].replacement='${1}' \
  --set prometheus.monitor.relabelings[0].sourceLabels[0]=__meta_kubernetes_pod_node_name

Флаг prometheus.monitor.enabled=true создаёт ServiceMonitor для автоматического обнаружения Prometheus Operator. После установки проверьте метрики в Prometheus UI запросом node_filesystem_avail_bytes. Лейбл mountpoint позволяет отфильтровать системные разделы и оставить только значимые, например /var/lib/docker или /data:

node_filesystem_avail_bytes{mountpoint="/var/lib/docker"}

Для алертинга используйте процент доступного места: (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100. Значение ниже 20% - предупреждение, ниже 10% - критический алерт.

Если вам нужен мониторинг дисков на уровне операционной системы без контейнеров, посмотрите наше руководство по мониторингу дисков в Linux. Там разобраны Zabbix, Netdata и другие инструменты.

Настройка оповещений о нехватке дискового пространства в Alertmanager

Метрики без алертов - это архив. Настройка оповещений превращает мониторинг из пассивного наблюдения в активную защиту от инцидентов. Prometheus оценивает правила алертинга каждые 15 секунд (или согласно evaluation_interval), и при срабатывании условия отправляет алерт в Alertmanager.

Правила алертинга для дисков

Создайте манифест PrometheusRule с алертами для трёх уровней: узел, Persistent Volume и контейнер Docker. Пример для Kubernetes с Prometheus Operator:

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: disk-space-alerts
  namespace: monitoring
spec:
  groups:
    - name: disk-space
      rules:
        - alert: NodeDiskSpaceUsageHigh
          expr: |
            (node_filesystem_avail_bytes{mountpoint="/"} 
              / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 20
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "Дисковое пространство на узле {{ $labels.instance }} заканчивается"
            description: "Доступно {{ $value | humanize }}% на разделе {{ $labels.mountpoint }}."

        - alert: NodeDiskSpaceUsageCritical
          expr: |
            (node_filesystem_avail_bytes{mountpoint="/"} 
              / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 10
          for: 1m
          labels:
            severity: critical
          annotations:
            summary: "Критически мало места на узле {{ $labels.instance }}"
            description: "Осталось {{ $value | humanize }}% на разделе {{ $labels.mountpoint }}. Немедленно примите меры."

        - alert: PersistentVolumeUsageHigh
          expr: |
            (kubelet_volume_stats_used_bytes 
              / kubelet_volume_stats_capacity_bytes) * 100 > 80
          for: 10m
          labels:
            severity: warning
          annotations:
            summary: "Persistent Volume {{ $labels.persistentvolumeclaim }} заполнен на {{ $value | humanize }}%"
            description: "PVC {{ $labels.persistentvolumeclaim }} в namespace {{ $labels.namespace }} превысил порог 80%."

        - alert: PersistentVolumeUsageCritical
          expr: |
            (kubelet_volume_stats_used_bytes 
              / kubelet_volume_stats_capacity_bytes) * 100 > 90
          for: 5m
          labels:
            severity: critical
          annotations:
            summary: "Persistent Volume {{ $labels.persistentvolumeclaim }} заполнен критически"
            description: "PVC {{ $labels.persistentvolumeclaim }} в namespace {{ $labels.namespace }} превысил 90%. Возможна остановка подов."

        - alert: ContainerDiskUsageHigh
          expr: |
            (container_fs_usage_bytes{name=~".+"} 
              / container_fs_limit_bytes{name=~".+"}) * 100 > 85
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "Контейнер {{ $labels.name }} использует {{ $value | humanize }}% диска"
            description: "Файловая система контейнера {{ $labels.name }} на хосте {{ $labels.instance }} заполнена."

Ключевые моменты в правилах: for указывает, сколько времени условие должно выполняться до отправки алерта - это фильтрует кратковременные всплески. severity разделяет warning и critical для маршрутизации: warning идёт в общий канал, critical - в срочный (PagerDuty, телефон).

Конфигурация Alertmanager и каналы уведомлений

Пример alertmanager.yml с маршрутизацией по severity и каналами в Slack и email:

global:
  slack_api_url: 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL'

route:
  receiver: 'slack-warnings'
  routes:
    - match:
        severity: critical
      receiver: 'slack-critical'
      repeat_interval: 5m
    - match:
        severity: warning
      receiver: 'slack-warnings'
      repeat_interval: 30m

receivers:
  - name: 'slack-warnings'
    slack_configs:
      - channel: '#monitoring-warnings'
        title: '{{ .GroupLabels.alertname }}'
        text: '{{ range .Alerts }}{{ .Annotations.summary }}
{{ .Annotations.description }}
{{ end }}'
  - name: 'slack-critical'
    slack_configs:
      - channel: '#monitoring-critical'
        title: '[CRITICAL] {{ .GroupLabels.alertname }}'
        text: '{{ range .Alerts }}{{ .Annotations.summary }}
{{ .Annotations.description }}
{{ end }}'
  - name: 'email'
    email_configs:
      - to: 'devops@example.com'
        from: 'alertmanager@example.com'
        smarthost: 'smtp.example.com:587'
        auth_username: 'alertmanager@example.com'
        auth_password: 'password'

Маршрутизация построена на лейбле severity: critical-алерты уходят в канал #monitoring-critical с повтором каждые 5 минут, warning - в #monitoring-warnings с интервалом 30 минут. repeat_interval определяет, как часто Alertmanager будет напоминать о неразрешённом алерте.

Для проверки работоспособности отправьте тестовый алерт через API Alertmanager (порт 9093):

curl -X POST http://alertmanager:9093/api/v1/alerts \
  -H 'Content-Type: application/json' \
  -d '[{"labels":{"alertname":"TestAlert","severity":"critical"},"annotations":{"summary":"Тестовый алерт","description":"Проверка канала уведомлений"}}]'

В канале Slack должно появиться сообщение. Если нет - проверьте логи Alertmanager: docker logs alertmanager или kubectl logs -n monitoring alertmanager-0.

Типовые причины заполнения дисков и как их избежать

Алерты сообщают о проблеме, когда она уже возникла. Профилактика устраняет причины. Три главных источника заполнения дисков в контейнерных средах: логи, образы и неочищаемые тома.

Логи контейнеров. Docker по умолчанию использует драйвер json-file без ограничения размера. Контейнер, пишущий в stdout/stderr, может занять весь диск за сутки. Решение - настройка log rotation в демоне Docker (/etc/docker/daemon.json):

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}

После изменения конфигурации перезапустите Docker: systemctl restart docker. Для Kubernetes настройте ротацию через kubelet (флаг --container-log-max-size и --container-log-max-files) или используйте централизованный сбор логов в Loki - это подробно разобрано в нашем гайде по деплою Docker в production.

Накопление образов. CI/CD пайплайны собирают образы, старые версии остаются на хосте. Команда docker system df показывает использование диска Docker-объектами. Очистка: docker system prune -a -f удаляет все неиспользуемые образы, контейнеры и тома. Добавьте эту команду в cron на ежедневное выполнение. В Kubernetes следите за образами через garbage collection kubelet (настраивается флагами --image-gc-high-threshold и --image-gc-low-threshold).

Неочищаемые Persistent Volumes. PV с политикой Retain после удаления PVC остаются в статусе Released и не освобождают место. Администратор должен вручную удалить PV и очистить данные на стороне хранилища. Настройте мониторинг PV в статусе Released через метрику kube_persistentvolume_status_phase и алерт на долго висящие тома.

Рекомендации по лимитам. Устанавливайте resource.requests.storage для PVC - это предотвращает резервирование избыточного места. Для контейнеров без PV задавайте размер временного хранилища через ephemeral-storage limits в спецификации пода. Это защитит узел от контейнера, который внезапно начал писать данные на локальный диск.

Заключение: полный цикл мониторинга дисков

Вы развернули cAdvisor для метрик контейнеров, kube-state-metrics для состояния PV и PVC, Node Exporter для дисков узлов. Prometheus собирает метрики со всех трёх источников, Alertmanager рассылает оповещения о заполнении до того, как место закончится. Архитектура покрывает все уровни: контейнер, оркестрация, инфраструктура.

Следующий шаг - визуализация. Импортируйте дашборд Node Exporter Full (ID 1860) в Grafana для отображения дисковой статистики узлов в реальном времени. Для Kubernetes используйте дашборд Kubernetes Compute Resources Persistent Volume (ID 11074). Оба доступны на grafana.com и показывают тренды заполнения за дни и недели - это помогает прогнозировать, когда место закончится.

Проверьте настройки на тестовом стенде: заполните PV тестовыми данными, убедитесь, что алерт приходит в Slack. Настройте repeat_interval в Alertmanager так, чтобы вас не засыпало повторными уведомлениями, но и не пропустить эскалацию. Для продвинутых сценариев алертинга и наблюдаемости высоконагруженных систем обратитесь к нашему руководству по наблюдаемости для высоконагруженных систем - там разобраны SRE-практики и GitOps-подход к мониторингу.

Если вам нужна облачная инфраструктура для развёртывания этого стека, обратите внимание на Timeweb Cloud - они предоставляют Kubernetes и VDS с гибким масштабированием ресурсов. Для автоматизации создания контента и SEO-продвижения вашей базы знаний используйте LidBiz - сервис автоматической генерации и публикации материалов.

Поделиться:
Сохранить гайд? В закладки браузера