Kubernetes: события, жизненный цикл пода, хранилище и узлы

Практическая шпаргалка для инцидентов: где искать причину и как читать сигналы кластера

1. Начните с событий (Events)

Когда что-то ломается, Kubernetes обычно создаёт объект Event. Это не логи приложения, а сообщения компонентов кластера: планировщика, kubelet и контроллеров. Они объясняют, почему система приняла то или иное решение, а не только показывают текущее состояние.

kubectl get events -n production --sort-by=.metadata.creationTimestamp
kubectl get events -n production --field-selector type=Warning

Часто повторяющиеся события подсказывают направление поиска:

2. Жизненный цикл пода

Под проходит фазы Pending, Running, Succeeded, Failed и Unknown. Большинство проблем возникает на раннем этапе, когда под либо не стартует, либо запускается и затем падает. Если под не в состоянии Running и Ready, Kubernetes обычно уже указывает причину в статусе и событиях.

ФазаЧто означает
PendingПод принят, но ещё не запущен: ждёт планирования, загрузки образа или тома.
RunningХотя бы один контейнер работает.
SucceededВсе контейнеры завершились успешно (типично для Job).
FailedВсе контейнеры завершились, хотя бы один с ошибкой.
UnknownKubernetes не может получить состояние пода, часто из-за проблем с узлом.

Под не стартует: три места отказа

Запуск пода обычно ломается на одном из трёх этапов: загрузка образа, планирование или создание контейнера.

Ошибки загрузки образа (ErrImagePull, ImagePullBackOff). Чаще всего это опечатка в имени или теге образа. Вторая частая причина — нет учётных данных для приватного реестра. Kubernetes будет повторять попытки, и в итоге статус станет ImagePullBackOff.

kubectl describe pod <pod> -n <ns>
kubectl get pod <pod> -n <ns> -o jsonpath='{.spec.containers[*].image}'

Проверьте имя и тег, а для приватного реестра — наличие imagePullSecrets у пода или ServiceAccount.

Сетевые политики

NetworkPolicy ограничивает, какие поды могут обращаться друг к другу. Если правило неверно, трафик просто отбрасывается: ни ошибки, ни записи в логах, только таймауты. Если внутри namespace связь работает, а между namespace нет, причина часто именно в политике. Проверяйте и входящие (ingress), и исходящие (egress) правила.

kubectl get networkpolicy -n <ns>
kubectl describe networkpolicy <name> -n <ns>

3. Постоянное хранилище

PersistentVolumeClaim, который остаётся в состоянии Pending, означает, что Kubernetes не нашёл подходящий том. В большинстве случаев дело в несоответствии StorageClass: класс не существует, не назначен по умолчанию, или не поддерживает нужный access mode или размер. Пока том не привязан, под не запустится. Сначала проверяйте PVC и события, и только потом всё остальное.

kubectl describe pvc <pvc-name> -n <ns>
kubectl get storageclass
kubectl get pv

Типичное событие в такой ситуации: ProvisioningFailed с сообщением, что StorageClass не найден. Исправляется указанием существующего класса или созданием недостающего.

Если хранилище требует времени на подключение, под может долго оставаться в Pending. Не спешите пересоздавать PVC: сначала посмотрите события, возможно, проблема в узле или квоте.

4. Узлы и kubelet

Kubelet — агент на каждом узле. Он взаимодействует со средой выполнения контейнеров, управляет подами, подключает тома и сообщает о состоянии узла. Если kubelet работает плохо, проблемы появляются у всех подов этого узла.

Одна из частых проблем связана с PLEG (Pod Lifecycle Event Generator). Этот механизм kubelet отслеживает изменения состояния контейнеров через среду выполнения (containerd или CRI-O). Под высокой нагрузкой или при неисправном рантайме PLEG начинает отставать: в логах kubelet появляются предупреждения, статусы подов обновляются с задержкой, перезапуски занимают больше времени.

kubectl get nodes
kubectl describe node <node>
journalctl -u kubelet --since "30 min ago" --no-pager | grep -i pleg

Если в describe узла есть условия NotReady, MemoryPressure или DiskPressure, начинайте с ресурсов узла и состояния рантайма.

Не перезапускайте kubelet и не перезагружайте узел наугад: это может вызвать каскад пересоздания подов. Сначала посмотрите события и логи, затем решайте, что переводить под другой узел через cordon и drain.

5. Порядок действий при инциденте

  1. Посмотреть события в нужном namespace, отсортированные по времени.
  2. Проверить фазу и статус пода, затем kubectl describe pod.
  3. Определить этап отказа: образ, планирование, том, контейнер или сеть.
  4. Если проблема в хранилище, проверить PVC и StorageClass.
  5. Если проблема в сети, проверить NetworkPolicy и Service.
  6. Если проблема общая для нескольких подов, проверить узел и kubelet.
  7. Исправить причину и только потом перезапускать или пересоздавать поды.
Начинайте с событий: почти всегда Kubernetes уже записал причину. Сочетание kubectl get events --sort-by=.metadata.creationTimestamp и kubectl describe по нужному объекту закрывает большинство вопросов.