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 блокирует себя —
requiredDuringSchedulingIgnoredDuringExecutionanti-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