Kubernetes: диагностика
Диагностика CrashLoopBackOff, Pending, OOMKilled, Evicted и ошибок ImagePull, node NotReady, зависших выкаток и 502 от Ingress по выводу kubectl.
12 вопросов
MiddleДебаггингОчень частоPod в CrashLoopBackOff — как отличить падение приложения от проваленной liveness-пробы?
Pod в CrashLoopBackOff — как отличить падение приложения от проваленной liveness-пробы?
CrashLoopBackOff значит, что контейнер умирает, а kubelet ждёт — но не почему. Смотрите logs --previous и lastState.terminated: Reason Error, Exit 1 — падение кода. Убийство liveness даёт Liveness probe failed; выход 137 — SIGKILL.
Типичные ошибки
- ✗Считать
CrashLoopBackOffкорневой причиной, а не симптомом - ✗Читать живые логи вместо
logs --previousдля мёртвого контейнера - ✗Считать любой рестарт багом кода, упуская убийство liveness-пробой
Уточняющие вопросы
- →Какой код выхода ждёте при OOM-убийстве и чем он отличается от этого случая?
- →Как слишком агрессивный
initialDelaySecondsу liveness вызывает crash loop?
MiddleДебаггингОчень частоPod остаётся Pending без назначенного узла — что проверяете и в каком порядке?
Pod остаётся Pending без назначенного узла — что проверяете и в каком порядке?
Pending значит, что планировщик не разместил Pod. Строка FailedScheduling называет причину — здесь Insufficient memory: узел не вмещает memory requests. Прочее: taint, нет узла под nodeSelector/affinity или несвязанный PVC.
Типичные ошибки
- ✗Путать
Pending(не размещён) с ещё-не-Ready работающим контейнером - ✗Игнорировать сообщение
FailedScheduling, называющее точную причину - ✗Считать причиной лишь ёмкость, упуская taints, affinity и привязку PVC
Уточняющие вопросы
- →Чем отличалось бы сообщение
FailedSchedulingпри нетолерируемом taint? - →Почему снижение memory
requestдаёт размещение, но грозит OOM позже?
JuniorДебаггингЧастоPod застрял в ImagePullBackOff — какие обычные причины и что проверить первым?
Pod застрял в ImagePullBackOff — какие обычные причины и что проверить первым?
ImagePullBackOff — kubelet не смог скачать образ и делает паузы. Смотрите Events в describe — здесь latset опечатка, реестр отвечает not-found; исправьте тег. Прочее: нет imagePullSecret, неверный хост или лимит на пул.
Типичные ошибки
- ✗Путать
ImagePullBackOffс падающим контейнером вместо неудачного пула - ✗Пропускать Events в
describe, где назван точный сбой пула - ✗Забывать, что приватному образу нужен
imagePullSecret
Уточняющие вопросы
- →Как подключить
imagePullSecret, чтобы Pod тянул из приватного реестра? - →Чем изменяемый тег вроде
latestрискован для воспроизводимых выкатов?
JuniorДебаггингЧастоPod не работает и не пишет полезных логов — какие команды kubectl запускаете и в каком порядке?
Pod не работает и не пишет полезных логов — какие команды kubectl запускаете и в каком порядке?
Сначала kubectl describe pod — он показывает Events, Conditions и State/lastState с кодом выхода. Если процесс умер, kubectl logs --previous читает его stdout; kubectl get events даёт контекст. Гадайте только после describe.
Типичные ошибки
- ✗Считать статус
Runningдоказательством, что контейнер здоров - ✗Забывать про
logs --previousдля уже перезапущенного контейнера - ✗Гадать с фиксами до чтения Events в
describe
Уточняющие вопросы
- →Что блок
lastState.terminatedконтейнера говорит такого, чего не дадут живые логи? - →Когда вы возьмёте
kubectl debugвместоlogsиdescribe?
MiddleДебаггингЧастоIngress отдаёт 503, хотя Pod у Service вроде живы — проследите, где теряется трафик.
Ingress отдаёт 503, хотя Pod у Service вроде живы — проследите, где теряется трафик.
503 при пустом kubectl get endpoints api значит, что у Service нет готовых бэкендов, kube-proxy некуда маршрутизировать. Две причины: readiness не проходит, поды 0/1 Running и вне Service, либо selector не совпадает с метками подов.
Типичные ошибки
- ✗Винить Ingress-контроллер до проверки endpoints у Service
- ✗Забывать, что не-Ready под убирается из endpoints Service
- ✗Упускать селектор Service, не совпадающий с метками подов
Уточняющие вопросы
- →Чем readiness-проба отличается от liveness в этом сбое?
- →Какой командой сверить селектор Service с метками работающего пода?
MiddleДебаггингЧастоУзел в NotReady, но его Pod всё ещё Running и недоступны — диагностируйте.
Узел в NotReady, но его Pod всё ещё Running и недоступны — диагностируйте.
Узел перестал слать статус и стал NotReady; поды всё ещё Running, ведь запись сделана до сбоя — молчит kubelet. Проверяйте узел: мёртвый kubelet, давление диска/памяти или потеря сети до control plane. За таймаутом поды перепланируются.
Типичные ошибки
- ✗Верить устаревшему
Runningна узле, переставшем отчитываться - ✗Считать, что упало приложение, когда сбоит heartbeat kubelet
- ✗Не знать, что поды NotReady-узла вытесняются после таймаута
Уточняющие вопросы
- →Каков дефолтный таймаут toleration
node.kubernetes.io/unreachableдо вытеснения? - →Как с узла подтвердить, что виноват kubelet, а не сеть?
MiddleДебаггингЧастоКонтейнер показывает Reason OOMKilled и Exit Code 137 — объясните и исправьте.
Контейнер показывает Reason OOMKilled и Exit Code 137 — объясните и исправьте.
Выход 137 — это 128 + 9 (SIGKILL), а Reason OOMKilled значит, что cgroup убил контейнер за превышение memory limit (128Mi). Поднимите лимит до реального рабочего набора или устраните утечку. Низкий CPU-лимит лишь тормозит — не убивает.
Типичные ошибки
- ✗Читать выход 137 как что-то, кроме SIGKILL (128 + 9)
- ✗Путать OOM-убийство по лимиту памяти с CPU-throttling
- ✗Слепо поднимать лимит, не проверив заодно утечку
Уточняющие вопросы
- →Как memory
requests/limitsзадают класс QoS пода и порядок вытеснения? - →Почему лимит памяти жёстко убивает, а CPU-лимит лишь тормозит?
MiddleДебаггингИногдаkubectl exec не работает — в образе нет shell; как получить оболочку для отладки?
kubectl exec не работает — в образе нет shell; как получить оболочку для отладки?
Образ distroless, поэтому sh для exec нет. Подключите эфемерный отладочный контейнер, делящий namespace цели: kubectl debug -it api-5f6 --image=busybox --target=api. --target делит process-namespace — видны процессы приложения. Без пересборки.
Типичные ошибки
- ✗Считать, что distroless-под нельзя отладить без пересборки
- ✗Забывать
--target, из-за чего не видно процессов приложения - ✗Путать
kubectl debugс обычнымexecв тот же контейнер
Уточняющие вопросы
- →Чем distroless-образ без shell полезен для безопасности в проде?
- →Что меняет
--targetпо сравнению с его отсутствием вkubectl debug?
MiddleДебаггингИногдаPod вытеснен из-за нехватки ephemeral-storage на узле — найдите причину и исправьте.
Pod вытеснен из-за нехватки ephemeral-storage на узле — найдите причину и исправьте.
Это вытеснение по давлению узла: узел получил DiskPressure и вытеснил Pod, занявший 4Gi ephemeral-storage без request. Это диск узла под логи, emptyDir и writable-слой. Фикс: ephemeral-storage requests/limits или PersistentVolume под данные.
Типичные ошибки
- ✗Читать
Evictedкак OOM, а не вытеснение по давлению узла - ✗Не знать, что логи,
emptyDirи writable-слой — это ephemeral-storage - ✗Оставлять ephemeral-storage requests/limits пустыми у прожорливого пода
Уточняющие вопросы
- →Как класс QoS и приоритет пода меняют, кого kubelet вытеснит первым?
- →Почему под без ephemeral-storage
requestвытесняется раньше того, кто его задал?
SeniorДебаггингИногдаВсе Pod стали CreateContainerConfigError после изменения конфигурации — найдите причину.
Все Pod стали CreateContainerConfigError после изменения конфигурации — найдите причину.
CreateContainerConfigError — ошибка создания, не падение: kubelet не может собрать контейнер, потому что нужного ConfigMap/Secret или ключа нет. Здесь env берёт DB_PASSWORD из Secret, но изменение удалило ключ — верните его или поправьте ссылку.
Типичные ошибки
- ✗Читать
CreateContainerConfigErrorкак падение с логами для чтения - ✗Упускать, что удалённый ключ Secret/ConfigMap блокирует создание
- ✗Не считать это Waiting-состоянием как
ImagePullBackOff
Уточняющие вопросы
- →Как пометка env
valueFromкакoptional: trueменяет этот сбой? - →Почему переименование Secret и удаление ключа дают один и тот же симптом?
SeniorДебаггингИногдаПериодические 5xx идут только от Pod на одном узле — отделите узловую причину от прикладной.
Периодические 5xx идут только от Pod на одном узле — отделите узловую причину от прикладной.
Один образ и конфиг, но ошибки только на node-7, изолируем к узлу, не к приложению. Группируйте по spec.nodeName: выделяется один узел — приложение оправдано. Подозреваемые: давление памяти/диска, плохой CoreDNS или kube-proxy, полный conntrack. Cordon и drain.
Типичные ошибки
- ✗Винить приложение до группировки ошибок по
spec.nodeName - ✗Упускать давление памяти/диска узла, ведущее к OOM и вытеснению
- ✗Забывать про CoreDNS, kube-proxy и conntrack узла как подозреваемых
Уточняющие вопросы
- →Почему полная таблица conntrack на узле даёт периодические, а не постоянные 5xx?
- →Что делает
kubectl cordonи чтоdrainдобавляет сверху?
SeniorДебаггингИногдаВыкат Deployment деградировал с ProgressDeadlineExceeded — разберите застой.
Выкат Deployment деградировал с ProgressDeadlineExceeded — разберите застой.
ProgressDeadlineExceeded значит, что новый ReplicaSet не набрал Ready-подов за progressDeadlineSeconds; выкат застывает, сам не откатывается, а maxUnavailable держит старые поды. Опишите новый под — обычно readiness, ImagePull, ёмкость или PDB.
Типичные ошибки
- ✗Ждать, что
ProgressDeadlineExceededсам откатит, а не застынет - ✗Не описывать новый под, чтобы понять, почему он не Ready
- ✗Упускать readiness, ImagePull, ёмкость и PDB как обычные причины
Уточняющие вопросы
- →Как
maxUnavailableиmaxSurgeформируют, что остаётся доступным при застое? - →Когда
kubectl rollout undoуместнее, чем чинить новые поды вперёд?