Troubleshooting Kubernetes

TL;DR: Pod не работает → kubectl describe pod + kubectl logs. Pending = scheduling. CrashLoopBackOff = приложение падает. ImagePullBackOff = образ. Всегда проверяйте Events.

Алгоритм отладки

Pod не работает
  │
  ├─ Status: Pending
  │   └─ kubectl describe pod → Events
  │       ├─ Insufficient cpu/memory → увеличить ноду или уменьшить requests
  │       ├─ No nodes match selector → проверить nodeSelector/affinity/taints
  │       └─ PVC Pending → проверить StorageClass и PV
  │
  ├─ Status: ImagePullBackOff
  │   └─ kubectl describe pod → Events
  │       ├─ 404 Not Found → проверить имя образа и тег
  │       ├─ Unauthorized → создать imagePullSecrets
  │       └─ Timeout → проверить сеть ноды
  │
  ├─ Status: CrashLoopBackOff
  │   └─ kubectl logs pod (--previous)
  │       ├─ Ошибка приложения → исправить код или конфигурацию
  │       ├─ OOMKilled → увеличить memory limits
  │       └─ Permission denied → проверить securityContext
  │
  └─ Status: Running, но не отвечает
      ├─ kubectl logs pod → ошибки?
      ├─ kubectl exec -it pod -- curl localhost:PORT → приложение работает?
      ├─ kubectl get endpoints svc → Service видит поды?
      └─ kubectl describe ingress → правила маршрутизации?

Ключевые команды

# 1. Статус подов
kubectl get pods -o wide
kubectl get pods --field-selector status.phase!=Running
 
# 2. Events — САМЫЙ ПОЛЕЗНЫЙ источник информации
kubectl get events --sort-by=.metadata.creationTimestamp
kubectl get events --field-selector involvedObject.name=my-pod
 
# 3. Описание (events + конфигурация)
kubectl describe pod my-pod
kubectl describe svc my-service
kubectl describe node my-node
 
# 4. Логи
kubectl logs my-pod
kubectl logs my-pod -c sidecar          # конкретный контейнер
kubectl logs my-pod --previous          # предыдущий (упавший) контейнер
kubectl logs my-pod -f                  # stream
kubectl logs -l app=web --all-containers # все поды по label
 
# 5. Exec (зайти в контейнер)
kubectl exec -it my-pod -- /bin/sh
kubectl exec -it my-pod -- curl localhost:8080/health
kubectl exec -it my-pod -- env          # проверить env vars
kubectl exec -it my-pod -- cat /etc/resolv.conf  # DNS
 
# 6. Ресурсы
kubectl top pods --sort-by=memory
kubectl top nodes
 
# 7. Сеть
kubectl get endpoints my-service        # IP подов за Service
kubectl run debug --image=busybox -it --rm -- wget -qO- http://my-service

Проблемы по статусам

Pending

kubectl describe pod my-pod
# Events:
#   Warning  FailedScheduling  Insufficient cpu
#   Warning  FailedScheduling  0/3 nodes are available: 3 node(s) had taint
ПричинаРешение
Insufficient cpu/memoryУменьшить requests или добавить ноды
node(s) had taintДобавить toleration или убрать taint с ноды
no persistent volumes availableПроверить StorageClass, создать PV
Unschedulablekubectl uncordon <node>

ImagePullBackOff

kubectl describe pod my-pod
# Events:
#   Warning  Failed  Failed to pull image "myapp:v99": not found
ПричинаРешение
Образ не существуетПроверить имя и тег: docker pull myapp:v99
Private registryСоздать imagePullSecrets в Pod spec
Rate limit (DockerHub)Использовать authenticated pull или mirror

CrashLoopBackOff

kubectl logs my-pod --previous
kubectl describe pod my-pod | grep -A5 "Last State"
ПричинаРешение
OOMKilledУвеличить limits.memory. Проверить утечки памяти
Exit code 1Ошибка приложения — смотреть логи
Exit code 137Убит сигналом SIGKILL (OOM или preemption)
Exit code 0Контейнер завершился. Для long-running: не использовать Job
Config errorПроверить ConfigMap/Secret смонтированы: kubectl exec ... -- env

Running, но не отвечает

# 1. Приложение работает внутри?
kubectl exec -it my-pod -- curl localhost:8080
 
# 2. Service находит поды?
kubectl get endpoints my-service
# Если пусто — labels не совпадают
 
# 3. DNS работает?
kubectl run debug --image=busybox -it --rm -- nslookup my-service
 
# 4. Проверить readinessProbe
kubectl describe pod my-pod | grep -A10 "Readiness"

Debug Pod (временный отладочный контейнер)

# Запустить отладочный под в том же namespace
kubectl run debug --image=nicolaka/netshoot -it --rm -- /bin/bash
 
# Внутри:
curl http://my-service:80
nslookup my-service
dig my-service.default.svc.cluster.local
tcpdump -i any port 80
 
# Ephemeral debug container (K8s 1.23+)
kubectl debug my-pod -it --image=busybox --target=my-container

Типичные ошибки

ОшибкаСимптомРешение
Смотрят только kubectl get podsНе видят причину проблемыkubectl describe pod + kubectl get events
--previous не используют«Логов нет» для CrashLoopkubectl logs --previous показывает логи упавшего контейнера
Отладка сети из-за пределов кластераcurl: connection refusedЗапустить debug pod внутри кластера
Не проверяют endpoints«Service не работает»kubectl get ep svc-name — если пусто, labels не совпадают