Практическая шпаргалка для инцидентов: где искать причину и как читать сигналы кластера
Когда что-то ломается, Kubernetes обычно создаёт объект Event. Это не логи приложения, а сообщения компонентов кластера: планировщика, kubelet и контроллеров. Они объясняют, почему система приняла то или иное решение, а не только показывают текущее состояние.
kubectl get events -n production --sort-by=.metadata.creationTimestamp kubectl get events -n production --field-selector type=Warning
Часто повторяющиеся события подсказывают направление поиска:
Под проходит фазы Pending, Running, Succeeded, Failed и Unknown. Большинство проблем возникает на раннем этапе, когда под либо не стартует, либо запускается и затем падает. Если под не в состоянии Running и Ready, Kubernetes обычно уже указывает причину в статусе и событиях.
| Фаза | Что означает |
|---|---|
| Pending | Под принят, но ещё не запущен: ждёт планирования, загрузки образа или тома. |
| Running | Хотя бы один контейнер работает. |
| Succeeded | Все контейнеры завершились успешно (типично для Job). |
| Failed | Все контейнеры завершились, хотя бы один с ошибкой. |
| Unknown | Kubernetes не может получить состояние пода, часто из-за проблем с узлом. |
Запуск пода обычно ломается на одном из трёх этапов: загрузка образа, планирование или создание контейнера.
Ошибки загрузки образа (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>
PersistentVolumeClaim, который остаётся в состоянии Pending, означает, что Kubernetes не нашёл подходящий том. В большинстве случаев дело в несоответствии StorageClass: класс не существует, не назначен по умолчанию, или не поддерживает нужный access mode или размер. Пока том не привязан, под не запустится. Сначала проверяйте PVC и события, и только потом всё остальное.
kubectl describe pvc <pvc-name> -n <ns> kubectl get storageclass kubectl get pv
Типичное событие в такой ситуации: ProvisioningFailed с сообщением, что StorageClass не найден. Исправляется указанием существующего класса или созданием недостающего.
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, начинайте с ресурсов узла и состояния рантайма.
kubectl describe pod.kubectl get events --sort-by=.metadata.creationTimestamp и kubectl describe по нужному объекту закрывает большинство вопросов.