ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

Kubernetes CrashLoopBackOff: события, пробы, exit codes и backoff — практический разбор

CrashLoopBackOff в Kubernetes — не «ошибка», а симптом: контейнер быстро завершается, kubelet перезапускает его и увеличивает паузу (backoff). Ниже — практический алгоритм: events, kubectl describe и logs --previous, плюс разбор OOMKilled/exit 137 и типичных ошибок probes.
Kubernetes CrashLoopBackOff: события, пробы, exit codes и backoff — практический разбор

Что такое CrashLoopBackOff и почему это важно

CrashLoopBackOff — состояние Pod’а, при котором kubelet пытается запустить контейнер, контейнер быстро завершается, затем kubelet запускает его снова, но с увеличивающейся задержкой между попытками. Эта задержка и называется backoff.

Ключевая мысль: CrashLoopBackOff почти никогда не «лечится» ожиданием. Пока причина завершения процесса внутри контейнера не устранена, Pod будет крутиться в цикле «старт → падение → пауза → старт».

Чаще всего причина в одном из сценариев:

  • приложение падает из‑за ошибки конфигурации/переменных окружения/секретов;
  • процесс убивается по памяти: OOMKilled и часто exit code 137;
  • контейнер «живой», но его убивает livenessProbe;
  • долгий старт без корректной startupProbe (миграции, прогрев, загрузка зависимостей);
  • ошибки в entrypoint/команде запуска, отсутствие бинарника, права, файловые пути.

С чего начать: быстрый чек-лист команд

Ниже набор команд, который в большинстве случаев быстро выводит на первопричину. Порядок важен: он соответствует тому, как kubelet «видит» проблему.

1) Посмотреть статус Pod и контейнеров

kubectl get pod -n <namespace> <pod> -o wide

Смотрите колонку STATUS (обычно будет CrashLoopBackOff) и RESTARTS (растёт). Если Pod управляется Deployment/StatefulSet, полезно сразу понять, какой ReplicaSet/Revision активен.

2) Посмотреть причины рестартов через kubectl describe

kubectl describe pod -n <namespace> <pod>

kubectl describe почти всегда показывает «скелет» проблемы: почему контейнер в последний раз завершился, кто его убил, и какие события происходили вокруг (pull image, probes, OOM, ошибки монтирования томов).

Что искать в выводе:

  • в секции Containers: Last State, State, Reason, Exit Code, Started/Finished;
  • внизу в Events: Back-off restarting failed container, OOMKilled, Liveness probe failed, Readiness probe failed, ошибки volume mount.

3) Забрать логи «предыдущего» падения: kubectl logs --previous

kubectl logs -n <namespace> <pod> --previous

Команда kubectl logs --previous критична при CrashLoopBackOff: текущий контейнер может ещё не успеть вывести лог, а предыдущий — уже упал и оставил след. Если контейнеров несколько, добавьте -c <container>.

kubectl logs -n <namespace> <pod> -c <container> --previous

Если логов нет вообще, это тоже сигнал: процесс падает до инициализации логгера, entrypoint не запускается, либо приложение пишет в файл, а не в stdout/stderr.

4) События в namespace (иногда полезнее, чем describe одного Pod)

kubectl get events -n <namespace> --sort-by=.lastTimestamp

Иногда проблема «рядом»: не создался Secret, не смонтировался PVC, не вытянулся образ, нет прав ServiceAccount — а Pod проявляет это как CrashLoopBackOff.

Пример: kubectl describe pod с событиями, Last State и причиной завершения контейнера

Как читать exit codes и понять, кто «убил» контейнер

Exit code — это «финальная точка», которая часто экономит часы. Kubernetes показывает его в kubectl describe в контейнерной секции.

Exit code 137: что означает и почему это часто OOM

exit code 137 обычно означает, что процесс завершён сигналом SIGKILL (9), то есть его «жёстко» убили. Типичный сценарий в Kubernetes — OOMKilled, когда контейнер превысил лимит памяти.

Как подтвердить OOM:

  • в kubectl describe pod ищите Last State: Terminated и Reason: OOMKilled;
  • в Events встречаются сообщения про OOM или давление памяти;
  • по метрикам видно, что потребление упиралось в limits.memory.

Важно: exit code 137 бывает не только от OOM. Контейнер могут убить и по другим причинам (eviction при давлении ресурсов на ноде, остановка ноды, ручное удаление Pod’а). Всегда сверяйтесь с Reason и Events.

Частые exit codes при CrashLoopBackOff

  • 1 — приложение само завершилось с ошибкой (конфиг, миграции, недоступна БД и т. п.).
  • 2 — часто ошибка аргументов/CLI: неверные флаги, неверная команда.
  • 126 — команда найдена, но не исполняется (права, noexec, несовместимость).
  • 127 — команда не найдена (неверный entrypoint/command, отсутствует бинарник).
  • 137 — SIGKILL, часто OOMKilled.
  • 139 — segfault (ошибка приложения, нативные зависимости, баги).
FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Backoff: почему рестарты замедляются и как это мешает диагностике

backoff — защитный механизм: чтобы не «забить» ноду постоянными рестартами, kubelet увеличивает задержку между попытками запуска контейнера. В Events это выглядит как Back-off restarting failed container.

Backoff не исправляет проблему — он делает её менее разрушительной для кластера. Ваша задача — понять, почему контейнер завершился, а не «разогнать» рестарты.

Практические приёмы, чтобы не потерять «улики»:

  • используйте kubectl logs --previous сразу после рестарта;
  • если падение мгновенное, временно увеличьте уровень логирования приложения через env, чтобы успеть увидеть причину;
  • держите централизованный сбор логов: при частых рестартах это сильно экономит время (подходы к пайплайнам и меткам можно сверить в материале про лейблы и пайплайны Loki).

Probes и CrashLoopBackOff: когда контейнер убивает не приложение, а проверка

Частый сценарий: приложение в целом работает, но kubelet регулярно его убивает из‑за неверно настроенной livenessProbe. Или Pod никогда не становится Ready из‑за readinessProbe, а дальше начинается «пила» рестартов из‑за деплоя/автоскейлинга, которую легко принять за падение приложения.

Liveness vs Readiness vs Startup: что и когда использовать

  • livenessProbe — «жив ли процесс». Если проваливается, kubelet перезапускает контейнер.
  • readinessProbe — «готов ли принимать трафик». Если проваливается, контейнер не убивают, но Pod исключают из endpoints.
  • startupProbe — защита медленного старта: пока она не успешна, livenessProbe не должна «рубить» контейнер за то, что он ещё запускается.

Как понять, что виновата probe

В kubectl describe в секции Events вы увидите строки вида:

Liveness probe failed: ...
Readiness probe failed: ...

Если есть Liveness probe failed, а затем рестарт — это почти прямое попадание. Дальше важно понять, что именно не так: порт, path, таймауты или логика эндпоинта.

Типовые ошибки конфигурации probes:

  • слишком маленькие timeoutSeconds и failureThreshold для реального времени ответа;
  • health endpoint зависит от внешних ресурсов (БД/очереди), и кратковременная деградация приводит к рестарту вместо ожидания;
  • нет startupProbe при долгой инициализации: livenessProbe начинает проверять слишком рано;
  • проверка идёт на неправильный порт/путь или не учитывает префикс/host header.

Практический паттерн: добавить startupProbe и ослабить liveness

Если приложение стартует долго (миграции, прогрев, загрузка моделей), добавление startupProbe обычно резко снижает ложные рестарты. livenessProbe при этом имеет смысл сделать более «терпимой», чтобы рестарт происходил только при реальном зависании, а не при кратком всплеске задержек.

OOMKilled и память: почему контейнер падает «без логов»

OOMKilled — классика для CrashLoopBackOff. Контейнер может отработать несколько секунд, съесть память на старте и быть убитым раньше, чем успеет записать полезный лог. Вы увидите exit code 137, рост рестартов и backoff.

Что делать по шагам:

  1. Подтвердить Reason: OOMKilled в kubectl describe.
  2. Проверить resources.limits.memory и resources.requests.memory в манифесте или Helm values.
  3. Сверить лимиты приложения с лимитами контейнера (например, Java heap, число воркеров, размеры буферов).
  4. Если память «ползёт» со временем — подозревать утечку и включать профилирование/метрики, а не просто поднимать лимит бесконечно.

Отдельный нюанс QoS: если у контейнера нет requests/limits, он может быть менее предсказуемо выселен при давлении памяти на ноде. А строгий limits.memory, наоборот, даёт воспроизводимый OOM внутри cgroup — и это часто проще диагностировать.

Схема: контейнер упирается в лимит памяти и получает OOMKilled с exit code 137

Ошибки конфигурации и окружения: когда приложение честно выходит с code 1

Второй по частоте сценарий: приложение валится с Exit Code: 1 из‑за отсутствующих переменных окружения, неправильных строк подключения, неверных путей к файлам, отсутствующих сертификатов, миграций, которые не проходят.

Практика диагностики:

  • сначала kubectl logs --previous — обычно там стек/сообщение об ошибке;
  • потом внимательно проверить env/volumeMounts в kubectl describe: смонтировались ли Secret/ConfigMap, те ли ключи и имена;
  • если используются initContainers — проверить их логи отдельно: основная app может не стартовать, потому что init не завершился.

Как не «стрелять себе в ногу»: приёмы при расследовании

Уточняйте, какой контейнер падает

В Pod’е может быть несколько контейнеров (sidecar, прокси, агент логов). CrashLoopBackOff относится к конкретному контейнеру. Всегда указывайте -c в логах и смотрите секцию каждого контейнера в kubectl describe.

Не путайте рестарты контейнера и пересоздание Pod

RESTARTS — это рестарты контейнеров внутри одного Pod. Если контроллер пересоздаёт Pod заново (rollout, переселение, выселение), вы увидите новые Pod’ы с нулевыми рестартами, но с той же ошибкой. Поэтому полезно смотреть events по namespace.

Временная пауза для анализа (когда нужно «остановить мясорубку»)

Если рестарты слишком частые и мешают анализу, иногда проще временно масштабировать Deployment в 0, поправить конфиг/секрет, затем вернуть реплики. Это особенно уместно, если падение вызвано явной ошибкой конфигурации и вы хотите избежать нагрузки на внешние сервисы (БД, брокер).

Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

Мини-алгоритм: от CrashLoopBackOff к первопричине

  1. Соберите контекст: kubectl get pod, имя контейнера, число рестартов, время последнего рестарта.
  2. Прочитайте факты kubelet: kubectl describe pod, секции Last State и Events.
  3. Достаньте логи падения: kubectl logs --previous (при необходимости с -c).
  4. Классифицируйте:
  • OOMKilled / exit code 137 → память/лимиты/утечки.
  • Liveness probe failed → настройка probes/таймаутов, часто нужна startupProbe.
  • Exit Code: 127/126 → entrypoint/command/права/образ.
  • Exit Code: 1 → конфиг/секреты/доступы/миграции/зависимости.

Проверьте внешние зависимости: DNS, сервисы, БД/очереди, PVC, права ServiceAccount — через events и логи. Если нужна системная «страховка» для воркеров и очередей (чтобы перезапуски были предсказуемыми), может пригодиться разбор про Supervisor и systemd для воркеров.

Типовой пример: «падает на старте, потом backoff, логов мало»

Если вы видите CrashLoopBackOff, в events — backoff, а в логах почти пусто, чаще всего это один из трёх случаев:

  • OOMKilled на старте: подтверждается Reason: OOMKilled и нередко exit code 137.
  • Неверная команда запуска: exit code 127 или 126.
  • Слишком агрессивная livenessProbe без startupProbe: в events будет Liveness probe failed.

Это хорошая «развилка» для быстрой диагностики: сначала describe, потом logs --previous, и только потом — глубокие гипотезы.

Что настроить заранее, чтобы CrashLoopBackOff расследовался быстрее

  • Пишите важные ошибки старта в stdout/stderr (не только в файл).
  • Делайте health endpoints простыми и быстрыми; не завязывайте livenessProbe на внешние зависимости.
  • Используйте startupProbe для долгого старта, а readinessProbe — для готовности принимать трафик.
  • Задавайте requests/limits осмысленно и согласуйте лимиты приложения (heap/worker’ы) с лимитами контейнера.
  • Собирайте события и логи централизованно — тогда рестарты и backoff не «съедят» улики.

Итог

CrashLoopBackOff — это сигнал от Kubernetes: «контейнер не удерживается в рабочем состоянии, и я уже начал увеличивать backoff». Самые полезные инструменты — kubectl describe (факты и events) и kubectl logs --previous (логи последнего падения). Дальше всё упирается в классификацию причины: OOMKilled/exit code 137, probes (livenessProbe/readinessProbe/startupProbe) либо ошибки запуска/конфига.

Если вы разворачиваете приложения на своих серверах, удобнее всего держать рабочие окружения на VDS: можно быстро подключить сбор метрик/логов, подобрать ресурсы под реальные пики и без боли пересобрать образ/рантайм при расследованиях.

Поделиться статьей

Вам будет интересно

Grafana Tempo + Loki + Prometheus: корреляция traceID и быстрый triage инцидентов OpenAI Статья написана AI (GPT 5)

Grafana Tempo + Loki + Prometheus: корреляция traceID и быстрый triage инцидентов

Пошагово связываем Grafana Tempo, Loki и Prometheus в единую observability-схему: OpenTelemetry-трейсы, логи с traceID и метрики. ...
Kubernetes DNS: таймауты, MTU и conntrack — диагностика через CoreDNS, tcpdump и PMTUD OpenAI Статья написана AI (GPT 5)

Kubernetes DNS: таймауты, MTU и conntrack — диагностика через CoreDNS, tcpdump и PMTUD

Если в Kubernetes периодически не резолвится DNS или внешние API отвечают timeout, причина часто в MTU/PMTUD, conntrack и настройк ...
Apache 403 Forbidden: права, Require, DocumentRoot, suEXEC и SELinux — практическая диагностика OpenAI Статья написана AI (GPT 5)

Apache 403 Forbidden: права, Require, DocumentRoot, suEXEC и SELinux — практическая диагностика

403 Forbidden в Apache почти всегда означает явный запрет: правило Require/Directory, несоответствие DocumentRoot/Alias, права на ...