Поиск

Мониторинг Local Persistent Volumes в Kubernetes: от метрик kubelet до алертов в Grafana

Мониторинг Local Persistent Volumes в Kubernetes: от метрик kubelet до алертов в Grafana

Локальные персистентные тома (Local Persistent Volumes) в Kubernetes дают высокую производительность за счёт прямого доступа к дискам узлов, но вводят строгое ограничение: данные привязаны к конкретной ноде через

  1. nodeAffinity
. Если на воркере заканчивается место, файловая система переходит в
  1. read-only
или сам узел становится недоступным, Kubernetes не может просто переехать под с данными на другую машину. Статус
  1. Running
у пода и
  1. Bound
у PVC в таком случае не отражают реальное состояние хранилища. Базовый мониторинг CPU, RAM и количества рестартов здесь слеп — нужен стек, контролирующий три уровня: Kubernetes API, операционную систему и способность приложения читать и писать данные.

Почему стандартного мониторинга Kubernetes недостаточно для Local PV

Три уровня контроля

Обычный набор метрик — загрузка CPU, потребление памяти, доступность нод и подов — покрывает только уровень Kubernetes API. Для локальных томов это недостаточно, потому что физический ресурс диска не абстрагирован от узла. Проблемы проявляются на уровне ОС: заполнение раздела, исчерпание inode, ошибки файловой системы, отказ диска. На уровне приложения это приводит к ошибкам записи, которые не видны в метриках контейнера. Только совокупность проверок на всех трёх уровнях даёт полную картину.

Почему стандартного мониторинга Kubernetes недостаточно для Local PV

Рассмотрим кластер из пяти воркер-нод. На

  1. worker-1
заканчивается свободное место. Под с PostgreSQL остаётся в
  1. Running
, PVC в
  1. Bound
, но любая попытка записи завершается ошибкой файловой системы. Метрики kubelet о состоянии пода не покажут эту проблему. Необходимо отслеживать заполнение конкретного тома, состояние inode на его файловой системе и доступность самой ноды, к которой том привязан.

Проверка доступных метрик kubelet для локальных томов

Ключевые метрики kubelet_volume_stats

Основным источником данных о томах служит эндпоинт

  1. /metrics
kubelet. Для Local PV наиболее актуальны следующие метрики (их наличие зависит от версии Kubernetes, типа тома и конфигурации сбора):

Проверка доступных метрик kubelet для локальных томов

    1. kubelet_volume_stats_used_bytes
    — занятое пространство тома;
    1. kubelet_volume_stats_capacity_bytes
    — общая ёмкость тома;
    1. kubelet_volume_stats_available_bytes
    — доступное пространство;
    1. kubelet_volume_stats_inodes
    — общее количество inode;
    1. kubelet_volume_stats_inodes_free
    — свободные inode.

Не путайте их с метриками cAdvisor (

  1. /metrics/cadvisor
), которые отражают состояние контейнерной файловой системы, а не примонтированных томов.

Диагностика сбора метрик через API

Проверить наличие метрик можно прямо через Kubernetes API proxy:

  1. kubectl get nodes -o wide
  2. kubectl get --raw "/api/v1/nodes/worker-1/proxy/metrics" | grep '^kubelet_volume_stats_'

Если RBAC или настройки API proxy блокируют запрос, используйте доступный в окружении способ обращения к эндпоинту kubelet (например, через порт-форвардинг или node-exporter). Отсутствие результата не означает поломку тома — метрики могут не собираться, не поддерживаться драйвером или отсутствовать для данного типа тома.

Что делать, если метрик нет

Сначала проверьте конфигурацию сбора. При использовании Prometheus Operator убедитесь, что

  1. ServiceMonitor
для kubelet настроен и применяется. Для VictoriaMetrics Operator проверьте ресурсы
  1. VMServiceScrape
или
  1. VMPodScrape
(в зависимости от схемы развёртывания). Диагностика:

  1. kubectl get servicemonitor -A
  2. kubectl get vmservicescrape -A
  3. kubectl get vmpodscrape -A

Перечисленные ресурсы относятся к разным стекам мониторинга; в конкретном кластере могут присутствовать не все.

Расчёт процента заполнения и настройка дашбордов в Grafana

PromQL-запросы для заполнения

Абсолютные значения байт неудобны для алертинга: 10 GiB — это мало для тома 500 GiB, но критично для 12 GiB. Рассчитываем процент заполнения:

  1. 100 * ( kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes )

Фильтр для томов, заполненных более чем на 80%:

  1. ( 100 * kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes ) > 80

Для удобства добавьте в запрос лейблы

  1. namespace
,
  1. persistentvolumeclaim
,
  1. node
, если они экспортируются.

Настройка панели визуализации

В Grafana рекомендую следующие параметры панели:

  • Visualization: Time series или Table;
  • Unit: Percent (0–100);
  • Min: 0;
  • Max: 100.

Фиксированная шкала упрощает сравнение томов разного размера.

Нюанс: том против файловой системы узла

Заполненность тома и заполненность файловой системы, на которой он расположен, — не всегда одно и то же. Если Local PV указывает на обычный каталог (а не на отдельный раздел), объявленная ёмкость PV может не отражать реальный изолированный лимит для этого каталога. В таком случае обязательно мониторьте файловую систему узла отдельно (например, через

  1. node_filesystem_*
метрики node-exporter).

Настройка алертов на заполнение хранилища

Пример правил для Prometheus и VictoriaMetrics

Правила ниже адаптируются под PrometheusRule или конфигурацию VMAlert. Используются два уровня:

  1. groups:
  2. - name: local-pv-alerts
  3. interval: 30s
  4. rules:
  5. - alert: LocalPVUsageWarning
  6. expr: |
  7. ( 100 * kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes ) > 80
  8. for: 10m
  9. labels:
  10. severity: warning
  11. annotations:
  12. summary: "Local PV заполнен более чем на 80%"
  13. description: >-
  14. PVC {{ $labels.persistentvolumeclaim }} в namespace {{ $labels.namespace }} использует {{ $value }}% доступной ёмкости.
  15. - alert: LocalPVUsageCritical
  16. expr: |
  17. ( 100 * kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes ) > 90
  18. for: 5m
  19. labels:
  20. severity: critical
  21. annotations:
  22. summary: "Критическое заполнение Local PV"
  23. description: >-
  24. PVC {{ $labels.persistentvolumeclaim }} в namespace {{ $labels.namespace }} заполнен на {{ $value }}%.

Пороги и длительность

  1. for
— примеры. Для баз данных с интенсивной записью их нужно калибровать под нагрузку.

Важность контроля отсутствия метрик

Если метрика перестаёт поступать, выражение перестаёт возвращать временной ряд. Само по себе это не значит, что том свободен. Отсутствие метрик необходимо отслеживать отдельным правилом (например, через

  1. absent()
или алерт на
  1. up
таргета kubelet).

Контроль свободных inode

Приложения, создающие много мелких файлов (логи, кэш, временные данные), могут исчерпать inode при свободном месте на диске. Файловая система перестаёт создавать файлы, приложение падает с ошибками, а мониторинг диска показывает норму.

Проверяем процент использованных inode:

  1. 100 * ( 1 - kubelet_volume_stats_inodes_free / kubelet_volume_stats_inodes )

Фильтр для критического значения (менее 10% свободных):

  1. (100 * ( 1 - kubelet_volume_stats_inodes_free / kubelet_volume_stats_inodes ) ) > 90

Если метрик inode нет в kubelet, контролируйте их на уровне файловой системы узла через node-exporter.

Мониторинг состояния узлов и привязки Local PV

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

Local PV жёстко привязан к узлу. Пример спецификации PV:

  1. nodeAffinity:
  2. required:
  3. nodeSelectorTerms:
  4. - matchExpressions:
  5. - key: kubernetes.io/hostname
  6. operator: In
  7. values:
  8. - worker-1

Посмотреть привязку можно командами:

  1. kubectl get pv -o wide
  2. kubectl describe pv postgres-pv

Состояние ноды отслеживается через kube-state-metrics:

  1. kube_node_status_condition{condition="Ready",status="true"} == 0

Этот запрос находит ноды, не находящиеся в состоянии

  1. Ready
(при наличии соответствующего ряда метрик).

Связывание алертов нод с критичными приложениями

Один алерт

  1. NodeNotReady
недостаточен. В production нужно сопоставлять недоступные ноды с критичными приложениями и их локальными томами. Это можно сделать через джойны в PromQL (используя лейблы
  1. node
из метрик томов и
  1. kubernetes_io_hostname
из метрик нод) или отдельной проверкой через Kubernetes API при расследовании инцидента.

Почему статус Running не гарантирует сохранность данных

Проверки на уровне приложения (пример PostgreSQL)

Под в

  1. Running
, PVC в
  1. Bound
— но база может не писать на диск. Статусы Kubernetes подтверждают только оркестрацию, не исправность носителя. Для PostgreSQL базовая проверка доступности:

  1. kubectl exec -it postgres-0 -- pg_isready -h 127.0.0.1 -p 5432

Она проверяет только сетевую готовность сервера. Гарантию записи даёт только тестовый сценарий, безопасно выполняющий операцию

  1. INSERT
/
  1. SELECT
в тестовой таблице, не затрагивая пользовательские данные и не создавая нагрузку.

Ограничения readiness/liveness probes

Не кладите тяжёлые дисковые операции в

  1. readinessProbe
или
  1. livenessProbe
. Частые проверки записи сами станут источником нагрузки и износа диска. Приложенческие health-checks для диска лучше выносить в отдельный контроллер или sidecar, запускаемый по расписанию.

Проверка работоспособности цепочки алертинга

Настроить правило и увидеть его в конфигурации — полдела. Цепочка: источник метрик → Prometheus/VictoriaMetrics → Alertmanager → маршрутизация → SMTP/мессенджер. Если алерт есть в Alertmanager, а уведомление не пришло — проблема в маршрутизации, группировке или доставке.

Проверяйте по порядку: 1. Правило загружено и выполняется (UI Prometheus/VM → Alerts). 2. Активный алерт появляется в Alertmanager. 3. Логи доставки уведомлений (SMTP, webhook).

Тестировать заполнение диска до 90–100% в проде не рекомендую. Лучше временно снизить порог на тестовом томе или использовать тестовую метрику.

Рекомендуемая структура дашбордов в Grafana

Local Storage Overview

Сводная панель для быстрой оценки:

  • Количество PV по состояниям:
    1. Bound
    ,
    1. Available
    ,
    1. Released
    ,
    1. Failed
    ;
  • Количество PVC в
    1. Pending
    ;
  • Процент заполнения каждого тома;
  • Свободные inode (процент или абсолютное значение);
  • Список узлов, на которых размещены локальные PV;
  • Активные алерты по хранилищам.

Local PV Details

Детальная панель на том (или таблица с drill-down):

  • Namespace, имя PVC, имя PV;
  • Узел размещения;
  • Занятая и доступная ёмкость (байты и %);
  • Использование inode (%);
  • Состояние связанного пода;
  • Ошибки монтирования и события Kubernetes (требуют отдельного сбора, например, через event-exporter).

Данные приходят из разных источников: kubelet (статистика томов), kube-state-metrics (состояния объектов), node-exporter (ФС узла), event-exporter (события). При проектировании дашборда для расследований полезно добавить ссылки на логи пода и историю событий узла.

Итоги

Local Persistent Volumes дают производительность локальных дисков, но требуют ответственности за размещение и доступность данных. Ключевые выводы:

  • Статус
    1. Running
    не гарантирует возможность записи данных.
  • Статус
    1. Bound
    не гарантирует исправность ФС или диска.
  • Заполненность тома и заполненность ФС узла — разные показатели.
  • Недоступность узла = недоступность локальных данных на нём.
  • Отсутствие метрик нужно отличать от нормального состояния (отдельный алерт).
  • Алерты проверяются целиком: от сбора метрики до доставки уведомления.

Правильно собранный стек мониторинга перестаёт быть набором графиков ресурсов и становится инструментом раннего обнаружения рисков для приложений и данных.

—
22:49
29
Нет комментариев. Ваш будет первым!