Что означает состояние Pending у Pod в Kubernetes?
Состояние Pending — это начальный этап жизненного цикла Pod в Kubernetes. Когда вы создаёте Pod (например, через kubectl apply -f pod.yaml), система принимает его, но планировщик (scheduler) ещё не нашёл подходящую ноду для запуска контейнеров. Pod остаётся в этом состоянии, пока не будут выполнены все условия для размещения.
Обычно это выглядит так:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-5d89d7c8b9-abcde 0/1 Pending 0 2m
Если Pod завис в Pending надолго (несколько минут и более), это указывает на проблему, которая мешает планировщику выбрать ноду. Давайте разберём основные причины и решения.
Причины возникновения
Вот наиболее частые причины, по которым Pod не покидает состояние Pending:
- Недостаток ресурсов на нодах
Pod запрашивает черезresources.requestsбольше CPU или памяти, чем доступно на любых нодах в кластере. Например, если все ноды имеют 2 ГБ свободной памяти, а Pod запрашивает 4 ГБ, он не будет запланирован. - Несоответствие taints и tolerations
Ноды могут иметь taints (например,dedicated=production:NoSchedule), которые repel Pod без соответствующих tolerations в манифесте. Если Pod не имеет tolerations для таких taints, планировщик его не разместит. - Проблемы с PersistentVolumeClaim (PVC)
Если Pod требует тома черезvolumeMountsиpersistentVolumeClaim.claimName, а соответствующий PVC находится в состоянииPending(например, нет доступного PV или класс хранения недоступен), то Pod тоже останется в Pending. - Node selector, affinity, или anti-affinity
Условия вspec.nodeSelector,spec.affinityмогут быть слишком строгими. Например, если вы указалиnodeSelector: {disktype: ssd}, но ни одна нода не имеет такой метки, Pod не будет запланирован. - Исчерпание ResourceQuota
В namespace может быть установленResourceQuota, который ограничивает общее количество Pod, CPU или памяти. Если квота превышена, новые Pod останутся в Pending. - Ограничение на количество Pod на ноде
ПараметрmaxPodsв конфигурации kubelet (обычно 110 по умолчанию) может быть достигнут на нодах, и планировщик не сможет добавить ещё Pod. - Отсутствие подходящих нод
Все ноды могут быть заблокированы для обслуживания (например, черезkubectl cordon) или находятся в состоянииNotReady.
Способы решения
Способ 1: Анализ событий Pod с помощью kubectl describe
Это первый и самый важный шаг. Команда kubectl describe pod показывает события (Events), где scheduler объясняет, почему не может разместить Pod.
- Найдите имя Pod и namespace:
kubectl get pods --all-namespaces | grep Pending - Описайте Pod, заменив
<pod-name>и<namespace>:kubectl describe pod <pod-name> -n <namespace> - В выводе найдите раздел Events. Пример сообщения:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 5m default-scheduler Successfully assigned default/myapp-5d89d7c8b9-abcde to node-1 Warning FailedScheduling 4m default-scheduler 0/3 nodes are available: 3 Insufficient cpu.
ЗдесьInsufficient cpuуказывает на нехватку CPU.
Другие возможные сообщения:0/3 nodes are available: 3 node(s) had taint {key:value}, that the pod didn't tolerate.0/3 nodes are available: 2 node(s) had volume node affinity conflict.persistentvolumeclaim "my-pvc" not found
💡 Совет: Если событий нет, возможно, Pod ещё не обработан scheduler. Подождите 1-2 минуты и повторите.
Способ 2: Проверка доступности ресурсов на нодах
После того как вы узнали причину из событий (например, Insufficient memory), проверьте, сколько ресурсов действительно доступно.
- Посмотрите общее использование ресурсов нодами:
kubectl top nodes
Вывод:NAME CPU(cores) MEMORY(bytes) node-1 150m 1900Mi node-2 200m 2100Mi
Обратите внимание наMEMORY(bytes)— если близко к лимиту ноды, это может быть причиной. - Подробно опишите конкретную ноду (например,
node-1):kubectl describe node node-1
В разделеAllocated resourcesвы увидите, сколько ресурсов уже выделено Pod'ам. Сравните сCapacity. - Если ресурсы исчерпаны, у вас есть варианты:
- Увеличить ресурсы кластера: добавить новую ноду (например, через
kubectl scale --replicas=2 deployment/<deployment-name>если используется Deployment с автоматическим масштабированием, или вручную в облачном провайдере). - Уменьшить запросы ресурсов в Pod: отредактируйте манифест Pod, снизьте значения
resources.requests.cpuиresources.requests.memory. Например, с2Giдо1Gi.
- Увеличить ресурсы кластера: добавить новую ноду (например, через
Способ 3: Проверка и корректировка манифеста Pod
Часто проблема кроется в самом манифесте Pod или Deployment. Проверьте следующие разделы:
- Запросы ресурсов (
resources.requests)
Убедитесь, что запросы не превышают типичные ресурсы нод. Например, если у вас ноды по 2 ГБ RAM, не запрашивайте 1.5 ГБ на контейнер, если планируете запускать несколько контейнеров.spec: containers: - name: myapp image: myapp:latest resources: requests: memory: "256Mi" # ↓ уменьшите, если нужно cpu: "250m" - Node selector и affinity
Проверьте, не задаёте ли вы слишком специфичные селекторы:spec: nodeSelector: disktype: ssd # Убедитесь, что ноды имеют такую метку: kubectl get nodes --show-labels
Если метки нет, Pod не будет запланирован. Либо удалитеnodeSelector, либо добавьте метку на ноду:kubectl label node <node-name> disktype=ssd. - Tolerations
Если ноды имеют taints (например, для выделенных рабочих нагрузок), Pod должен иметь соответствующие tolerations:spec: tolerations: - key: "dedicated" operator: "Equal" value: "production" effect: "NoSchedule" - Affinity/anti-affinity
Сложные правила affinity могут не находить подходящих нод. Временно упростите или удалитеaffinityраздел, чтобы проверить.
После изменений примените манифест:
kubectl apply -f pod.yaml
Способ 4: Проверка PersistentVolumeClaim (PVC) и ResourceQuota
Если Pod использует хранилище, убедитесь, что PVC готово.
- Проверьте статус PVC:
kubectl get pvc -n <namespace>
Если PVC в состоянииPending, проблема с томом. Описайте его:kubectl describe pvc <pvc-name> -n <namespace>
Возможные причины:- Нет доступного PersistentVolume (PV) с подходящим классом хранения (
storageClassName). - PV существует, но уже привязан к другому PVC.
- Класс хранения не поддерживается в кластере.
Решение: создать соответствующий PV, изменитьstorageClassNameв PVC или использовать динамическое provisioning. - Нет доступного PersistentVolume (PV) с подходящим классом хранения (
- Проверьте ResourceQuota в namespace:
kubectl get resourcequota -n <namespace> kubectl describe resourcequota <quota-name> -n <namespace>
В выводе ищитеhardиusedlimits. Еслиusedблизко кhard, новые Pod не будут создаваться. Увеличьте квоту или удалите лишние ресурсы.
Профилактика
Чтобы избежать состояния Pending в будущем:
- Настраивайте запросы ресурсов реалистично: тестируйте приложение и устанавливайте
requestsна основе фактического использования, а не с запасом 100%. - Используйте автоматическое масштабирование кластера: если вы в облаке, настройте Cluster Autoscaler, который добавляет ноды при нехватке ресурсов.
- Регулярно мониторьте использование ресурсов: инструменты вроде
kubectl top, Prometheus + Grafana помогут увидеть тренды и предсказать нехватку. - Правильно настраивайте taints/tolerations и affinity: документируйте, какие ноды для каких workloads предназначены, и проверяйте соответствие.
- Управляйте квотами ресурсов: устанавливайте ResourceQuota в namespace с запасом, но не слишком высоким, чтобы избежать "штурма" ресурсов.
- Проверяйте статус хранилища: убедитесь, что классы хранения (StorageClass) доступны и PV создаются корректно.
Следуя этим рекомендациям, вы значительно снизите вероятность зависания Pod в состоянии Pending и обеспечите стабильную работу ваших приложений в Kubernetes.