KubernetesMiddleTechnical

Под в Pending. По какому алгоритму ты ищешь причину?

Алгоритм: kubectl describe pod (читаем Events) -> нехватка CPU/RAM на нодах -> taints без tolerations -> nodeSelector/affinity без подходящей ноды -> PVC в Pending -> ResourceQuota исчерпан -> логи kube-scheduler.

Алгоритм диагностики пода в состоянии Pending

Под остаётся в Pending, когда scheduler не может или не успел назначить его на ноду. Причин несколько: нехватка ресурсов, ограничения affinity/taints, отсутствующий PVC, лимиты namespace. Нужно последовательно исключать каждую.

Шаг 1: описание пода — первый источник правды

# Самая важная команда
kubectl describe pod <pod-name> -n <namespace>

# Смотрим секцию Events в конце вывода:
# "0/5 nodes are available: 3 Insufficient cpu, 2 node(s) had taint"
# "0/5 nodes are available: 5 Insufficient memory"
# "persistentvolumeclaim not found"
# "didn't match pod anti-affinity rules"
# "no nodes available to schedule pods"

Шаг 2: нехватка ресурсов

# Проверяем доступные ресурсы на нодах
kubectl describe nodes | grep -A 5 "Allocated resources"

# Или через top (если metrics-server установлен)
kubectl top nodes

# Смотрим requests/limits нашего пода
kubectl get pod <pod-name> -o yaml | grep -A 10 resources

# Итоговые requests по всем подам в namespace
kubectl get pods -n production -o json | \
  jq '.items[].spec.containers[].resources.requests'

Если pod запрашивает 4 CPU, а на всех нодах свободно по 2 — scheduler не найдёт подходящую ноду. Решение: уменьшить requests, добавить ноду или использовать Cluster Autoscaler.

Шаг 3: taints и tolerations

# Смотрим taints на нодах
kubectl describe nodes | grep -i taint
# или
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints

# Типичные taints:
# node.kubernetes.io/not-ready:NoSchedule  — нода NotReady
# node-role.kubernetes.io/control-plane:NoSchedule  — master-нода
# spot=true:NoSchedule  — spot instance
# Если тест показал taint, добавляем toleration в спецификацию пода
spec:
  tolerations:
    - key: "spot"
      operator: "Equal"
      value: "true"
      effect: "NoSchedule"

Шаг 4: affinity и node selector

# Проверяем метки нод
kubectl get nodes --show-labels

# Если в поде есть nodeSelector — проверяем, есть ли нода с такой меткой
kubectl get nodes -l disktype=ssd

# Если пусто — нода с нужной меткой не существует или метка другая
# Пример проблемного nodeSelector
spec:
  nodeSelector:
    disktype: ssd      # нода с такой меткой должна существовать

# Добавить метку ноде
# kubectl label node <node-name> disktype=ssd

Шаг 5: PersistentVolumeClaim

# Если в поде есть volumes с PVC
kubectl get pvc -n <namespace>
# STATUS: Pending — PVC не может получить PV

kubectl describe pvc <pvc-name> -n <namespace>
# Events: "no persistent volumes available for this claim"
# или: "storageclass not found"

# Доступные StorageClass
kubectl get storageclass

# Если PVC ждёт WaitForFirstConsumer — это нормально,
# PV создастся только когда под назначен на ноду

Шаг 6: ResourceQuota в namespace

# Проверяем квоты
kubectl describe resourcequota -n <namespace>

# Если Used >= Hard — новые поды не запустятся
# Решение: увеличить квоту или освободить ресурсы

Шаг 7: логи scheduler

# Если describe pod не даёт ответа — смотрим scheduler
kubectl logs -n kube-system -l component=kube-scheduler --tail=100

# Или события кластера
kubectl get events -n <namespace> --field-selector reason=FailedScheduling
kubectl get events -A --sort-by=.lastTimestamp | tail -30

Шаг 8: проверка ImagePullBackOff как ложный Pending

# Иногда под переходит из Pending в Init или ContainerCreating и зависает
# Проверяем статус init-контейнеров
kubectl get pod <pod-name> -o jsonpath='{.status.initContainerStatuses}'

# Проблемы с образом
kubectl describe pod <pod-name> | grep -A 10 "Events"

Подводные камни

  • Requests != Limits путаница — scheduler смотрит только на requests, не на limits; под с requests: 0 всегда будет запланирован, даже если потом убьёт ноду.
  • Pod anti-affinity блокирует себяrequiredDuringSchedulingIgnoredDuringExecution anti-affinity с одинаковыми метками и топологией ноды сделает запуск более одного пода невозможным.
  • Cluster Autoscaler не масштабирует при taint — если все ноды в ASG имеют taint, а новый под не имеет toleration, autoscaler добавит ноду, но под всё равно не запустится.
  • PVC с ReadWriteOnce на двух нодах — если PV уже смонтирован на node-A, второй под с тем же PVC никогда не запустится на node-B; нужен ReadWriteMany или отдельные PVC.
  • Namespace ResourceQuota без LimitRange — если в namespace есть ResourceQuota, но нет LimitRange, поды без явных requests отклоняются admission webhook.
  • Scheduler extender недоступен — кастомный scheduler extender (например, от GPU оператора) при недоступности блокирует scheduling всех подов с соответствующими ресурсами.

Common mistakes

  • Начинать с kubectl logs
  • Не читать Events
  • Путать Pending и CrashLoopBackOff

What the interviewer is testing

  • Имеет пошаговый алгоритм
  • Понимает FailedScheduling
  • Проверяет storage и quota

Sources

Related topics