Drain узла остановился на PodDisruptionBudget: как разобраться в ограничении
Команда обслуживания начала drain узла и остановилась на сообщении о нарушении disruption budget. Повторение команды не увеличивает число доступных реплик. Kubernetes отказывается добровольно выселять Pod, когда это нарушит заданный минимум доступности. Прежде чем обходить запрет, нужно понять, почему приложение уже израсходовало свой запас.
Находим бюджет именно этого приложения
kubectl -n demo get pdb
kubectl -n demo describe pdb api-budget
kubectl -n demo get pdb api-budget -o yaml
kubectl -n demo get pods -l app=api -o wideПосмотрите selector PDB и фактические labels Pod. В policy/v1 пустой selector выбирает все Pod namespace, поэтому оставлять его пустым по ошибке опасно. Одинаково названные Deployment и PDB не связаны автоматически. У бюджета есть currentHealthy, desiredHealthy, expectedPods и disruptionsAllowed. Эти поля показывают текущую возможность добровольного выселения, а не только желаемое число реплик в Deployment.
Считаем ограничение на простом случае
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-budget
namespace: demo
spec:
minAvailable: 2
selector:
matchLabels:
app: apiПусть Deployment имеет три реплики. Если все три здоровы для расчёта бюджета, один добровольный eviction допустим. Если одна уже неготова, остаются две здоровые, и выселение ещё одной опустит число ниже minAvailable: 2. Для этого состояния disruptionsAllowed обычно равно нулю. Начните с причины неготовности третьей реплики: readiness, авария процесса, недоступный том или отсутствие места на узлах.
Можно задать maxUnavailable вместо minAvailable, но одновременно оба поля не используются. Процентные значения округляются вверх; у маленького числа реплик это заметно меняет результат. Например, 30% от трёх при maxUnavailable допускает одну недоступную реплику. Для прикладного смысла «ровно одна» абсолютное число иногда понятнее процента.
Проверяем, сможет ли появиться замена
kubectl -n demo describe deployment api kubectl -n demo get events --sort-by=.metadata.creationTimestamp kubectl get nodes
Узел после cordon не принимает обычные новые Pod, поэтому замена должна поместиться на остальных подходящих узлах. Строгая anti-affinity, nodeSelector или зона диска могут оставить новый Pod Pending. Увеличение replicas без такой проверки не создаёт доступность: получатся дополнительные ожидающие объекты. Рассмотрите свободные requests, разрешённые узлы и ограничения хранилища вместе.
PDB защищает добровольные disruption через eviction API, но не предотвращает физическую аварию узла. Он также не управляет стратегией RollingUpdate Deployment: та имеет собственные maxUnavailable и maxSurge. При одновременном релизе и обслуживании узлов легко уменьшить запас доступности, хотя каждая отдельная настройка выглядит разумно. Согласуйте эти операции по времени.
Выбираем безопасный способ продолжить
Обычно сначала восстанавливают неготовую реплику либо добавляют пригодную ёмкость, ждут Ready и нового расчёта бюджета. После этого повторяют согласованное обслуживание. В отдельных приложениях допустимо временно изменить PDB, но такое решение должно опираться на переносимость потери реплики: quorum, активный лидер и длительные соединения влияют сильнее, чем само число Pod.
Поле unhealthyPodEvictionPolicy задаёт поведение для нездоровых работающих Pod. Значение AlwaysAllow может помочь вывести узел с экземпляром, который не становится здоровым, но оно не делает сам сервис доступным. Применимость нужно проверить по версии кластера и устройству приложения. Не переносите его на все PDB как универсальное исправление drain.
Прямое удаление Pod и режимы обхода eviction меняют механизм защиты. В частности, --disable-eviction у drain использует удаление вместо eviction и обходит PDB; это отдельное решение с риском потери доступности. Обычный --force связан с определёнными unmanaged Pod и сам по себе не означает «игнорировать бюджет». Перед любым обходом сохраните состояние и согласуйте реальную цену остановки.
Хороший результат расследования — восстановленный запас и положительное disruptionsAllowed для планируемого шага. Во время обслуживания наблюдайте новые реплики и запросы сервиса. Для следующего шага обслуживания снова проверьте число работающих экземпляров на доступных узлах.
Ещё по теме
- OOMKilled в Kubernetes: отделяем лимит контейнера от нехватки памяти узла
- Pod завис в Pending: как читать события и найти нехватку ресурсов
Продолжить изучение
Хотите увереннее разворачивать приложения и разбирать сбои в кластере? Сети, конфигурация, хранилища и обновления входят в программу «Kubernetes с нуля до PRO».
Продолжить на практике
- Kubernetes с нуля до PRO ↗
Разворачивайте и сопровождайте приложения в Kubernetes: от первого Pod до релизов, сетей, хранилищ, масштабирования и диагностики. Итоговый проект — сервис с базой данных, мониторингом и проверенным откатом.
