В Kubernetes под планированием понимается поиск подходящих узлов, на которых kubelet сможет запустить Pod'ы. Приоритизация — процесс завершения работы Pod'ов с более низким приоритетом и высвобождения места для Pod'ов с более высоким приоритетом. Вытеснение — это проактивное завершение работы одного или нескольких Pod'ов на узлах с дефицитом ресурсов.
В Kubernetes под планированием понимается поиск узлов, подходящих для размещения Pod'ов так, чтобы kubelet
мог их запустить. Приоритизация (упреждение; preemption) — процесс завершения работы Pod'ов
с более низким приоритетом с освобождением места для Pod'ов с более высоким приоритетом. Вытеснение (eviction) — завершение работы одного или нескольких Pod'ов на узлах.
Плановое завершение работы подов инициируется владельцами приложений или администраторами
кластера. Внеплановое завершение работы обычно вызвано непредвиденными обстоятельствами различной природы,
например, недостатком ресурсов на узлах или случайными удалениями.
Можно настроить под так, чтобы тот мог запускаться только на определенном(-ых) узле(-ах) или предпочитал определенную группу узлов.
Сделать это можно несколькими способами, при этом все рекомендуемые подходы используют селекторы лейблов для выбора.
Зачастую нужды в подобных ограничениях нет; планировщик автоматически размещает поды оптимальным образом (например, распределяет их по узлам, чтобы они не оказались все на одном узле с дефицитом ресурсов).
Однако в некоторых обстоятельствах возможность контролировать, куда именно попадет под, может пригодиться. Например, она поможет запланировать под на узел с быстрым SSD-хранилищем или разместить два активно взаимодействующих друг с другом пода в одной зоне доступности.
Для планирования подов на определенные узлы можно использовать любой из методов:
Значения этих лейблов зависят от облачного провайдера, поэтому на них нельзя полагаться.
Например, в одних окружениях значение kubernetes.io/hostname может совпадать с именем узла, в других — отличаться.
Изоляция узла/ограничение его использования
Лейблы узлов позволяют размещать поды на определенные узлы или группы узлов. С их помощью можно планировать поды на узлы с определенными требованиями к изоляции, безопасности или соответствию нормативным положениям.
При использовании лейблов для изоляции узлов следует выбирать ключи лейблов, которые kubelet не может изменить. В этом случае взломанный узел не сможет навесить на себя эти лейблы в надежде, что планировщик разместит на него рабочие нагрузки.
Admission-плагин NodeRestriction не позволяет kubelet'у устанавливать или изменять лейблы с префиксом node-restriction.kubernetes.io/.
Чтобы использовать этот префикс для изоляции узла:
Убедитесь, что используется авторизатор узлов и включен admission-плагин NodeRestriction.
Добавьте лейблы с префиксом node-restriction.kubernetes.io/ к узлам и используйте их в селекторах узлов. Например, example.com.node-restriction.kubernetes.io/fips=true или example.com.node-restriction.kubernetes.io/pci-dss=true.
nodeSelector
nodeSelector — простейшая рекомендуемая форма настроек выбора узлов.
Можно добавить поле nodeSelector в спецификацию пода и перечислить в нем лейблы узлов, которые подходят для развертывания пода. В этом случае Kubernetes будет планировать под только на узлы со всеми указанными лейблами.
Правила совместного/раздельного существования (affinity и anti-affinity)
nodeSelector — самый простой способ развернуть поды на узлах с определенными лейблами. Правила совместного/раздельного существования расширяют типы ограничений, которые можно накладывать. Вот некоторые из их преимуществ:
Язык правил affinity/anti-affinity более выразителен. nodeSelector выбирает узлы только со всеми указанными лейблами. Правила affinity/anti-affinity расширяют логику выбора и делают ее более гибкой.
Правило может быть мягким (soft) или предпочтительным (preferred). В этом случае планировщик все равно запланирует под, даже если подходящего узла для него не найдется.
При планировании пода планировщик может учитывать лейблы других подов, запущенных на узле (или в иной топологической области), а не только лейблы самого узла. Это позволяет формулировать правила, определяющие сосуществование подов на узле.
Правила совместного существования (affinity) бывают двух типов:
Правила для узлов (node affinity) работают подобно полю nodeSelector, но более выразительны. Кроме того, можно задавать мягкие правила.
Правила для подов (inter-pod affinity и anti-affinity) позволяют при планировании учитывать лейблы других подов.
Правила совместного существования для узлов (node affinity)
Правила совместного существования для узлов концептуально похожи на nodeSelector. С помощью лейблов они позволяют ограничивать список узлов, на которые может быть запланирован под. Существует два типа таких правил:
requiredDuringSchedulingIgnoredDuringExecution: Планировщик не может запланировать под, если правило не выполнено. Работает как nodeSelector, но с более выразительным синтаксисом.
preferredDuringSchedulingIgnoredDuringExecution: Планировщик пытается найти узел, который соответствует правилу. Если подходящий узел не удается найти, планировщик все равно планирует под.
Примечание:
В типах выше IgnoredDuringExecution означает, что под продолжит свою работу, если лейблы узлов изменятся после того, как Kubernetes запланировал его.
Задавать правила совместного существования для узлов можно с помощью поля .spec.affinity.nodeAffinity в спецификации пода.
В качестве примера рассмотрим следующую спецификацию пода:
У узла должен быть лейбл с ключом topology.kubernetes.io/zone, и значение этого лейбла должно быть либо antarctica-east1, либо antarctica-west1.
Предпочтительно, чтобы у узла был лейбл с ключом another-node-label-key и значением another-node-label-value.
Можно использовать поле operator для указания логического оператора, который Kubernetes будет применять при интерпретации правил. Доступны In, NotIn, Exists, DoesNotExist, Gt и Lt.
Узнать больше о том, как они работают, можно в подразделе Операторы.
NotIn и DoesNotExist позволяют задавать правила раздельного существования (anti-affinity) для узла.
Кроме того, можно использовать taint'ы узлов, чтобы "отвадить" поды от определенных узлов.
Примечание:
Когда указаны и nodeSelector, и nodeAffinity, под будет запланирован на узел только в том случае, если оба этих условия удовлетворены.
Если указать несколько условий nodeSelectorTerms, привязанных к типам nodeAffinity, то под может быть запланирован на узел, если удовлетворяется одно из указанных условий nodeSelectorTerms. К условиям применяется логическое ИЛИ.
Если задать несколько выражений в поле matchExpressions для одного условия nodeSelectorTerms, под будет запланирован на узел только если удовлетворены все выражения matchExpressions. К условиям применяется логическое И.
Для каждого правила типа preferredDuringSchedulingIgnoredDuringExecution можно указать вес weight в диапазоне от 1 до 100. Найдя несколько узлов, удовлетворяющих всем остальным требованиям для планирования пода, планировщик перебирает предпочтительные правила, которым удовлетворяет узел, и суммирует их веса.
Итоговая сумма добавляется к оценке, полученной при анализе других параметров, влияющих на приоритет узла. Принимая решение о размещении пода, планировщик отдает предпочтение узлам с наибольшей суммарной оценкой.
В качестве примера рассмотрим следующую спецификацию пода:
Если правилу preferredDuringSchedulingIgnoredDuringExecution соответствуют два узла (один — с лейблом label-1:key-1, другой — с label-2:key-2), планировщик считает вес weight каждого узла и добавляет его к другим оценкам для этого узла. Под планируется на узел с наивысшей итоговой оценкой.
Примечание:
Чтобы Kubernetes смог запланировать поды в этом примере, необходимо, чтобы существовали узлы с лейблом kubernetes.io/os=linux.
Правила совместного существования и профили планирования
СТАТУС ФИЧИ:Kubernetes v1.20 [beta]
При настройке нескольких профилей планирования можно связать профиль с правилами совместного существования для узлов (это удобно, когда профиль применяется к определенному набору узлов). Для этого необходимо добавить addedAffinity в поле argsплагина NodeAffinity в конфигурации планировщика. Например:
Правило addedAffinity применяется ко всем подам с полем .spec.schedulerName, имеющим значение foo-scheduler, в дополнение к NodeAffinity, заданному в PodSpec. Таким образом, подходящие для пода узлы должны удовлетворять параметрам addedAffinity и правилам .spec.NodeAffinity пода.
Поскольку конечные пользователи не видят addedAffinity, результат применения этих правил может быть для них неожиданным. Используйте лейблы узлов, которые однозначно соотносятся с именем профиля планировщика.
Примечание:
Контроллер DaemonSet, создающий поды для DaemonSet'ов, не поддерживает профили планирования. Контроллер DaemonSet создает поды, а штатный планировщик Kubernetes, размещая их, следит за соблюдением правил nodeAffinity.
Правила совместного/раздельного существования подов
Правила совместного/раздельного существования подов позволяют выбирать узлы для планирования в зависимости от лейблов подов, которые уже на этих узлах работают (вместо лейблов самих узлов).
Алгоритм работы правил совместного/раздельного существования подов можно описать так: "данный под должен (или не должен в случае раздельного (anti-affinity) существования) размещаться на X, если на нем уже работает один или несколько подов, удовлетворяющих правилу Y", где X — топологический домен, например, узел, стойка, зона/регион облачного провайдера и т. п., а Y — правило, которое Kubernetes пытается удовлетворить.
Для задания правил Y используются селекторы лейблов с необязательным связанным списком пространств имен. Для подов в Kubernetes указываются пространства имен, соответственно, их лейблы также оказываются неявно связаны с этими же пространствами имен. Любые селекторы лейблов для лейблов подов должны содержать пространства имен, в которых Kubernetes должен искать эти лейблы.
Топологический домен X задается с помощью topologyKey — ключа для лейбла узла, который система использует для обозначения домена. Примеры см. в разделе Типичные лейблы, аннотации и taint'ы.
Примечание:
Обработка правил совместного/раздельного существования подов требует значительных ресурсов и может значительно замедлить планирование в больших кластерах. Их не рекомендуется использовать в кластерах, число узлов в которых превышает несколько сотен.
Примечание:
Правила раздельного существования для подов требуют согласованности лейблов узлов. Другими словами, у каждого узла в кластере должен быть лейбл, относящий его к определенному ключу topologyKey. Отсутствие лейблов topologyKey у некоторых или всех узлов в кластере может привести к непредсказуемому поведению.
Типы правил совместного/раздельного существования подов
Например, с помощью правила совместного существования requiredDuringSchedulingIgnoredDuringExecution можно заставить планировщик размещать поды, относящиеся к разным сервисам, в одной зоне облачного провайдера, поскольку они активно обмениваются данными друг с другом.
Аналогичным образом можно использовать правило раздельного существования preferredDuringSchedulingIgnoredDuringExecution для распределения подов по нескольким зонам облачного провайдера.
Для задания правил совместного существования предназначено поле affinity.podAffinity в спецификации пода.
Для задания правил раздельного существования предназначено поле affinity.podAntiAffinity в спецификации пода.
Планирование группы подов, связанных правилами совместного существования
Если планируемый под — первый в серии подов, связанных правилами совместного существования,
он может быть запланирован, если удовлетворит всем остальным правилам совместного существования. Чтобы подтвердить, что этот под — действительно первый,
проводится проверка, которая должна показать, что пространство имен и селектор этого пода уникальны в кластере (то есть нет других таких подов). Кроме того,
под должен соответствовать своим собственным правилам, а выбранный узел — всем запрошенным топологиям.
Это предотвращает тупиковую ситуацию, когда поды не могут запланироваться из-за того, что все они связаны правилами совместного существования.
Пример правил совместного/раздельного существования для пода
В примере задается одно правило совместного существования подов, и одно — раздельного. Для совместного правила используется жесткий тип requiredDuringSchedulingIgnoredDuringExecution, для раздельного — мягкий preferredDuringSchedulingIgnoredDuringExecution.
Правило совместного существования гласит, что планировщик может разместить под на узел, только если тот находится в зоне с одним или более подами с лейблом security=S1.
Например, если есть кластер с выделенной зоной, назовем ее "V",
состоящей из узлов с лейблом topology.kubernetes.io/zone=V, планировщик может
назначить под на любой узел зоны V только если в этой зоне уже есть хотя бы один под
с лейблом security=S1. И наоборот, если в зоне V нет подов с лейблом security=S1,
планировщик не сможет назначить под на какой-либо из узлов в этой зоне.
Правило раздельного существования гласит, что планировщик при возможности не должен размещать под на узел, если тот находится в зоне с одним или более подами с лейблом security=S2.
Например, если есть кластер с выделенной зоной, назовем ее "R",
состоящей из узлов с лейблами topology.kubernetes.io/zone=R. Планировщик должен избегать
назначать поды на узлы из зоны R, если в ней уже есть по крайней мере один под
с лейблом security=S2. Соответственно, если в зоне R нет подов с лейблами security=S2,
правило раздельного существования не будет влиять на планирование подов в эту зону.
Больше примеров правил совместного/раздельного существования для подов можно найти в рабочей документации.
Поле operator пода поддерживает значения In, NotIn, Exists и DoesNotExist при задании правил совместного/раздельного существования.
Узнать больше о том, как они работают, можно в подразделе Операторы.
В принципе, topologyKey может быть любым разрешенным лейблом-ключом со следующими исключениями по соображениям производительности и безопасности:
При задании правил совместного/раздельного существования для подов пустое поле topologyKey не допускается как для requiredDuringSchedulingIgnoredDuringExecution, так и для preferredDuringSchedulingIgnoredDuringExecution.
Для правил раздельного существования типа requiredDuringSchedulingIgnoredDuringExecution admission-контроллер разрешает использовать только kubernetes.io/hostname в качестве topologyKey. Для работы с кастомными топологиями admission-контроллер можно дополнить или совсем отключить его.
В дополнение к labelSelector и topologyKey можно опционально указать список пространств имен, которые должен выбирать labelSelector, с помощью поля namespaces на том же уровне, что labelSelector и topologyKey. Если поле namespaces опущено или пусто, по умолчанию выбирается пространство имен пода, в котором задаются правила совместного/раздельного существования.
Селектор пространств имен
СТАТУС ФИЧИ:Kubernetes v1.24 [stable]
Подходящие пространства имен также можно выбрать с помощью namespaceSelector, который попытается найти лейбл в наборе пространств имен.
Условия совместного существования применяются к пространствам имен, выбранным как селектором namespaceSelector, так и полем namespaces.
Обратите внимание, что пустой селектор namespaceSelector ({}) выбирает все пространства имен, в то время как пустой или null-список namespaces и null-селектор namespaceSelector выбирает пространство имен пода, в котором правило задано.
matchLabelKeys
СТАТУС ФИЧИ:Kubernetes v1.31 [beta] (enabled by default: true)
Примечание:
Поле matchLabelKeys является полем альфа-уровня и по умолчанию отключено в
Kubernetes 1.32.
Включить его можно с помощью переключателя функциональности
(feature gate) MatchLabelKeysInPodAffinity.
Kubernetes включает необязательное поле matchLabelKeys для правил совместного (раздельного) существования подов.
В нем указываются ключи для лейблов, которые должны совпадать с лейблами входящего пода,
чтобы правила совместного (раздельного) существования выполнялись.
Ключи используются для поиска значений в лейблах подов; эти ключи-лейблы объединяются (с помощью AND)
с ограничениями, задаваемыми с помощью поля labelSelector. Такая комбинированная фильтрация позволяет отобрать
набор существующих подов, которые приниматься в расчет при обработке правил совместного (раздельного) существования.
Обычно matchLabelKeys используется вместе с pod-template-hash (задается для подов,
которые управляются как часть деплоймента, где значение уникально для каждой ревизии).
Использование pod-template-hash в matchLabelKeys позволяет нацеливаться на поды, принадлежащие
к той же ревизии, что и входящий под. Таким образом, что скользящее обновление не нарушит правила совместного существования.
apiVersion:apps/v1kind:Deploymentmetadata:name:application-server...spec:template:spec:affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key:appoperator:Invalues:- databasetopologyKey:topology.kubernetes.io/zone# При расчете affinity подов учитываются только поды из определенного выката.# При обновлении Deployment'а новые поды будут следовать своим собственным правилам совместного существования# (если они заданы в новом шаблоне подов)matchLabelKeys:- pod-template-hash
mismatchLabelKeys
СТАТУС ФИЧИ:Kubernetes v1.31 [beta] (enabled by default: true)
Примечание:
Поле mismatchLabelKeys является полем альфа-уровня и по умолчанию отключено в
Kubernetes 1.32.
Включить его можно с помощью переключателя функциональности
(feature gate) MatchLabelKeysInPodAffinity.
Kubernetes включает необязательное поле mismatchLabelKeys для определения правил совместного (раздельного) существования подов.
В поле указываются ключи для лейблов, которые не должны совпадать с лейблами входящего пода,
чтобы правила совместного (раздельного) существования подов удовлетворялись.
Один из примеров использования — размещение подов определенной группы пользователей (tenant'ов) или команды в конкретном топологическом домене (узле, зоне и т. д.).
То есть идея в том, чтобы избежать одновременного запуска подов от разных групп пользователей в одном топологическом домене.
apiVersion:v1kind:Podmetadata:labels:# Assume that all relevant Pods have a "tenant" label settenant:tenant-a...spec:affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:# следим за тем, чтобы поды, связанные с этим тенантом, попадали на нужный пул узлов- matchLabelKeys:- tenanttopologyKey:node-poolpodAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:# следим за тем, чтобы поды, связанные с этим тенантом, не смогли планироваться на узлы для другого тенанта- mismatchLabelKeys:- tenant# значение лейбла "tenant" этого пода будет предотвращать# планирование на узлы в пулах, на которых работают поды# другого тенантаlabelSelector:# Должен быть labelSelector, который выбирает поды с лейблом tenant,# иначе этот под также будет "ненавидеть" поды из daemonset'ов, например, # те, у которых нет лейбла tenant.matchExpressions:- key:tenantoperator:ExiststopologyKey:node-pool
Другие примеры использования
Правила совместного/раздельного существования для подов особенно удобны, когда используются совместно с абстракциями более высокого уровня, такими как ReplicaSet, StatefulSet, Deployment и т. д. Эти правила позволяют настроить размещение рабочих нагрузок с учетом имеющейся топологии; например, пара связанных подов будет планироваться на один и тот же узел.
Представьте кластер, состоящий из трех узлов. Он используется для запуска веб-приложения и как in-memory-кэш (например, Redis). Предположим, что задержка между веб-приложением и кэшем должна быть минимальной. Правила совместного/раздельного существования для подов позволяют настроить планировщик так, чтобы тот размещал веб-серверы как можно ближе к кэшу.
В приведенном ниже примере конфигурации деплоймента с Redis его реплики получают лейбл app=store. Правило podAntiAffinity запрещает планировщику размещать несколько реплик с лейблом app=store на одном узле. В результате каждый узел получает по отдельной кэш-реплике.
Конфигурация деплоймента, приведенная ниже, создает три реплики веб-сервера с лейблом app=web-store.
Правило совместного существования предписывает планировщику размещать каждую реплику на узле, на котором уже имеется под с лейблом app=store. В то же время правило раздельного существования запрещает планировщику размещать несколько серверов с лейблом app=web-store на одном узле.
Развертывание ресурсов в соответствии с приведенными выше конфигурациями приведет к созданию кластера, в котором на каждом узле будет по одному веб-серверу и одной реплике Redis (всего три отдельных узла):
узел 1
узел 2
узел 3
webserver-1
webserver-2
webserver-3
cache-1
cache-2
cache-3
В итоге к каждому инстансу Redis'а, скорее всего, будет обращаться клиент, который работает с ним на том же узле. Подобный подход позволит минимизировать как перекос (дисбаланс нагрузки), так и задержки.
Правила совместного/раздельного существования для подов можно использовать и в других случаях.
См., например, руководство по ZooKeeper. В нем с помощью правил раздельного существования StatefulSet настраивается так, чтобы обеспечить высокую доступность (используется подход, аналогичный тому, что применен выше).
nodeName
Поле nodeName в спецификации пода — более непосредственный способ выбора узлов по сравнению с правилами совместного существования или селектором nodeSelector. Если поле nodeName не пустое, планировщик игнорирует под, а kubelet на узле с соответствующим именем пытается разместить под на этом узле. Приоритет поля nodeName выше, чем селектора nodeSelector или правил совместного/раздельного существования.
Однако у nodeName имеются и некоторые недостатки:
Если узел с заданным именем не существует, под не будет запущен. Кроме того, в некоторых случаях он может быть автоматически удален.
Если на узле с заданным именем недостаточно ресурсов для работы пода, последний будет остановлен; соответствующая причина (например, OutOfmemory или OutOfcpu) будет указана.
В облачных окружениях имена узлов не всегда предсказуемы или стабильны.
Примечание:
Поле nodeName предназначено для использования в кастомных планировщиках или в продвинутых случаях,
когда необходимо обойти настроенные планировщики. Обход планировщиков может привести к тому, что поды не будут запущены,
если целевые узлы окажутся перегруженными. С помощью правила совместного существования (affinity) узла или поля nodeselector под можно назначить на определенный узел, не обходя планировщики с помощью nodeName.
Ниже приведен пример спецификации пода с полем nodeName:
Такой под будет работать только на узле с именем kube-01.
Ограничения на топологию распределения подов
С помощью ограничений на топологию распределения (topology spread constraints) можно настроить размещение подов в кластере по failure-доменам, таким как регионы, зоны, узлы, или любым другим заданным топологическим конфигурациям. Это позволяет повысить производительность, ожидаемую доступность или эффективность использования ресурсов.
Ниже приведены все логические операторы, которые можно использовать в поле operator для nodeAffinity и podAffinity.
Оператор
Действие
In
Значение лейбла присутствует в предоставленном наборе строк
NotIn
Значение лейбла отсутствует в предоставленном наборе строк
Exists
Лейбл с таким ключом существует для объекта
DoesNotExist
У объекта не существует лейбла с таким ключом
Следующие операторы могут использоваться только с nodeAffinity.
Оператор
Действие
Gt
Введенное значение будет обработано как целое число, и это целое число меньше, чем целое число, полученное в результате обработки значения лейбла, указанного этим селектором
Lt
Введенное значение будет обработано как целое число, и это целое число больше, чем целое число, полученное в результате обработки значения лейбла, указанного этим селектором
Примечание:
Операторы Gt и Lt не работают с нецелыми значениями. Если заданное значение
не является целым числом, под не будет запланирован. Кроме того, Gt и Lt
недоступны для podAffinity.
Вытеснение, инициированное через API, — процесс, при котором с помощью Eviction API
создается объект Eviction, который запускает корректное завершение работы пода.
Вытеснение можно инициировать напрямую с помощью Eviction API или программно,
используя клиент API-сервера
(например, командой kubectl drain). В результате будет создан объект Eviction,
который запустит процесс контролируемого завершения работы Pod'а.
Создание с помощью API объекта Eviction для Pod'а аналогично выполнению
операции DELETE
для этого Pod'а, которая контролируется политикой.
Вызов API Eviction
Для доступа к API Kubernetes и создания объекта Eviction можно воспользоваться клиентской библиотекой. Необходимая операция оформляется в виде POST-запроса (см. пример ниже):
При вытеснении, инициированном через API, сервер API выполняет admission-проверки
и отвечает одним из следующих способов:
200 OK: вытеснение разрешено, подресурс Eviction создан,
Pod удален (аналогично отправке запроса DELETE на URL Pod'а).
429 Too Many Requests: вытеснение в данный момент не разрешено из-за настроек
PodDisruptionBudget.
Попытку вытеснения можно повторить позже. Такой ответ также может быть вызван
работой механизма по ограничению частоты запросов к API.
500 Internal Server Error: вытесение запрещено из-за неправильной конфигурации;
например, несколько PodDisruptionBudget'ов могут ссылаться на один и тот же Pod.
Если Pod, предназначенный для вытеснения, не является частью рабочей нагрузки
с настроенным PodDisruptionBudget'ом, сервер API всегда возвращает 200 OK и
разрешает вытеснение.
В случае, если вытеснение разрешено, процесс удаления Pod'а выглядит следующим образом:
К ресурсу Pod на сервере API добавляется метка времени удаления,
после чего сервер API считает ресурс Pod завершенным (terminated). Ресурс Pod также помечается
настроенным grace-периодом.
kubelet на узле, где запущен
локальный Pod, замечает, что ресурс Pod помечен на удаление, и приступает к
корректному завершению работы локального Pod'а.
Пока kubelet завершает работу Pod'а, управляющий слой удаляет Pod из объектов
Endpoint и
EndpointSlice.
В результате контроллеры больше не рассматривают Pod как валидный объект.
После истечения периода корректного завершения работы (grace-периода) kubelet
принудительно завершает работу локального Pod'а.
kubelet передает API-серверу информацию о необходимости удалить ресурс Pod.
Сервер API удаляет ресурс Pod.
Зависшие вытеснения
В некоторых ситуациях сбой приводит к тому, что API Eviction начинает возвращать
исключительно ответы 429 или 500. Такое может случиться, если, например,
за создание Pod'ов для приложения отвечает ReplicaSet, однако новые Pod'ы не
переходят в состояние Ready. Подобное поведение также может наблюдаться в случаях,
когда у последнего вытесненного Pod'а слишком долгий период завершения работы (grace-период).
Одно из следующих решений может помочь решить проблему:
Прервите или приостановите автоматическую операцию, вызвавшую сбой.
Перед повторным запуском операции внимательно изучите сбойное приложение.
Подождите некоторое время, затем напрямую удалите Pod из управляющего слоя
кластера вместо того, чтобы пытаться удалить его с помощью Eviction API.