Задача 16. Почему под висит в Pending

Ноды свободны, а под не запускается. Разбираем, как планировщик фильтрует и оценивает ноды, чем taint отличается от affinity и почему свободная память ноды не то же самое, что доступная.
Опубликовано:

Задача

Под висит в состоянии Pending. При этом kubectl top nodes показывает, что ноды загружены на 40–50% — места, казалось бы, полно.

Вопрос: какие причины могут держать под в Pending и как быстро найти настоящую?

Что кажется очевидным

«Не хватает ресурсов». Иногда так и есть, но «свободно по top» и «доступно для планирования» — разные величины, и это только одна из шести типичных причин.

Как это работает на самом деле

Планировщик работает в две фазы:

  1. Фильтрация — отсеиваются ноды, на которых под размещать нельзя: не хватает ресурсов, не подходит nodeSelector, есть непереносимый taint, нет нужного тома.
  2. Оценка — оставшиеся ноды ранжируются, выбирается лучшая.

Если после фильтрации не осталось ни одной ноды — под остаётся Pending, а причина пишется в события.

Ключевой момент про ресурсы: планировщик считает сумму requests всех подов на ноде, а не фактическое потребление. Нода может использовать 40% памяти по факту, но если сумма requests уже покрывает всю ёмкость — новых подов туда не поставят. Это ровно тот случай, когда top вводит в заблуждение.

Шесть типичных причин

1. Недостаточно выделяемых ресурсов. Сумма requests не влезает. Помните, что часть ресурсов ноды зарезервирована под системные компоненты (kube-reserved, system-reserved) и не доступна подам — смотрите Allocatable, а не Capacity.

2. Taints без toleration. Нода помечена, под не имеет разрешения:

BASH
kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, taints: .spec.taints}'
Нажмите, чтобы развернуть и увидеть больше

Классика — мастер-ноды с node-role.kubernetes.io/control-plane:NoSchedule и ноды с GPU.

3. Не выполняются nodeSelector / nodeAffinity. Под требует метку, которой ни на одной ноде нет — например, disktype: ssd при переезде в новый пул нод.

4. Не выполняются podAntiAffinity / topologySpread. Правило «не более одного пода на ноду» при 3 нодах не даст запустить четвёртую реплику. При whenUnsatisfiable: DoNotSchedule под честно останется Pending (см. задачу 8).

5. Проблема с томом. PVC не привязан: нет подходящего PV, StorageClass отсутствует, или том находится в другой зоне доступности, чем свободные ноды. Для volumeBindingMode: WaitForFirstConsumer порядок обратный — том создаётся после выбора ноды, и тут свои сюрпризы.

6. Превышена квота namespace. ResourceQuota исчерпана — под не создастся вовсе или зависнет (см. задачу 4).

Ответ

Причин много, но узнавать их наизусть не нужно — планировщик сам пишет причину в события пода. Это первое, что нужно смотреть:

BASH
kubectl describe pod my-pod | tail -20
Нажмите, чтобы развернуть и увидеть больше

Типичный вывод:

PLAINTEXT
Events:
  Type     Reason            Message
  ----     ------            -------
  Warning  FailedScheduling  0/12 nodes are available:
           3 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: },
           5 Insufficient memory,
           4 node(s) didn't match Pod's node affinity/selector.
Нажмите, чтобы развернуть и увидеть больше

Здесь сразу видна вся арифметика: 3 + 5 + 4 = 12 нод, и по каждой группе названа причина. Это самый информативный вывод во всём Kubernetes — он практически всегда даёт ответ.

Что с этим делать

Диагностика по шагам

BASH
# 1. Причина — почти всегда здесь
kubectl describe pod my-pod | grep -A10 Events

# 2. Реально доступные ресурсы ноды (Allocatable, не Capacity)
kubectl describe node node-1 | grep -A6 "Allocated resources"

# 3. Taints на нодах
kubectl describe node node-1 | grep -i taint

# 4. Состояние PVC, если под с томом
kubectl get pvc
Нажмите, чтобы развернуть и увидеть больше

Особенно полезен пункт 2: он показывает суммы Requests и Limits по ноде в процентах от Allocatable. Если Requests по памяти близки к 100%, вопрос закрыт независимо от показаний top.

Лечение по причинам

Причина в событияхЧто делать
Insufficient cpu/memoryУменьшить requests, добавить ноды, включить autoscaler
untolerated taintДобавить tolerations или убрать taint
didn't match node affinity/selectorПроверить метки нод, поправить селектор
didn't match pod anti-affinityСмягчить правило или добавить ноды
had volume node affinity conflictТом в другой зоне — проверить StorageClass и зоны
exceeded quotaПоднять квоту или освободить ресурсы

Профилактика


Дальше: Задача 17. StatefulSet, PVC и данные, которые пережили под.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
ESC
⌘K Горячая клавиша