Цей посібник призначений для власників застосунків, які хочуть створити високодоступні застосунки та, таким чином, повинні розуміти, які типи порушень можуть трапитися з Podʼами.
Також це стосується адміністраторів кластера, які хочуть виконувати автоматизовані дії з кластером, такі як оновлення та автомасштабування кластерів.
Podʼи не зникають, поки хтось (людина або контролер) не знищить їх, або не трапиться невідворотна помилка обладнання чи системного програмного забезпечення.
Ми називаємо ці невідворотні випадки невідворотними порушеннями застосунку. Приклади:
Окрім вичерпання ресурсів, усі ці ситуації мають бути знайомі більшості користувачів; вони не є специфічними для Kubernetes.
Ми називаємо інші випадки добровільними порушеннями. До них належать як дії, ініційовані власником застосунку, так і ті, які ініціює адміністратор кластера. Типові дії власника застосунку включають:
Дії адміністратора кластера включають:
Ці дії можуть бути виконані безпосередньо адміністратором кластера чи за допомогою автоматизації, запущеної адміністратором кластера, або вашим провайдером хостингу кластера.
Зверніться до адміністратора кластера або проконсультуйтеся з документацією вашого хмарного провайдера або дистрибутиву, щоб визначити, чи увімкнено які-небудь джерела добровільних порушень для вашого кластера. Якщо жодне з них не увімкнено, ви можете пропустити створення бюджетів порушень Podʼів (Pod Disruption Budget).
Ось кілька способів помʼякшення невідворотних порушень:
Частота добровільних порушень різниться. На базовому кластері Kubernetes немає автоматизованих добровільних порушень (тільки ті, які ініціює користувач). Однак адміністратор кластера або провайдер хостингу може запускати деякі додаткові сервіси, які призводять до добровільних порушень. Наприклад, розгортання оновлень програмного забезпечення вузла може призвести до добровільних порушень. Також деякі реалізації автомасштабування кластера (вузла) можуть призводити до добровільних порушень для дефрагментації та ущільнення вузлів. Адміністратор кластера або провайдер хостингу мають задокументувати, якого рівня добровільних порушень, якщо такі є, слід очікувати. Деякі параметри конфігурації, такі як використання PriorityClasses у вашій специфікації Podʼа, також можуть призводити до добровільних (і невідворотних) порушень.
Kubernetes пропонує функції, що допомагають запускати застосунки з високою доступністю навіть тоді, коли ви допускаєте часті добровільні порушення.
Як власник застосунку, ви можете створити бюджет порушень Podʼів (PodDisruptionBudget, PDB) для кожного застосунку. PDB обмежує кількість Podʼів реплікованого застосунку, які можуть одночасно не працювати через добровільні порушення. Наприклад, застосунок на основі кворуму хоче гарантувати, що кількість запущених реплік ніколи не впаде нижче необхідної для кворуму. Вебфронтенд може хотіти гарантувати, що кількість реплік, які обслуговують навантаження, ніколи не впаде нижче певного відсотка від загальної кількості.
Менеджери кластерів та провайдери хостингу повинні використовувати інструменти, які дотримуються бюджетів порушень Podʼів, викликаючи Eviction API замість прямого видалення Podʼів або Deployments.
Наприклад, команда kubectl drain дозволяє вам позначити вузол як такий, що виводиться з експлуатації. Коли ви виконуєте kubectl drain, інструмент намагається виселити всі Podʼи з вузла, який ви виводите з експлуатації. Запит на виселення, який kubectl робить від вашого імені, може тимчасово бути відхилено, тому інструмент періодично повторює всі невдалі запити, доки всі Podʼи на цільовому вузлі не будуть завершені або доки не буде досягнуто налаштованого тайм-ауту.
PDB визначає кількість реплік, яку застосунок може витримати, порівняно з тим, скільки їх має бути. Наприклад, Deployment, який має .spec.replicas: 5, повинен мати 5 Podʼів в будь-який момент часу. Якщо PDB дозволяє бути 4 Podʼам одночасно, то Eviction API дозволить добровільне порушення роботи одного (але не двох) Podʼів одночасно.
Група Podʼів, з яких складається застосунок, визначається за допомогою селектора міток, такого самого, як і той, який використовується контролером застосунку (deployment, stateful-set тощо).
"Передбачена" кількість Podʼів обчислюється з .spec.replicas ресурсу робочого навантаження, який керує цими Podʼами. Панель управління визначає ресурс робочого навантаження, що володіє Podʼом, оглядаючи .metadata.ownerReferences Podʼа.
Невідворотні порушення неможливо запобігти за допомогою PDB; однак вони враховуються в бюджеті.
Podʼи, які видаляються або недоступні через поетапне оновлення застосунку, дійсно враховуються в бюджеті порушень, але ресурси робочого навантаження (такі як Deployment і StatefulSet) не обмежуються PDB під час поетапного оновлення. Натомість обробка збоїв під час оновлення застосунку налаштовується в специфікації конкретного ресурсу робочого навантаження.
Рекомендується встановлювати політику виселення несправних Podʼів AlwaysAllow у ваших PodDisruptionBudgets для підтримки виселення застосунків, що працюють неправильно, під час очищення вузла. Стандартно очищення чекає, доки Podʼи застосунку стануть справними, перш ніж продовжитися.
Коли Pod виселяється за допомогою API виселення, він коректно завершується з урахуванням налаштування terminationGracePeriodSeconds його PodSpec.
Припустимо, що у кластері є 3 вузли, від node-1 до node-3. У кластері працює кілька застосунків. Один з них має 3 репліки, які спочатку називаються pod-a, pod-b і pod-c. Також показано інший, не повʼязаний з ними Pod без PDB — pod-x. Спочатку Podʼи розташовані так:
| node-1 | node-2 | node-3 |
|---|---|---|
| pod-a доступний | pod-b доступний | pod-c доступний |
| pod-x доступний |
Усі 3 Podʼи є частиною Deployment, і вони разом мають PDB, який вимагає, щоб одночасно було доступними принаймні 2 з 3 Podʼів.
Наприклад, припустимо, що адміністратор кластера хоче перезавантажитися в нову версію ядра, щоб виправити помилку в ядрі. Адміністратор кластера спочатку намагається очистити node-1 за допомогою команди kubectl drain. Цей інструмент намагається виселити pod-a і pod-x. Це вдається негайно. Обидва Podʼи одночасно переходять у стан terminating. Це переводить кластер у стан:
| node-1 очищується | node-2 | node-3 |
|---|---|---|
| pod-a завершується | pod-b доступний | pod-c доступний |
| pod-x завершується |
Deployment помічає, що один з Podʼів завершується, тому він створює заміну під назвою pod-d. Оскільки node-1 закрито для планування (cordoned), заміна опиняється на іншому вузлі. Також щось створило pod-y як заміну для pod-x.
(Примітка: для StatefulSet, pod-a, який міг би мати назву щось на зразок pod-0, повинен був би повністю завершити свою роботу,
перш ніж його заміна, яка також має назву pod-0, але має інший UID, може бути створена. В іншому випадку приклад застосовується і до StatefulSet.)
Тепер кластер перебуває у такому стані:
| node-1 очищується | node-2 | node-3 |
|---|---|---|
| pod-a завершується | pod-b доступний | pod-c доступний |
| pod-x завершується | pod-d запускається | pod-y |
У якийсь момент Podʼи завершують свою роботу, і кластер виглядає так:
| node-1 очищений | node-2 | node-3 |
|---|---|---|
| pod-b доступний | pod-c доступний | |
| pod-d запускається | pod-y |
На цьому етапі, якщо нетерплячий адміністратор кластера намагається очистити node-2 або node-3, команда очищення буде заблокована, оскільки доступно тільки 2 Podʼи для Deployment, і його PDB вимагає принаймні 2. Після того, як пройде певний час, pod-d стає доступним.
Тепер стан кластера виглядає так:
| node-1 очищений | node-2 | node-3 |
|---|---|---|
| pod-b доступний | pod-c доступний | |
| pod-d доступний | pod-y |
Тепер адміністратор кластера намагається очистити node-2. Команда drain спробує виселити два Podʼи в певному порядку, скажімо, спочатку pod-b, а потім pod-d. Їй вдасться виселити pod-b. Але коли вона спробує виселити pod-d, то отримає відмову, через те, що це залишить тільки один доступний Pod для Deployment.
Deployment створює заміну для pod-b з назвою pod-e. Оскільки в кластері недостатньо ресурсів для планування pod-e, очищення знову буде заблоковано. Кластер може опинитися в такому стані:
| node-1 очищений | node-2 | node-3 | немає вузла |
|---|---|---|---|
| pod-b завершується | pod-c доступний | pod-e очікує | |
| pod-d доступний | pod-y |
На цьому етапі адміністратор кластера повинен додати вузол назад до кластера, щоб продовжити оновлення.
Ви можете побачити, як Kubernetes змінює частоту випадків порушень відповідно до:
This is a stable feature in Kubernetes, and has been since the 1.31 release. You can no longer toggle this feature (the associated feature gate has been removed).
Спеціальний стан Podʼа DisruptionTarget додається для того, щоб вказати, що Pod буде видалено через порушення. Поле reason цього стану додатково вказує одну з таких причин завершення Podʼа:
PreemptionBySchedulerDeletionByTaintManagerkube-controller-manager) через NoExecute taint, який Pod не толерує; див. виселення на основі taint.EvictionByEvictionAPIDeletionByPodGCTerminationByKubeletУ всіх інших сценаріях порушення, таких як виселення через перевищення обмежень контейнерів Podʼа, Podʼи не отримують стан DisruptionTarget, оскільки ці порушення, ймовірно, були спричинені самим Podʼом і повторилися б під час повторної спроби.
DisruptionTarget може бути додано до Podʼа, але цей Pod може фактично не бути видаленим. У такій ситуації через деякий час стан порушення роботи Podʼа буде очищено.Разом з очищенням Podʼів механізм збору сміття Podʼів (PodGC) також позначає їх як невдалі, якщо вони перебувають у нетермінальній фазі (див. також збір сміття Podʼів).
Під час використання Job (або CronJob) ви можете використовувати ці стани порушення роботи Podʼів як частину політики збоїв Podʼа вашого Job.
Часто корисно розглядати менеджера кластера і власника застосунку як окремі ролі з обмеженим знанням одне про одного. Це розділення обовʼязків може мати сенс у таких сценаріях:
Бюджети порушень Podʼів підтримують це розділення ролей, надаючи інтерфейс між цими ролями.
Якщо у вашій організації немає такого розділення обовʼязків, вам може не знадобитися використовувати бюджети порушень Podʼів.
Якщо ви є адміністратором кластера і вам потрібно виконати дію, що порушує роботу, на всіх вузлах вашого кластера, таку як оновлення вузла чи системного програмного забезпечення, ось кілька варіантів:
Виконайте кроки для захисту вашого застосунку, налаштувавши бюджет порушень Podʼів.
Дізнайтеся більше про очищення вузлів.
Дізнайтеся про оновлення Deployment, включаючи кроки для забезпечення його доступності під час розгортання.