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

Локальные персистентные тома (Local Persistent Volumes) в Kubernetes дают высокую производительность за счёт прямого доступа к дискам узлов, но вводят строгое ограничение: данные привязаны к конкретной ноде через
nodeAffinity
read-only
Running
Bound
Почему стандартного мониторинга Kubernetes недостаточно для Local PV
Три уровня контроля
Обычный набор метрик — загрузка CPU, потребление памяти, доступность нод и подов — покрывает только уровень Kubernetes API. Для локальных томов это недостаточно, потому что физический ресурс диска не абстрагирован от узла. Проблемы проявляются на уровне ОС: заполнение раздела, исчерпание inode, ошибки файловой системы, отказ диска. На уровне приложения это приводит к ошибкам записи, которые не видны в метриках контейнера. Только совокупность проверок на всех трёх уровнях даёт полную картину.
Рассмотрим кластер из пяти воркер-нод. На
worker-1
Running
Bound
Проверка доступных метрик kubelet для локальных томов
Ключевые метрики kubelet_volume_stats
Основным источником данных о томах служит эндпоинт
/metrics
- — занятое пространство тома;
- kubelet_volume_stats_used_bytes
- — общая ёмкость тома;
- kubelet_volume_stats_capacity_bytes
- — доступное пространство;
- kubelet_volume_stats_available_bytes
- — общее количество inode;
- kubelet_volume_stats_inodes
- — свободные inode.
- kubelet_volume_stats_inodes_free
Не путайте их с метриками cAdvisor (
/metrics/cadvisor
Диагностика сбора метрик через API
Проверить наличие метрик можно прямо через Kubernetes API proxy:
kubectl get nodes -o wide kubectl get --raw "/api/v1/nodes/worker-1/proxy/metrics" | grep '^kubelet_volume_stats_'
Если RBAC или настройки API proxy блокируют запрос, используйте доступный в окружении способ обращения к эндпоинту kubelet (например, через порт-форвардинг или node-exporter). Отсутствие результата не означает поломку тома — метрики могут не собираться, не поддерживаться драйвером или отсутствовать для данного типа тома.
Что делать, если метрик нет
Сначала проверьте конфигурацию сбора. При использовании Prometheus Operator убедитесь, что
ServiceMonitor
VMServiceScrape
VMPodScrape
kubectl get servicemonitor -A kubectl get vmservicescrape -A kubectl get vmpodscrape -A
Перечисленные ресурсы относятся к разным стекам мониторинга; в конкретном кластере могут присутствовать не все.
Расчёт процента заполнения и настройка дашбордов в Grafana
PromQL-запросы для заполнения
Абсолютные значения байт неудобны для алертинга: 10 GiB — это мало для тома 500 GiB, но критично для 12 GiB. Рассчитываем процент заполнения:
100 * ( kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes )
Фильтр для томов, заполненных более чем на 80%:
( 100 * kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes ) > 80
Для удобства добавьте в запрос лейблы
namespace
persistentvolumeclaim
node
Настройка панели визуализации
В Grafana рекомендую следующие параметры панели:
- Visualization: Time series или Table;
- Unit: Percent (0–100);
- Min: 0;
- Max: 100.
Фиксированная шкала упрощает сравнение томов разного размера.
Нюанс: том против файловой системы узла
Заполненность тома и заполненность файловой системы, на которой он расположен, — не всегда одно и то же. Если Local PV указывает на обычный каталог (а не на отдельный раздел), объявленная ёмкость PV может не отражать реальный изолированный лимит для этого каталога. В таком случае обязательно мониторьте файловую систему узла отдельно (например, через
node_filesystem_*
Настройка алертов на заполнение хранилища
Пример правил для Prometheus и VictoriaMetrics
Правила ниже адаптируются под PrometheusRule или конфигурацию VMAlert. Используются два уровня:
groups: - name: local-pv-alerts interval: 30s rules: - alert: LocalPVUsageWarning expr: | ( 100 * kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes ) > 80 for: 10m labels: severity: warning annotations: summary: "Local PV заполнен более чем на 80%" description: >- PVC {{ $labels.persistentvolumeclaim }} в namespace {{ $labels.namespace }} использует {{ $value }}% доступной ёмкости. - alert: LocalPVUsageCritical expr: | ( 100 * kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes ) > 90 for: 5m labels: severity: critical annotations: summary: "Критическое заполнение Local PV" description: >- PVC {{ $labels.persistentvolumeclaim }} в namespace {{ $labels.namespace }} заполнен на {{ $value }}%.
Пороги и длительность
for
Важность контроля отсутствия метрик
Если метрика перестаёт поступать, выражение перестаёт возвращать временной ряд. Само по себе это не значит, что том свободен. Отсутствие метрик необходимо отслеживать отдельным правилом (например, через
absent()
up
Контроль свободных inode
Приложения, создающие много мелких файлов (логи, кэш, временные данные), могут исчерпать inode при свободном месте на диске. Файловая система перестаёт создавать файлы, приложение падает с ошибками, а мониторинг диска показывает норму.
Проверяем процент использованных inode:
100 * ( 1 - kubelet_volume_stats_inodes_free / kubelet_volume_stats_inodes )
Фильтр для критического значения (менее 10% свободных):
(100 * ( 1 - kubelet_volume_stats_inodes_free / kubelet_volume_stats_inodes ) ) > 90
Если метрик inode нет в kubelet, контролируйте их на уровне файловой системы узла через node-exporter.
Мониторинг состояния узлов и привязки Local PV
Проверка nodeAffinity и состояния нод
Local PV жёстко привязан к узлу. Пример спецификации PV:
nodeAffinity: required: nodeSelectorTerms: - matchExpressions: operator: In values: - worker-1
Посмотреть привязку можно командами:
kubectl get pv -o wide kubectl describe pv postgres-pv
Состояние ноды отслеживается через kube-state-metrics:
kube_node_status_condition{condition="Ready",status="true"} == 0
Этот запрос находит ноды, не находящиеся в состоянии
Ready
Связывание алертов нод с критичными приложениями
Один алерт
NodeNotReady
node
kubernetes_io_hostname
Почему статус Running не гарантирует сохранность данных
Проверки на уровне приложения (пример PostgreSQL)
Под в
Running
Bound
Она проверяет только сетевую готовность сервера. Гарантию записи даёт только тестовый сценарий, безопасно выполняющий операцию
INSERT
SELECT
Ограничения readiness/liveness probes
Не кладите тяжёлые дисковые операции в
readinessProbe
livenessProbe
Проверка работоспособности цепочки алертинга
Настроить правило и увидеть его в конфигурации — полдела. Цепочка: источник метрик → Prometheus/VictoriaMetrics → Alertmanager → маршрутизация → SMTP/мессенджер. Если алерт есть в Alertmanager, а уведомление не пришло — проблема в маршрутизации, группировке или доставке.
Проверяйте по порядку: 1. Правило загружено и выполняется (UI Prometheus/VM → Alerts). 2. Активный алерт появляется в Alertmanager. 3. Логи доставки уведомлений (SMTP, webhook).
Тестировать заполнение диска до 90–100% в проде не рекомендую. Лучше временно снизить порог на тестовом томе или использовать тестовую метрику.
Рекомендуемая структура дашбордов в Grafana
Local Storage Overview
Сводная панель для быстрой оценки:
- Количество PV по состояниям: ,
- Bound
,- Available
,- Released
;- Failed
- Количество PVC в ;
- 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 дают производительность локальных дисков, но требуют ответственности за размещение и доступность данных. Ключевые выводы:
- Статус не гарантирует возможность записи данных.
- Running
- Статус не гарантирует исправность ФС или диска.
- Bound
- Заполненность тома и заполненность ФС узла — разные показатели.
- Недоступность узла = недоступность локальных данных на нём.
- Отсутствие метрик нужно отличать от нормального состояния (отдельный алерт).
- Алерты проверяются целиком: от сбора метрики до доставки уведомления.
Правильно собранный стек мониторинга перестаёт быть набором графиков ресурсов и становится инструментом раннего обнаружения рисков для приложений и данных.


