FailedScheduling в Kubernetes: диагностика и устранение

Быстрые ссылки
- Идентификация ошибки FailedScheduling
- Понимание причин и похожих ошибок
- Устранение состояния FailedScheduling
- Дополнительные методики, чек-листы и playbook
- Резюме
Идентификация ошибки FailedScheduling
Нормально, если Pod остаётся в статусе Pending несколько секунд — Kubernetes назначает Pod на Node и Node скачивает образ контейнера. Но если Pod остаётся в Pending дольше обычного, нужно начинать диагностику. Первичная проверка статуса выполняется через kubectl:
$ kubectl get podsПример вывода:
NAME READY STATUS RESTARTS AGE
demo-pod 0/1 Pending 0 4m05sЕсли demo-pod уже несколько минут в Pending, посмотрите историю событий Pod:
$ kubectl describe pod demo-podВ выводе вы можете увидеть блок Events, например:
Warning FailedScheduling 4m default-scheduler 0/4 nodes are available: 1 Too many pods, 3 Insufficient cpu.Это подтверждает, что планировщик не нашёл ни одной ноды, пригодной для запуска Pod. Сообщение часто указывает причину: например, три ноды не имеют достаточного CPU, а одна достигла лимита по количеству Pod.
Понимание FailedScheduling и похожих проблем
Kubernetes может назначать Pod только на те Node, у которых достаточно доступных ресурсов и которые удовлетворяют всем ограничениям Pod (nodeSelector, affinity, hostPort, taints/tolerations и т. п.). Если ни одна нода не подходит, kube-scheduler генерирует событие FailedScheduling и Pod остаётся в Pending до изменения условий.
Причины, по которым Node может быть признана неподходящей:
- Node помечена как cordoned (SchedulingDisabled) — администратор временно запретил новые Pod.
- Node имеет taint, а Pod не содержит соответствующей toleration.
- Pod запрашивает
hostPort, который уже занят на Node. - Использован
nodeSelectorили affinity/anti-affinity, которые не удовлетворяются ни одной нодой. - В манифесте задано поле
nodeName, и указанная нода недоступна или unschedulable.
kube-scheduler проверяет все эти условия и оставляет Pod в Pending, если кандидатов нет.
Диагностика: шаг за шагом
Посмотрите события Pod:
kubectl describe pod— в разделе Events обычно указана причинаFailedSchedulingи краткая причина (недостаточно CPU, Memory, Too many pods, unschedulable и т. п.).Просмотрите состояние нод:
kubectl get nodesиkubectl describe node— проверьтеSTATUS(Ready, SchedulingDisabled), актуальные запросы/лимиты ресурсов, наличии taints и меток (labels).Проверьте запросы и лимиты ресурсов в Pod-манифесте (requests/limits). Pod с высокими request может не помещаться ни на одну ноду.
Проверьте политики планирования:
nodeSelector, affinity/anti-affinity,hostPort,tolerations.Убедитесь, что имена меток корректны (без опечаток) и соответствуют реальным меткам нод.
Если подозреваете, что кластер переполнен, исследуйте, какие Pod занимают ресурсы, и есть ли «лишние» ресурсоёмкие Pod или утечки.
Примеры команд и полезных блоков вывода сохранены ниже — используйте их как шаблон при диагностике.
Разрешение состояния FailedScheduling
Сообщение в событии обычно прямо указывает проблему. На практике бывает несколько подходов, которые можно комбинировать:
- Освободить ресурсы: удалить неиспользуемые Pod/Deployment/ReplicaSet, уменьшить requests/limits у неподходящих приложений.
- Масштабировать кластер: добавить ноды в пул (autoscaling или ручное добавление), чтобы увеличить CPU/память/диск.
- Исправить ограничения в манифестах: убрать ошибочные nodeSelector или скорректировать affinity/anti-affinity.
- Добавить соответствующие toleration на Pods, если ноды имеют taint.
- Снять cordon с ноды:
kubectl uncordon.
Пример проверки ресурсов ноды:
$ kubectl describe node demo-nodeЧасть вывода:
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 812m (90%) 202m (22%)
memory 905Mi (57%) 715Mi (45%)
ephemeral-storage 0 (0%) 0 (0%)
hugepages-2Mi 0 (0%) 0 (0%)Если уже запрошено 57% памяти, то новый Pod с request 1Gi не запланируется на эту ноду. Мониторинг распределения запросов по нодам помогает понять, где требуется балансировка или добавление ресурсов.
Когда ноды недоступны для планирования, событие FailedScheduling может содержать:
0/4 nodes are available: 4 node(s) were unschedulableЕсли нода была cordoned, в статусе ноды будет SchedulingDisabled:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
node-1 Ready,SchedulingDisabled control-plane,master 26m v1.23.3Разрешить планирование на такой ноде можно командой:
$ kubectl uncordon node-1Вывод:
node/node-1 uncordonedЕсли ноды не cordoned, а ресурсы кажутся достаточными, проверьте taints и nodeSelector. Пример наложения taint:
$ kubectl taint nodes node-1 demo-taint=allow:NoScheduleЕсли нода имеет taint demo-taint=allow:NoSchedule, то Pod будет назначен на неё только при наличии соответствующей toleration в манифесте:
spec:
tolerations:
- key: demo-taint
operator: Equal
value: allow
effect: NoScheduleПосле устранения причины FailedScheduling контрольная плоскость автоматически попытается переназначить Pod: обычно Pod стартует без ручного пересоздания, если манифест корректен.
Типичные ошибки в манифестах, приводящие к FailedScheduling
- Опечатки в ключах label/selector (чаще всего —
app: webvsapp:webили лишние пробелы). - Неправильно указанные unit для ресурсов (например,
1000вместо1000mдля CPU). - Жёстко зафиксированный
nodeNameна недоступную ноду. - Неочевидные affinity/anti-affinity: логика может блокировать размещение нескольких экземпляров на доступных нодах.
Проверьте манифесты командой:
$ kubectl apply --dry-run=client -f pod.yaml
$ kubectl explain pod.spec.affinityДополнительные методики и полезные материалы
Ниже собраны практические добавления: чек-листы, playbook, decision-tree, рольные задачи и критерии приёмки — чтобы ускорить диагностику и устранение.
Fact box: что смотреть в первую очередь
- События Pod:
kubectl describe pod— первая линия диагностики. - Статус нод:
kubectl get nodes— Ready / SchedulingDisabled. - Запросы/Limits: в Pod и распределение по нодам:
kubectl describe node. - Taints/Tolerations:
kubectl describe node→ Taints;kubectl describe pod→ Tolerations. - Метки нод:
kubectl get nodes --show-labels.
Мини‑методика (шаги для быстрого решения)
- Получить событие FailedScheduling:
kubectl describe pod. - Если причина — ресурсы, посчитать:
kubectl describe nodeиkubectl top nodes(если Metrics Server установлен). - Если причина — cordon, выполнить
kubectl uncordon. - Если причина — taint, либо удалить taint, либо добавить toleration в Pod.
- Если причина — nodeSelector/affinity — исправить манифесты или добавить подходящие метки на ноды.
- Если кластер действительно переполнен — масштабировать группы нод.
Decision tree (Mermaid)
flowchart TD
A[Pod в Pending > обычного времени] --> B{Есть ли FailedScheduling в Events?}
B -- Нет --> C[Проверить другие ошибки: ImagePullBackOff, CrashLoopBackOff]
B -- Да --> D{Сообщение: ресурсы?}
D -- Да --> E[Проверить requests/limits и использование нод]
D -- Нет --> F{Сообщение: unschedulable/taint/selector}
F -- taint --> G[Добавить toleration или снять taint]
F -- nodeSelector/affinity --> H[Исправить манифест/добавить метки]
F -- cordon --> I[Uncordon ноду]
E --> J{Можем ли мы удалить/пересобрать Pod?}
J -- Да --> K[Уменьшить requests или удалить ненужные Pod]
J -- Нет --> L[Масштабировать ноды]
G --> M[Подождать планировщик]
H --> M
I --> M
L --> M
M --> N[Pod должен перейти в Running]Ролевые чек-листы
SRE / оператор кластера:
- Проверить состояние Node (Ready, SchedulingDisabled).
- Посмотреть taints и метки Node.
- Оценить, нужно ли масштабирование и как его выполнить (cluster autoscaler или вручную).
- Проверить impact на стоимость при добавлении нод.
Разработчик приложения / владелец Pod:
- Проверить requests/limits в Pod-манифесте.
- Проверить nodeSelector, affinity и hostPort.
- Убедиться, что tolerations соответствуют необходимым taints.
- Если нужно — снизить footprint приложения или обеспечить горизонтальное масштабирование.
DevOps / CI‑CD инженер:
- Настроить проверки (linter) манифестов на опечатки в label/selector.
- Автоматизировать мониторинг использования ресурсов и alert на ресурсный дефицит.
Playbook: пошаговый SOP для устранения FailedScheduling
- Открыть
kubectl describe podи зафиксировать текст события. - Если причина — “Insufficient cpu/memory/disk”:
- Посмотреть
kubectl top nodesиkubectl describe node. - Найти ноды с перегрузкой, определить heavy‑consumer Pod (kubectl top pods –namespace N).
- Временные варианты: уменьшить requests или удалить временные Pod. Долгосрочно — масштабирование.
- Посмотреть
- Если причина — “Too many pods”:
- Проверить kubelet параметр
--max-podsна нодах или ограничения провайдера. - Переместить или удалить лишние Pod, либо увеличить лимит/добавить ноды.
- Проверить kubelet параметр
- Если причина — taint: добавить toleration в Pod, если это безопасно, либо снять taint на ноде.
- Если причина — cordon/unschedulable:
kubectl uncordon. - Если причина — nodeSelector/affinity: исправить манифест или пометить ноды требуемой меткой.
- После изменений дождаться, когда kube-scheduler назначит Pod; при необходимости пересоздать Pod.
Критерии приёмки
- Pod переходит в STATUS
Runningи контейнеры успешно запускаются. - В
kubectl describe podбольше нет событий FailedScheduling. - Контрольный функциональный тест (smoke test) успешно проходит.
- Мониторинг показывает, что метрики нод находятся в допустимых пределах и нет проблем с OOMKill/Throttling.
Контрпримеры / когда исправления могут не помочь
- Если внутри контейнера приложение падает сразу после старта (CrashLoopBackOff), то решение ресурсоёмкости нод не поможет — нужно отлаживать приложение.
- Если образ нельзя скачать (ImagePullBackOff), проблема не в планировщике.
- Если у провайдера есть скрытые лимиты (например, максимальное число Pod на ноде зафиксировано в kubelet/плагине), простое добавление toleration или изменение affinity не изменит ситуацию без изменения конфигурации ноды.
Безопасность и приватность
- При изменении taint/toleration убедитесь, что вы не размещаете неаудированные рабочие нагрузки на ноды с повышенным уровнем доверия (security boundary). Тaints часто используются для удержания специальных узлов (например, с доступом к PCIe‑устройствам) от обычных Pod.
- Не храните секреты в явном виде в манифестах. Ошибки планирования не должны побуждать к временному включению менее безопасных практик.
Набор тестов / критерии приёмки для автоматизации
- Unit: linter манифестов проверяет отсутствие опечаток в label/selector.
- Integration: CI‑job разворачивает тестовый Pod с разными request/limits и проверяет поведение планировщика.
- E2E: при удалении ноды workloads корректно перераспределяются на другие ноды.
Примеры распространённых команд
- Показать Pod и события:
kubectl describe pod -n - Показать ноды, метки и taints:
kubectl get nodes --show-labels
kubectl describe node - Снять cordon:
kubectl uncordon - Добавить taint:
kubectl taint nodes key=value:NoSchedule - Удалить taint:
kubectl taint nodes key:NoSchedule- - Проверить использование ресурсов (требуется Metrics Server):
kubectl top nodes
kubectl top pods --all-namespacesЛокальные рекомендации и миграция
- На облачных провайдерах проверьте настройки autoscaler и лимиты провайдера (quota), чтобы убедиться, что масштабирование узлов возможно.
- При миграции на другой тип instance убедитесь, что новые ноды имеют совместимые метки и taint, либо обновите манифесты.
Резюме
FailedScheduling означает, что kube-scheduler не нашёл подходящего Node для Pod. Частые причины: нехватка ресурсов (CPU/память/диск), cordon/taint на нодах, неверные nodeSelector/affinity или занятый hostPort. Диагностика начинается с kubectl describe pod и анализа Events. В зависимости от причины решением может быть освобождение ресурсов, изменение манифестов, снятие cordon/taint или масштабирование кластера. Следуйте playbook и рольным чек-листам, чтобы ускорить восстановление и минимизировать риск повторного возникновения проблем.
Важно: всегда тестируйте изменения в staging перед применением в production и учитывайте безопасность при снятии taint/cordon.
Похожие материалы
RDP: полный гид по настройке и безопасности
Android как клавиатура и трекпад для Windows
Советы и приёмы для работы с PDF
Calibration в Lightroom Classic: как и когда использовать
Отключить Siri Suggestions на iPhone