← назад к разделу

Снаружи все инциденты в Kubernetes выглядят одинаково — «сервис не работает». Но причины разные: упал сам процесс, кончилась память, не скачался образ, не прошла проверка здоровья, сломалась маршрутизация. Эта статья — набор команд и пошаговый разбор типичных ситуаций: по симптому находим причину и понимаем, что делать.

Базовый набор команд

Прежде чем разбирать конкретные симптомы — десяток команд, которые нужны постоянно. Все примеры с неймспейсом payments, подставьте свой.

kubectl -n payments get pods                                  # общее состояние: STATUS, RESTARTS, AGE
kubectl -n payments describe pod order-service-xxx           # подробности пода: события, причины
kubectl -n payments logs order-service-xxx                   # логи текущего контейнера
kubectl -n payments logs order-service-xxx -p                # логи ПРЕДЫДУЩЕГО запуска (до рестарта!)
kubectl -n payments logs deploy/order-service --tail=200 -f  # логи всех реплик деплоймента
kubectl -n payments get events --sort-by=.lastTimestamp      # лента событий неймспейса
kubectl -n payments exec -it order-service-xxx -- sh         # шелл внутри контейнера
kubectl -n payments port-forward svc/order-service 8080:80   # сервис к себе на localhost
kubectl -n payments top pods                                  # фактический CPU и память
kubectl -n payments get endpoints order-service              # кто реально стоит за Service
kubectl -n payments rollout status deploy/order-service      # как идёт выкатка

Две команды недооценены больше остальных. logs -p — единственный способ увидеть, что происходило до рестарта: текущие логи начинаются с нуля после перезапуска. get events --sort-by=.lastTimestamp — Kubernetes прямым текстом пишет причины: не хватило памяти на ноде, не смог скачать образ, проверка здоровья провалилась.

CrashLoopBackOff: под перезапускается снова и снова

Под стартует, падает, Kubernetes ждёт (пауза нарастает с каждым разом) и перезапускает снова. Это не отдельная проблема — это симптом: приложение завершается. Причина внутри.

Порядок разбора:

  1. logs -p — что сказало приложение перед тем, как упасть? Стектрейс? Сообщение «port already in use»? Ошибка чтения конфига?
  2. describe pod — смотрим exit code. Код 1 — процесс упал сам, причина в логах. Код 137 — процесс убит снаружи, см. OOMKilled ниже.
  3. Если логов нет совсем — приложение не успело добраться до логгера: проверьте entrypoint образа и настройки логирования.

Отдельный частый случай — убийство liveness probe. Приложение запускается 90 секунд, а liveness probe начинает проверки через 30 — под убивается снова и снова, так и не успевая стартовать. Лечится startup probe с честным failureThreshold. Подробнее про probes — в статье Spring Boot в Kubernetes.

OOMKilled: контейнер убит из-за памяти

Контейнер превысил memory limit — и ядро операционной системы его убило. Мгновенно, без стектрейса и прощальных сообщений в логах. В выводе describe pod будет: Last State: Terminated, Reason: OOMKilled.

Exit code при этом — 137 (128 + сигнал SIGKILL).

Для приложений на виртуальной машине — Java (JVM), .NET, Kotlin — причина почти всегда одна из двух: рантайм не знает об ограничении контейнера и выделяет heap пропорционально всей памяти ноды, а не лимиту. Современные JVM умеют читать cgroup-лимиты автоматически начиная с Java 10 — убедитесь, что версия подходящая и нужные флаги выставлены. Подробнее — в настройках ресурсов.

Важно не путать: OutOfMemoryError в логах — это не OOMKilled. Это heap закончился внутри живого процесса. Лечится по-другому: смотрим, что держит память, и либо увеличиваем heap, либо ищем утечку.

ImagePullBackOff: образ не скачивается

Нода не может загрузить образ из реестра. Три причины закрывают почти всё:

  • Опечатка в теге, или тег не был отправлен — CI собрал образ, но push упал.
  • Нет прав к реестру: protух imagePullSecret или он вовсе не указан.
  • Реестр недоступен с ноды.

describe pod покажет точную ошибку реестра в разделе events. Это единственный инцидент из всех, где код приложения гарантированно ни при чём.

Pending: под висит и никуда не идёт

Под создан, но Kubernetes не назначил его ни на одну ноду. describe pod → events → там будет причина словами.

Самые частые:

  • Insufficient memory / Insufficient cpu — ни на одной ноде нет столько свободных requests. Планирование идёт по requests, а не по фактическому потреблению. Кластер может быть «полон» при низком реальном использовании.
  • Несовпадение nodeSelector, affinity или taints — под ищет ноду с определёнными метками, но таких нет.

Что делать разработчику: проверить, не завышены ли requests у сервиса. Если нет — разговор с командой, которая управляет кластером, про ёмкость.

Мигающая readiness: соседи получают 503

Симптом: сервис «работает», но потребители периодически ловят 503 или таймауты. Под то входит в ротацию, то выпадает.

Причина — readiness probe нестабильна. Когда под не проходит проверку, Kubernetes убирает его из endpoints: трафик на него не идёт. Когда проходит — возвращает обратно.

Типичные сценарии:

  • В readiness включена нестабильная внешняя зависимость. Мигает она — мигает весь сервис.
  • GC-паузы или перегрузка заставляют probe не укладываться в timeout.
  • Слишком агрессивные periodSeconds и failureThreshold.

Проверка: kubectl get endpoints несколько раз подряд — список то сокращается, то восстанавливается. В describe podReadiness probe failed в событиях.

Решение: вынести из readiness зависимости, без которых сервис может отвечать в деградированном режиме, и скорректировать пороги.

«Запрос не доходит»: проверяем цепочку

Снаружи 502 или 504, а поды зелёные. Проверяем цепочку по пути запроса сверху вниз, каждое звено отдельно:

kubectl -n payments get ingress api                               # 1. Ingress есть, host/path верные?
kubectl -n payments get endpoints order-service                  # 2. За Service есть поды?
kubectl -n payments port-forward svc/order-service 8080:80       # 3. Service отвечает?
kubectl -n payments port-forward pod/order-service-xxx 8080:8080 # 4. Сам под отвечает?

Где цепочка рвётся — там и уровень проблемы:

  • Шаг 4 не работает → проблема в приложении.
  • Шаги 2–3 → selector или readiness.
  • Шаг 1 → Ingress, DNS или TLS.

Пустые endpoints при живых подах — почти всегда readiness или опечатка в selector (метки пода не совпадают с selector сервиса — после переименования манифестов такое бывает). Также стоит проверить NetworkPolicy: «запрос не доходит» между неймспейсами может быть политикой, а не поломкой.

Под перезапустился «сам»

RESTARTS > 0 без деплоя — у рестарта всегда есть причина, и она записана. describe pod → Last State. Варианты:

  • OOMKilled — см. выше.
  • Liveness probe failed — проверьте, не проверяет ли она внешнюю базу данных или другой сервис.
  • Нода ушла в drain или на обновление — это штатная ситуация. Поды обязаны переживать переезд: для этого нужны PodDisruptionBudget и минимум две реплики.
  • Evicted — нода исчерпала дисковое пространство или другой ресурс и вытеснила под.

Что должно быть до инцидента

Всё описанное разбирается за минуты, когда у сервиса есть базовая гигиена:

  • Структурированные логи в stdout — платформа их собирает. Файлы внутри контейнера умирают вместе с ним.
  • Метрики в формате Prometheus — де-факто стандарт в Kubernetes.
  • Алерты на рестарты и недоступность endpoints.
  • Дашборд с памятью и CPU по подам в сравнении с limits.

Без этого отладка превращается в угадывание. Подробнее — в Observability Style Guide.

Коротко

  • logs -p показывает логи до рестарта — это первое, что смотрят при CrashLoopBackOff.
  • get events --sort-by=.lastTimestamp — Kubernetes прямым текстом пишет, что пошло не так.
  • CrashLoopBackOff — приложение падает; exit code 1 → смотрим логи, exit code 137 → OOMKilled.
  • OOMKilled: рантайм не видит cgroup-лимит или лимит мал; в логах следа нет.
  • ImagePullBackOff: тег не существует, нет прав к реестру или реестр недоступен.
  • Pending: requests не помещаются на ноде; планирование идёт по requests, не по факту.
  • Мигающая readiness → под выпадает из endpoints → 503 у потребителей.
  • 502/504 при живых подах: проверяем цепочку Ingress → Service → endpoints → под.

Что почитать дальше

  • Spring Boot в Kubernetes — probes и ресурсы: профилактика половины этих ситуаций.
  • Сеть и трафик — endpoints, Ingress и NetworkPolicy.
  • Деплой и конфигурация — rollout status и откаты.
  • Observability Style Guide — логи, метрики и алерты, без которых отладка слепа.