Гид по технологиям

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

7 min read Kubernetes Обновлено 16 Dec 2025
FailedScheduling в Kubernetes — диагностика и исправление
FailedScheduling в Kubernetes — диагностика и исправление

Графика с логотипом 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, если кандидатов нет.

Диагностика: шаг за шагом

  1. Посмотрите события Pod: kubectl describe pod — в разделе Events обычно указана причина FailedScheduling и краткая причина (недостаточно CPU, Memory, Too many pods, unschedulable и т. п.).

  2. Просмотрите состояние нод: kubectl get nodes и kubectl describe node — проверьте STATUS (Ready, SchedulingDisabled), актуальные запросы/лимиты ресурсов, наличии taints и меток (labels).

  3. Проверьте запросы и лимиты ресурсов в Pod-манифесте (requests/limits). Pod с высокими request может не помещаться ни на одну ноду.

  4. Проверьте политики планирования: nodeSelector, affinity/anti-affinity, hostPort, tolerations.

  5. Убедитесь, что имена меток корректны (без опечаток) и соответствуют реальным меткам нод.

  6. Если подозреваете, что кластер переполнен, исследуйте, какие 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: web vs app: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.

Мини‑методика (шаги для быстрого решения)

  1. Получить событие FailedScheduling: kubectl describe pod .
  2. Если причина — ресурсы, посчитать: kubectl describe node и kubectl top nodes (если Metrics Server установлен).
  3. Если причина — cordon, выполнить kubectl uncordon .
  4. Если причина — taint, либо удалить taint, либо добавить toleration в Pod.
  5. Если причина — nodeSelector/affinity — исправить манифесты или добавить подходящие метки на ноды.
  6. Если кластер действительно переполнен — масштабировать группы нод.

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

  1. Открыть kubectl describe pod и зафиксировать текст события.
  2. Если причина — “Insufficient cpu/memory/disk”:
    • Посмотреть kubectl top nodes и kubectl describe node.
    • Найти ноды с перегрузкой, определить heavy‑consumer Pod (kubectl top pods –namespace N).
    • Временные варианты: уменьшить requests или удалить временные Pod. Долгосрочно — масштабирование.
  3. Если причина — “Too many pods”:
    • Проверить kubelet параметр --max-pods на нодах или ограничения провайдера.
    • Переместить или удалить лишние Pod, либо увеличить лимит/добавить ноды.
  4. Если причина — taint: добавить toleration в Pod, если это безопасно, либо снять taint на ноде.
  5. Если причина — cordon/unschedulable: kubectl uncordon .
  6. Если причина — nodeSelector/affinity: исправить манифест или пометить ноды требуемой меткой.
  7. После изменений дождаться, когда 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.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство