Podʼи можуть мати пріоритет. Пріоритет вказує на важливість Podʼа порівняно з іншими Podʼами. Якщо Pod не може бути запланований, планувальник намагається витіснити (виселити) Podʼи з нижчим пріоритетом, щоб зробити можливим планування Podʼа в очікуванні.
У кластері, де не всі користувачі є довіреними, зловмисник може створити Podʼи з найвищими можливими пріоритетами, що призведе до виселення інших Podʼів або неможливості їх планування. Адміністратор може використовувати ResourceQuota, щоб запобігти користувачам створювати Podʼи з високими пріоритетами.
Детальніше дивіться стандартне обмеження споживання Priority Class.
Для використання пріоритету та витіснення:
Додайте один чи кілька PriorityClasses.
Створіть Podʼи з параметром priorityClassName, встановленим на один з доданих PriorityClasses. Звісно, вам не потрібно створювати Podʼи безпосередньо; зазвичай ви додаєте priorityClassName до шаблону Podʼа обʼєкта колекції, такого як Deployment.
Продовжуйте читати для отримання додаткової інформації про ці кроки.
PriorityClass є обʼєктом, що не належить до простору імен, і визначає зіставлення назви класу пріоритету з цілим значенням пріоритету. Назва вказується в полі name метаданих обʼєкта PriorityClass. Значення вказується в обовʼязковому полі value. Чим вище значення, тим вищий пріоритет. Назва обʼєкта PriorityClass повинна бути дійсною назвою піддомену DNS, і вона не може мати префікс system-.
Обʼєкт PriorityClass може мати будь-яке 32-розрядне ціле значення, яке менше або дорівнює 1 мільярду. Це означає, що діапазон значень для обʼєкта PriorityClass становить від -2147483648 до 1000000000 включно. Більші числа зарезервовані для вбудованих PriorityClass, які представляють критичні системні Podʼи. Адміністратор кластера повинен створити один обʼєкт PriorityClass для кожного потрібного йому зіставлення.
system-cluster-critical та system-node-critical. Ці спільні класи використовуються для забезпечення того, що критичні компоненти завжди плануються першими. Для Kubernetes v1.37 їхні значення пріоритету становлять 2000000000 для system-cluster-critical і 2000001000 для system-node-critical.PriorityClass також має два необовʼязкові поля: globalDefault та description. Поле globalDefault вказує, що значення цього PriorityClass повинно використовуватися для Podʼів без priorityClassName. У системі може існувати лише один PriorityClass з globalDefault, встановленим в true. Якщо немає PriorityClass із встановленим globalDefault, пріоритет Podʼів без priorityClassName дорівнює нулю.
Поле description є довільним рядком. Воно призначене для сповіщення користувачів кластера про те, коли вони повинні використовувати цей PriorityClass.
Якщо ви оновлюєте наявний кластер без цієї можливості, пріоритет ваших наявних Podʼів фактично дорівнює нулю.
Додавання PriorityClass з globalDefault, встановленим в true, не змінює пріоритети наявних Podʼів. Значення такого PriorityClass використовується тільки для Podʼів, створених після додавання PriorityClass.
Якщо ви видаляєте PriorityClass, наявні Podʼи, які використовують назву видаленого PriorityClass, залишаються незмінними, але ви не можете створювати більше Podʼів, які використовують назву видаленого PriorityClass.
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for XYZ service pods only."
Podʼи з preemptionPolicy: Never будуть розміщені в черзі планування перед Podʼами з нижчим пріоритетом, але вони не можуть витісняти інші Podʼи. Pod без витіснення, який очікує на планування, залишиться в черзі планування, доки не буде достатньо вільних ресурсів і його можна буде запланувати. Podʼи без витіснення, як і інші Podʼи, підлягають backoff планувальника. Це означає, що якщо планувальник спробує запланувати ці Podʼи, і вони не можуть бути заплановані, повторні спроби будуть рідшими, що дозволяє іншим Podʼам з нижчим пріоритетом бути запланованими перед ними.
Podʼи без витіснення все ще можуть бути витіснені іншими Podʼами з високим пріоритетом.
Стандартне значення preemptionPolicy — PreemptLowerPriority, що дозволяє Podʼам цього PriorityClass витісняти Podʼи з нижчим пріоритетом (це наявна стандартна поведінка). Якщо preemptionPolicy встановлено в Never, Podʼи в цьому PriorityClass не витіснятимуть інші Podʼи.
Прикладом використання є робочі навантаження науки про дані. Користувач може надіслати завдання, якому він хоче дати пріоритет перед іншими робочими навантаженнями, але не бажає втрачати наявну роботу, витісняючи запущені Podʼи. Завдання з високим пріоритетом із preemptionPolicy: Never буде заплановано перед іншими Podʼами в черзі, щойно достатньо ресурсів кластера «природним чином» звільниться.
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority-nonpreempting
value: 1000000
preemptionPolicy: Never
globalDefault: false
description: "This priority class will not cause other pods to be preempted."
Після того, як у вас є один або кілька PriorityClasses, ви можете створювати Podʼи, які вказують одну з назв цих PriorityClasses у своїх специфікаціях. Контролер допуску пріоритетів використовує поле priorityClassName і заповнює ціле значення пріоритету. Якщо клас пріоритету не знайдено, Pod відхиляється.
Наведений нижче YAML — це приклад конфігурації Podʼа, який використовує PriorityClass, створений у попередньому прикладі. Контролер допуску пріоритетів перевіряє специфікацію та визначає пріоритет Podʼа як 1000000.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
priorityClassName: high-priority
Коли пріоритет Podʼа увімкнено, планувальник впорядковує Podʼи в очікуванні за їх пріоритетом, і Pod в очікуванні розташовується в черзі планування попереду інших Podʼів в очікуванні з нижчим пріоритетом. В результаті Pod з вищим пріоритетом може бути запланований швидше, ніж Podʼи з нижчим пріоритетом, якщо його вимоги до планування виконуються. Якщо такий Pod не може бути запланований, планувальник продовжить спроби запланувати інші Podʼи з нижчим пріоритетом.
To use this feature, you (or a cluster administrator) will need to enable the GenericWorkload feature gate for all relevant components in your cluster.
See Enable Or Disable Feature Gates for more information.
Коли функціональну можливість GenericWorkload увімкнено, PodGroups чергуються з окремими Podʼами в черзі планування. Обʼєкт PodGroup має власне поле priority, яке використовується для впорядкування відносно інших Podʼів та PodGroups. Деталі щодо того, як встановити пріоритет PodGroup, доступні на сторінці Порушення та пріоритет групи Podʼів.
To use this feature, you (or a cluster administrator) will need to enable the CompositePodGroup feature gate for all relevant components in your cluster.
See Enable Or Disable Feature Gates for more information.
Коли функціональну можливість CompositePodGroup увімкнено, планувальник розглядає наступні обʼєкти як одиниці планування, які можуть бути поставлені в чергу:
ParentCompositePodGroup,ParentCompositePodGroup.Ці обʼєкти вказують значення поля priority, яке використовується для визначення їх позиції в активній черзі планування.
Коли Podʼи створюються, вони потрапляють у чергу та очікують на планування. Планувальник вибирає Pod з черги та намагається запланувати його на вузлі. Якщо не знайдено жодного вузла, який задовольняє всі вказані вимоги Podʼа, для Podʼа в очікуванні спрацьовує логіка витіснення. Назвімо цей Pod в очікуванні P. Логіка витіснення спробує знайти вузол, де видалення одного або кількох Podʼів з нижчим пріоритетом, ніж P, дозволить запланувати P на цьому вузлі. Якщо такий вузол знайдено, один або кілька Podʼів з нижчим пріоритетом будуть виселені з вузла. Після того, як ці Podʼи зникнуть, P може бути запланований на вузлі.
To use this feature, you (or a cluster administrator) will need to enable the GenericWorkload feature gate for all relevant components in your cluster.
See Enable Or Disable Feature Gates for more information.
Коли функціональну можливість GenericWorkload увімкнено, PodGroups можуть брати участь у витісненні як ініціатор або як жертва. Коли PodGroup ініціює витіснення, він дотримується логіки витіснення з урахуванням робочого навантаження, щоб витіснити інші Podʼи та PodGroups і звільнити місце для себе. Коли Pod ініціює витіснення, PodGroup може стати жертвою. У цьому випадку поле priority PodGroup використовується для впорядкування відносно інших потенційних жертв, а поле disruptionMode використовується для визначення поведінки PodGroup під час порушення. Детальний опис цих полів доступний на сторінці Порушення та пріоритет групи Podʼів.
Коли Pod P витісняє один або кілька Podʼів на вузлі N, поле nominatedNodeName статусу Podʼа P встановлюється в назву вузла N. Це поле допомагає планувальнику відстежувати ресурси, зарезервовані для Podʼа P, і також надає користувачам інформацію про витіснення в їх кластерах.
Зверніть увагу, що Pod P не обовʼязково планується на «номінований вузол». Планувальник завжди спочатку спробує «номінований вузол», перед тим як перевіряти будь-які інші вузли. Після того, як Podʼи-жертви витіснено, вони отримують свій період коректного завершення. Якщо під час очікування на завершення роботи Podʼів-жертв стає доступним інший вузол, планувальник може використати інший вузол для планування Podʼа P. В результаті поля nominatedNodeName та nodeName специфікації Podʼа не завжди збігаються. Крім того, якщо планувальник витісняє Podʼи на вузлі N, а потім надходить Pod вищого пріоритету, ніж Pod P, планувальник може надати вузол N новому Podʼу вищого пріоритету. У такому випадку планувальник очищає nominatedNodeName Podʼа P. Цим самим планувальник робить Pod P придатним для витіснення Podʼів на іншому вузлі.
Коли Podʼи витісняються, жертви отримують свій період коректного завершення. У них є стільки часу, скільки вказано в цьому періоді, для завершення своєї роботи та виходу. Якщо вони цього не роблять, їх робота завершується примусово. Цей період коректного завершення створює проміжок часу між моментом, коли планувальник витісняє Podʼи, і моментом, коли Pod (P) в очікуванні може бути запланований на вузол (N). Тим часом планувальник продовжує планувати інші Podʼи в очікуванні. Поки жертви завершують роботу самі або примусово, планувальник намагається запланувати Podʼи з черги очікування. Тому зазвичай є проміжок часу між моментом, коли планувальник витісняє жертв, і моментом, коли Pod P буде заплановано. Щоб зменшити цей проміжок, можна встановити період коректного завершення для Podʼів з нижчим пріоритетом на нуль або мале число.
PodDisruptionBudget (PDB) дозволяє власникам застосунків обмежувати кількість Podʼів реплікованого застосунку, які одночасно недоступні через добровільні порушення. Kubernetes підтримує PDB під час витіснення Podʼів, але дотримання PDB відбувається за принципом best-effort. Планувальник намагається знайти жертв, PDB яких не буде перевищено в результаті витіснення, але якщо жодної такої жертви не знайдено, витіснення все одно відбудеться, і Podʼи з нижчим пріоритетом будуть видалені, попри перевищення їхнього PDB.
Вузол розглядається для витіснення тільки тоді, коли відповідь на це питання ствердна: «Якщо всі Podʼи з нижчим пріоритетом, ніж Pod в очікуванні, будуть видалені з вузла, чи може Pod в очікуванні бути запланований на цьому вузлі?»
Якщо Pod в очікуванні має спорідненість між Podʼами з одним або кількома Podʼами з нижчим пріоритетом на вузлі, правило спорідненості між Podʼами не може бути виконане за відсутності цих Podʼів з нижчим пріоритетом. У цьому випадку планувальник не витісняє жодних Podʼів на вузлі. Замість цього він шукає інший вузол. Планувальник може знайти відповідний вузол або може і не знайти. Немає гарантії, що Pod в очікуванні може бути запланований.
Рекомендованим рішенням для цієї проблеми є створення спорідненості між Podʼами лише з Podʼами з рівним або вищим пріоритетом.
Припустимо, що вузол N розглядається для витіснення, щоб запланувати Pod P в очікуванні на N. Планування P на N може стати здійсненним лише у випадку витіснення Podʼа на іншому вузлі. Ось приклад:
topologyKey: topology.kubernetes.io/zone).Якщо Pod Q буде видалено зі свого вузла, порушення антиспорідненості Podʼа буде усунено, і Pod P, можливо, можна буде запланувати на вузлі N.
Ми можемо розглянути додавання міжвузлового витіснення в майбутніх версіях, якщо буде достатньо попиту і якщо ми знайдемо алгоритм з прийнятною продуктивністю.
To use this feature, you (or a cluster administrator) will need to enable the InPlacePodVerticalScalingSchedulerPreemption feature gate for all relevant components in your cluster.
See Enable Or Disable Feature Gates for more information.
Коли функціональну можливість InPlacePodVerticalScalingSchedulerPreemption увімкнено, витіснення також застосовується, коли запит на зміну розміру запущеного Podʼа на місці має статус Deferred (тобто запитана зміна розміру тимчасово неможлива, але може стати можливою пізніше) через недостатню місткість вузла. Деталі щодо станів зміни розміру дивіться в статусі зміни розміру Podʼа.
Якщо Pod вищого пріоритету не може бути змінений на місці, оскільки його вузлу бракує доступних CPU або памʼяті, kube-scheduler намагається витіснити Podʼи нижчого пріоритету на цьому вузлі, щоб звільнити необхідну місткість.
Витіснення для зміни розміру Podʼа на місці відрізняється від стандартного витіснення під час розміщення Podʼа кількома ключовими способами:
Deferred.nominatedNodeName у статусі Podʼа не встановлюється, оскільки Pod вже призначений і працює на своєму цільовому вузлі.spec.podPreemptionPolicy.disableResizePreemption специфікації Node. На відміну від стандартного витіснення, яке можна вимкнути лише для кожного класу пріоритету за допомогою preemptionPolicy: Never, це дозволяє операторам або системам автомасштабування вимикати витіснення на окремих вузлах.Для отримання додаткових деталей про зміну розміру Podʼа на місці дивіться Зміна розміру CPU та памʼяті, призначених контейнерам.
Оператори кластера та контролери можуть вимикати ініційоване планувальником витіснення, спричинене запитами на зміну розміру Podʼа на місці, на конкретних вузлах. Це корисно для вузлів, розмір яких можна змінювати, або вузлів із власними рішеннями автомасштабування, захищаючи наявні робочі навантаження від порушення та дозволяючи натомість усунути дефіцит ресурсів збільшенням розміру вузла.
Це налаштовується за допомогою поля spec.podPreemptionPolicy у специфікації Node. Якщо список disableResizePreemption не порожній, витіснення, спричинене зміною розміру, вимикається на цьому вузлі, і kube-scheduler пропускатиме спроби витіснення для будь-яких відкладених змін розміру, що виконуються на цьому вузлі.
Ось приклад конфігурації Node:
apiVersion: v1
kind: Node
metadata:
name: resizable-node
spec:
podPreemptionPolicy:
disableResizePreemption:
- autoscaling.k8s.io/cluster-autoscaler
- autoscaling.k8s.io/vpa-updater
Обмеження та правила перевірки:
disableResizePreemption повинен відповідати стандартному формату ключа мітки Kubernetes (наприклад, префікс піддомену DNS та назва, розділені /).podPreemptionPolicy опущено, витіснення для зміни розміру на місці увімкнено на вузлі.Пріоритет та витіснення Podʼа можуть мати небажані побічні ефекти. Ось кілька прикладів потенційних проблем і способів їх вирішення.
Витіснення видаляє наявні Podʼи з кластера під тиском на ресурси, щоб звільнити місце для високопріоритетних Podʼів в очікуванні. Якщо ви помилково встановили високі пріоритети для певних Podʼів, ці ненавмисно високопріоритетні Podʼи можуть спричинити витіснення у вашому кластері. Пріоритет Podʼа вказується встановленням поля priorityClassName в специфікації Podʼа. Потім ціле значення пріоритету визначається і заповнюється у поле priority podSpec.
Щоб розвʼязати цю проблему, ви можете змінити priorityClassName для цих Podʼів, щоб використовувати класи з нижчим пріоритетом, або залишити це поле порожнім. Порожній priorityClassName стандартно вважається нулем.
Коли Pod витісняється, для такого Podʼа будуть записані події. Витіснення повинно відбуватися лише тоді, коли в кластері недостатньо ресурсів для Podʼа. У таких випадках витіснення відбувається лише тоді, коли пріоритет Podʼа в очікуванні (витіснювача) вищий, ніж у Podʼів-жертв. Витіснення не повинно відбуватися, коли немає Podʼа в очікуванні, або коли Podʼи в очікуванні мають рівні або нижчі пріоритети, ніж у жертв. Якщо витіснення відбувається в таких сценаріях, будь ласка, повідомте про проблему.
Коли Podʼи витісняються, вони отримують запитаний період коректного завершення, який стандартно становить 30 секунд. Якщо Podʼи-жертви не завершуються протягом цього періоду, вони завершуються примусово. Після того, як усі жертви зникають, Pod-витіснювач може бути запланований.
Поки Pod-витіснювач чекає, доки жертви зникнуть, може бути створений Pod з вищим пріоритетом, який підходить на той самий вузол. У цьому випадку планувальник запланує Pod з вищим пріоритетом замість витіснювача.
Це очікувана поведінка: Pod з вищим пріоритетом повинен зайняти місце Podʼа з нижчим пріоритетом.
Планувальник намагається знайти вузли, на яких можна запустити Pod в очікуванні. Якщо вузол не знайдено, планувальник намагається видалити Podʼи з нижчим пріоритетом з довільного вузла, щоб звільнити місце для Podʼа в очікуванні. Якщо вузол з Podʼами низького пріоритету не може бути використаний для запуску Podʼа в очікуванні, планувальник може вибрати інший вузол з Podʼами вищого пріоритету (порівняно з Podʼами на іншому вузлі) для витіснення. Жертви все ще повинні мати нижчий пріоритет, ніж Pod-витіснювач.
Коли є доступні кілька вузлів для витіснення, планувальник намагається вибрати вузол з набором Podʼів з найнижчим пріоритетом. Однак якщо такі Podʼи мають PodDisruptionBudget, який буде перевищено, якщо вони будуть витіснені, то планувальник може вибрати інший вузол з Podʼами вищого пріоритету.
Коли є кілька вузлів для витіснення і жоден з вищезазначених сценаріїв не застосовується, планувальник вибирає вузол з найнижчим пріоритетом.
Пріоритет Podʼа та клас якості обслуговування є двома ортогональними можливостями з невеликою кількістю взаємодій та без стандартних обмежень щодо встановлення пріоритету Podʼа на основі його класів QoS. Логіка витіснення планувальника не враховує QoS під час вибору цілей витіснення. Витіснення враховує пріоритет Podʼа і намагається вибрати набір цілей з найнижчим пріоритетом. Podʼи вищого пріоритету розглядаються для витіснення лише тоді, коли видалення Podʼів з найнижчим пріоритетом не є достатнім для того, щоб дозволити планувальнику розмістити Pod-витіснювач, або якщо Podʼи з найнижчим пріоритетом захищені PodDisruptionBudget.
kubelet використовує пріоритет для визначення порядку Podʼів для виселення внаслідок тиску на вузол. Ви можете використовувати клас QoS для оцінки порядку, в якому найімовірніше будуть виселятися Podʼи. kubelet ранжує Podʼи для виселення на основі таких факторів:
Дивіться Вибір Podʼа для виселення kubelet для отримання додаткової інформації.
Виселення kubelet внаслідок тиску на вузол не виселяє Podʼи, коли їх використання не перевищує їх запити. Якщо Pod з нижчим пріоритетом не перевищує свої запити, він не буде виселений. Інший Pod з вищим пріоритетом, який перевищує свої запити, може бути виселений.