Kubernetes надає кілька вбудованих API для декларативного керування вашими робочими навантаженнями та їх компонентами.
У кінцевому підсумку ваші застосунки працюють як контейнери всередині Podʼів; однак керування окремими Podʼами вимагало б багато зусиль. Наприклад, якщо Pod зазнає збою, ви, ймовірно, захочете запустити новий Pod для його заміни. Kubernetes може зробити це за вас.
Ви використовуєте API Kubernetes для створення обʼєкта робочого навантаження, який представляє вищий рівень абстракції, ніж Pod, а потім панель управління Kubernetes автоматично керує обʼєктами Pod від вашого імені, відповідно до специфікації обʼєкта робочого навантаження, яку ви визначили.
Вбудовані API для керування робочими навантаженнями:
Deployment (і, опосередковано, ReplicaSet), найпоширеніший спосіб запуску застосунку у вашому кластері. Deployment є хорошим вибором для керування робочим навантаженням, яке не зберігає стану, де будь-який Pod у Deployment є взаємозамінним і може бути замінений, якщо це потрібно. (Deployments є заміною застарілого API ReplicationController).
StatefulSet дозволяє вам керувати одним або кількома Podʼами, які виконують один і той самий код застосунку, де Podʼи покладаються на наявність окремої ідентичності. Це відрізняється від Deployment, де очікується, що Podʼи будуть взаємозамінними. Найпоширеніше використання StatefulSet полягає в тому, щоб забезпечити звʼязок між Podʼами та їх постійним сховищем. Наприклад, ви можете запустити StatefulSet, який повʼязує кожен Pod із PersistentVolume. Якщо один з Podʼів у StatefulSet зазнає збою, Kubernetes створює Pod-замінник, підключений до того самого PersistentVolume.
DaemonSet визначає Podʼи, які надають можливості, що є локальними для конкретного вузла; наприклад, драйвер, який дозволяє контейнерам на цьому вузлі отримувати доступ до системи зберігання. Ви використовуєте DaemonSet, коли драйвер або інший сервіс рівня вузла має працювати на вузлі, де він корисний. Кожен Pod в DaemonSet виконує роль, схожу на системний демон на класичному сервері Unix/POSIX. DaemonSet може бути фундаментальним для роботи вашого кластера, наприклад, як втулок, який надає цьому вузлу доступ до мережі кластера, він може допомогти вам керувати вузлом, або надати менш важливі можливості, які покращують платформу контейнерів, яку ви використовуєте. Ви можете запускати DaemonSets (та їхні Podʼи) на кожному вузлі вашого кластера або лише на підмножині (наприклад, встановити драйвер прискорювача GPU лише на вузлах, де встановлено GPU).
Ви можете використовувати Job та/або CronJob для визначення завдань, які виконуються до завершення та зупиняються. Job представляє одноразове завдання, тоді як кожен CronJob повторюється згідно з розкладом.
Інші теми в цьому розділі:
1 - Deployments
Deployment керує набором Podʼів для запуску робочого навантаження застосунку, зазвичай такого, що не зберігає стан.
Deployment забезпечує декларативні оновлення для Podʼів та ReplicaSets.
Ви описуєте бажаний стан у Deployment, і контролер Deployment змінює фактичний стан на бажаний з контрольованою швидкістю. Ви можете визначити Deployments для створення нових ReplicaSets або для видалення наявних Deployments і перейняття всіх їхніх ресурсів новими Deployments.
Примітка:
Не керуйте ReplicaSets, що належать Deployment. Розгляньте можливість створення тікета в основному репозиторії Kubernetes, якщо ваш випадок використання не врахований нижче.
Оголошення нового стану Podʼів шляхом оновлення PodTemplateSpec в Deployment. Створюється новий ReplicaSet, і Deployment поступово нарощує кількість його елементів, водночас зменшуючи старий ReplicaSet, забезпечуючи контрольовану заміну Podʼів. Кожен новий ReplicaSet оновлює ревізію Deployment.
Створюється Deployment з назвою nginx-deployment, назва вказується в полі .metadata.name. Ця назва буде основою для ReplicaSets та Podʼів, які буде створено потім. Докладніше див. у розділі Написання специфікації Deployment.
Deployment створює ReplicaSet, який створює три реплікованих Podʼи, кількість зазначено у полі .spec.replicas.
Поле .spec.selector визначає, як створений ReplicaSet відшукує Podʼи для керування. У цьому випадку вибирається мітка, визначена в шаблоні Podʼа (app: nginx). Однак можливі складніші правила вибору, якщо сам шаблон Podʼа задовольняє це правило.
Примітка:
Поле .spec.selector.matchLabels є мапою пар {key,value}. Одна пара {key,value} у мапі matchLabels еквівалентна елементу matchExpressions, де поле key — "key", operator — "In", а масив values містить лише "value". Всі умови, як від matchLabels, так і від matchExpressions, повинні бути виконані для отримання збігу.
Поле .spec.template має такі вкладені поля:
Podʼи позначаються міткою app: nginx з поля .metadata.labels.
Специфікація шаблону Podʼа, або поле .spec, вказує на те, що Podʼи запускають один контейнер, nginx, який використовує образ nginx з Docker Hub версії 1.14.2.
Створюється один контейнер із назвою nginx, вказаною в полі .spec.containers[0].name.
Перш ніж почати, переконайтеся, що ваш кластер Kubernetes працює. Дотримуйтесь наведених нижче кроків для створення наведеного вище Deployment:
Виконайте kubectl get deployments для перевірки створення Deployment.
Якщо Deployment все ще створюється, ви побачите вивід, подібний до цього:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 0/3 0 0 1s
Коли ви переглядаєте Deployments у вашому кластері, показуються такі поля:
NAME — містить назви Deployments у просторі імен.
READY — показує, скільки реплік застосунку доступно користувачам. Значення відповідає шаблону готово/бажано.
UP-TO-DATE — показує кількість реплік, які були оновлені для досягнення бажаного стану.
AVAILABLE — показує, скільки реплік застосунку доступно користувачам.
AGE — показує час впродовж якого застосунок працює.
Зверніть увагу, що бажана кількість реплік дорівнює 3 відповідно до поля .spec.replicas.
Для перевірки стану розгортання Deployment виконайте kubectl rollout status deployment/nginx-deployment.
Вивід буде подібний до цього:
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment "nginx-deployment" successfully rolled out
Запустіть kubectl get deployments знов через кілька секунд. Вивід буде подібний до цього:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 18s
Зверніть увагу, що Deployment створив усі три репліки, і всі репліки актуальні (вони містять останній шаблон Podʼа) та доступні.
Для перевірки ReplicaSet (rs), створеного Deployment, виконайте kubectl get rs. Вивід буде подібний до цього:
NAME DESIRED CURRENT READY AGE
nginx-deployment-75675f5897 3 3 3 18s
Вивід ReplicaSet має такі поля:
NAME — перелік назв ReplicaSets в просторі імен.
DESIRED — показує бажану кількість реплік застосунку, яку ви вказали під час створення Deployment. Це бажаний стан.
CURRENT — показує, скільки реплік працює зараз.
READY — показує, скільки реплік застосунку доступно користувачам.
AGE — показує час впродовж якого застосунок працює.
Зверніть увагу, що назва ReplicaSet завжди складається як [DEPLOYMENT-NAME]-[HASH]. Ця назва буде основою для назв Podʼів, які буде створено потім.
Рядок HASH є відповідником мітки pod-template-hash в ReplicaSet.
Для ознайомлення з мітками, автоматично створеними для кожного Podʼа, виконайте kubectl get pods --show-labels.
Вивід буде схожим на це:
NAME READY STATUS RESTARTS AGE LABELS
nginx-deployment-75675f5897-7ci7o 1/1 Running 0 18s app=nginx,pod-template-hash=75675f5897
nginx-deployment-75675f5897-kzszj 1/1 Running 0 18s app=nginx,pod-template-hash=75675f5897
nginx-deployment-75675f5897-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=75675f5897
Створений ReplicaSet гарантує наявність трьох Podʼів nginx.
Примітка:
Ви маєте зазначити відповідний селектор та мітки шаблону Podʼа в Deployment (у цьому випадку app: nginx).
Не допускайте перетину міток або селекторів з іншими контролерами (включаючи інші Deployments та StatefulSets). Kubernetes не завадить вам це зробити, і якщо кілька контролерів мають селектори, що перетинаються, ці контролери можуть конфліктувати та поводитись непередбачувано.
Мітка pod-template-hash
Увага:
Не змінюйте цю мітку.
Мітка pod-template-hash додається контролером Deployment до кожного ReplicaSet, який створює або переймає Deployment.
Ця мітка гарантує, що дочірні ReplicaSets Deployment не перетинаються. Вона генерується шляхом хешування PodTemplate ReplicaSet, і отриманий хеш використовується як значення мітки, яке додається до селектора ReplicaSet, міток шаблону Podʼа, а також до всіх наявних Podʼів, які можуть бути у ReplicaSet.
Оновлення Deployment
Примітка:
Розгортання Deployment запускається тоді й лише тоді, коли змінюється шаблон Podʼа Deployment (тобто .spec.template), наприклад, якщо оновлено мітки чи образи контейнерів шаблону. Інші оновлення, такі як масштабування Deployment, не запускають розгортання.
Дотримуйтеся поданих нижче кроків для оновлення вашого Deployment:
Оновіть Podʼи nginx, щоб використовувати образ nginx:1.16.1 замість nginx:1.14.2.
kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
або використовуйте таку команду:
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
де deployment/nginx-deployment вказує на Deployment, nginx — на контейнер, який буде оновлено, і nginx:1.16.1 — на новий образ та його теґ.
Вивід буде подібний до цього:
deployment.apps/nginx-deployment image updated
Або ви можете відредагувати (edit) Deployment і змінити .spec.template.spec.containers[0].image з nginx:1.14.2 на nginx:1.16.1:
kubectl edit deployment/nginx-deployment
Вивід буде подібний до цього:
deployment.apps/nginx-deployment edited
Щоб перевірити статус розгортання, виконайте:
kubectl rollout status deployment/nginx-deployment
Вивід буде подібний до цього:
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
або
deployment "nginx-deployment" successfully rolled out
Отримайте більше деталей про ваш оновлений Deployment:
Після успішного розгортання можна переглянути Deployment за допомогою kubectl get deployments. Вивід буде подібний до цього:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 36s
Виконайте kubectl get rs, щоб перевірити, що Deployment оновив Podʼи, створивши новий ReplicaSet і масштабувавши його до 3 реплік, а також зменшивши розмір старого ReplicaSet до 0 реплік.
kubectl get rs
Вивід буде подібний до цього:
NAME DESIRED CURRENT READY AGE
nginx-deployment-1564180365 3 3 3 6s
nginx-deployment-2035384211 0 0 0 36s
Виклик get pods повинен тепер показати лише нові Podʼи:
kubectl get pods
Вивід буде подібний до цього:
NAME READY STATUS RESTARTS AGE
nginx-deployment-1564180365-khku8 1/1 Running 0 14s
nginx-deployment-1564180365-nacti 1/1 Running 0 14s
nginx-deployment-1564180365-z9gth 1/1 Running 0 14s
Наступного разу, коли вам потрібно буде оновити ці Podʼи, вам достатньо буде знову оновити шаблон Podʼа в Deployment.
Deployment гарантує, що під час оновлення недоступною буде лише певна кількість Podʼів. Типово він гарантує, що працюватимуть принаймні 75% бажаної кількості Podʼів (максимум 25% недоступних).
Deployment також гарантує, що понад бажану кількість Podʼів буде створено лише певну кількість. Типово він гарантує, що працюватимуть щонайбільше 125% бажаної кількості Podʼів (максимальне перевищення 25%).
Наприклад, якщо ви ретельно досліджуєте Deployment вище, ви побачите, що спочатку було створено новий Pod, потім видалено старий Pod і створено ще один новий. Старі Podʼи не прибираються допоки не зʼявиться достатня кількість нових, і не створюються нові Podʼи допоки не буде прибрано достатню кількість старих. Deployment гарантує, що доступні принаймні 3 Podʼи, а загалом доступно щонайбільше 4 Podʼи. У випадку розгортання з 4 репліками кількість Podʼів буде між 3 і 5.
Отримайте деталі вашого Deployment:
kubectl describe deployments
Вивід буде подібний до цього:
Name: nginx-deployment
Namespace: default
CreationTimestamp: Thu, 30 Nov 2017 10:56:25 +0000
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision=2
Selector: app=nginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.16.1
Port: 80/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: nginx-deployment-1564180365 (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 2m deployment-controller Scaled up replica set nginx-deployment-2035384211 to 3
Normal ScalingReplicaSet 24s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 1
Normal ScalingReplicaSet 22s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 2
Normal ScalingReplicaSet 22s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 2
Normal ScalingReplicaSet 19s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 1
Normal ScalingReplicaSet 19s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 3
Normal ScalingReplicaSet 14s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 0
Тут ви бачите, що під час створення Deployment спочатку було створено ReplicaSet (nginx-deployment-2035384211) та масштабовано його до 3 реплік безпосередньо. Коли ви оновили Deployment, було створено новий ReplicaSet (nginx-deployment-1564180365) та масштабовано його до 1, потім Deployment дочекався, коли він запуститься. Потім було зменшено розмір старого ReplicaSet
до 2 і масштабовано новий ReplicaSet до 2, таким чином, щоб принаймні 3 Podʼи були доступні, і не більше 4 Podʼів в будь-який момент. Потім було продовжено масштабування нового та старого ReplicaSet, з однаковою стратегією поетапного оновлення. Зрештою у вас буде 3 доступні репліки в новому ReplicaSet, а старий ReplicaSet буде зменшено до 0.
Примітка:
Kubernetes не враховує Podʼи, які завершують роботу, коли розраховує кількість availableReplicas, яка повинна бути між replicas - maxUnavailable та replicas + maxSurge. Внаслідок цього ви можете помітити, що під час розгортання є більше Podʼів, ніж очікувалося, і що загальні ресурси, які використовує Deployment, перевищують replicas + maxSurge до того моменту, поки не мине terminationGracePeriodSeconds для Podʼів, що завершують роботу.
Rollover (або кілька одночасних оновлень)
Кожного разу, коли контролер Deployment виявляє новий Deployment, створюється ReplicaSet для запуску необхідних Podʼів. Якщо Deployment оновлюється, поточний ReplicaSet, який контролює Podʼи, мітки яких відповідають .spec.selector, але шаблон яких не відповідає .spec.template, зменшується. Врешті-решт новий ReplicaSet масштабується до .spec.replicas, а всі старі ReplicaSets масштабуються до 0.
Якщо ви оновите Deployment під час наявного процесу розгортання, Deployment створить новий ReplicaSet відповідно до оновлення, почне масштабувати його і перекине (roll over) ReplicaSet, який масштабував раніше: він додасть його до свого списку старих ReplicaSets і почне зменшувати його масштаб.
Наприклад, припустимо, ви створюєте Deployment для створення 5 реплік nginx:1.14.2, але потім оновлюєте Deployment для створення 5 реплік nginx:1.16.1, коли вже створено тільки 3 репліки nginx:1.14.2. У цьому випадку Deployment негайно починає
знищувати 3 Podʼи nginx:1.14.2, які вже створено, і починає створювати
Podʼи nginx:1.16.1. Deployment не чекає, доки буде створено 5 реплік nginx:1.14.2, перш ніж змінити напрямок.
Оновлення селектора міток
Зазвичай не рекомендується вносити оновлення до селектора міток, і рекомендується планувати ваші селектори наперед.
Селектор міток Deployment є незмінним після створення; його не можна оновити за допомогою kubectl patch, kubectl edit, kubectl apply або інструментів, таких як helm upgrade.
Якщо вам потрібно змінити селектор, вам доведеться видалити Deployment і створити його заново. Стандартно видалення Deployment також видаляє його запущені Podʼи, що призводить до простою; використовуйте --cascade=orphan, якщо вам потрібно, щоб ці Podʼи продовжували працювати під час повторного створення Deployment (див. наслідки нижче). Будьте дуже обережні та переконайтеся, що ви розумієте такі наслідки:
Додавання: Коли ви створюєте новий Deployment з більш вузьким селектором, новий Deployment повинен також мати відповідний шаблон Podʼа. Якщо у вас є наявний маніфест і ви редагуєте його, щоб звузити селектор, вам потрібно відредагувати метадані шаблону Podʼа всередині цього Deployment, додавши нові мітки для відповідності, інакше API-сервер поверне помилку валідації. Це зміна без перетину: новий Deployment не "побачить" старі Podʼи (які не мають нової мітки), тому старий ReplicaSet стане сирітським і буде створено абсолютно новий ReplicaSet.
Оновлення значень: Зміна наявного значення в ключі селектора (наприклад, з v1 на v2) призводить до тієї ж поведінки, що й додавання (сирітство та повторне створення).
Видалення: Видалення наявного ключа з селектора Deployment не вимагає жодних змін у мітках шаблону Podʼа. Це зміна з перетином: новий, ширший селектор відповідатиме старим Podʼам. Наявні ReplicaSets не стають сирітськими, і новий ReplicaSet не створюється, але зверніть увагу, що видалена мітка все ще існує в будь-яких наявних Podʼах та ReplicaSets. Ви можете прибрати її, запустивши розгортання Deployment.
Відкочування Deployment
Іноді вам може знадобитися відкотити Deployment, наприклад, коли Deployment нестабільний, зокрема зациклений на збоях (crash looping). Типово вся історія розгортань Deployment зберігається в системі, щоб ви могли відкотити його в будь-який час (ви можете змінити це, змінивши обмеження історії ревізій).
Примітка:
Ревізія Deployment створюється, коли запускається розгортання Deployment. Це означає, що нова ревізія створюється тільки тоді, коли змінюється шаблон Podʼа Deployment (.spec.template), наприклад, якщо ви оновлюєте мітки або образи контейнера в шаблоні. Інші оновлення, такі як масштабування Deployment, не створюють ревізію Deployment, щоб ви могли одночасно використовувати ручне або автоматичне масштабування. Це означає, що під час відкочування до попередньої ревізії повертається лише частина шаблону Podʼа Deployment.
Припустимо, ви припустилися помилки під час оновлення Deployment, вказавши назву образу як nginx:1.161 замість nginx:1.16.1:
kubectl set image deployment/nginx-deployment nginx=nginx:1.161
Вивід буде подібний до цього:
deployment.apps/nginx-deployment image updated
Розгортання застрягає. Ви можете перевірити це, перевіривши стан розгортання:
kubectl rollout status deployment/nginx-deployment
Вивід буде подібний до цього:
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
Натисніть Ctrl-C, щоб зупинити спостереження за станом розгортання. Докладніше про розгортання, що застрягли, читайте тут.
Ви бачите, що кількість старих реплік (додаючи кількість реплік від nginx-deployment-1564180365 та nginx-deployment-2035384211) — 3, а кількість нових реплік (від nginx-deployment-3066724191) — 1.
kubectl get rs
Вивід буде подібний до цього:
NAME DESIRED CURRENT READY AGE
nginx-deployment-1564180365 3 3 3 25s
nginx-deployment-2035384211 0 0 0 36s
nginx-deployment-3066724191 1 1 0 6s
При перегляді створених Podʼів ви бачите, що 1 Pod, створений новим ReplicaSet, застряг у циклі завантаження образу.
kubectl get pods
Вивід буде подібний до цього:
NAME READY STATUS RESTARTS AGE
nginx-deployment-1564180365-70iae 1/1 Running 0 25s
nginx-deployment-1564180365-jbqqo 1/1 Running 0 25s
nginx-deployment-1564180365-hysrc 1/1 Running 0 25s
nginx-deployment-3066724191-08mng 0/1 ImagePullBackOff 0 6s
Примітка:
Контролер Deployment автоматично зупиняє невдале розгортання та припиняє масштабування нового ReplicaSet. Це залежить від параметрів rollingUpdate (maxUnavailable), які ви вказали. Стандартно Kubernetes встановлює значення 25%.
Отримайте опис Deployment:
kubectl describe deployment
Вивід буде подібний до цього:
Name: nginx-deployment
Namespace: default
CreationTimestamp: Tue, 15 Mar 2016 14:48:04 -0700
Labels: app=nginx
Selector: app=nginx
Replicas: 3 desired | 1 updated | 4 total | 3 available | 1 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.161
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True ReplicaSetUpdated
OldReplicaSets: nginx-deployment-1564180365 (3/3 replicas created)
NewReplicaSet: nginx-deployment-3066724191 (1/1 replicas created)
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 1
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3
13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0
13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 1
Для виправлення цього вам потрібно відкотитися до попередньої ревізії Deployment, яка є стабільною.
Перевірка історії розгортання Deployment
Виконайте наведені нижче кроки, щоб перевірити історію розгортань:
По-перше, перевірте ревізії цього Deployment:
kubectl rollout history deployment/nginx-deployment
CHANGE-CAUSE копіюється з анотації Deployment kubernetes.io/change-cause до його ревізій під час створення. Ви можете вказати повідомлення CHANGE-CAUSE:
Анотуючи Deployment командою kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="image updated to 1.16.1"
Ручним редагуванням маніфесту ресурсу.
Використовуючи інструменти, які автоматично встановлюють анотації.
Примітка:
У старих версіях Kubernetes можна було використовувати прапорець --record з командами kubectl для автоматичного заповнення поля CHANGE-CAUSE. Цей прапорець є застарілим і буде видалений у майбутніх версіях.
Щоб переглянути деталі кожної ревізії, виконайте:
kubectl rollout history deployment/nginx-deployment --revision=2
Для отримання додаткових відомостей про команди, повʼязані з розгортаннями, читайте kubectl rollout.
Deployment тепер повернуто до попередньої стабільної ревізії. Як ви можете бачити, контролер Deployment генерує подію DeploymentRollback щодо відкочування до ревізії 2.
Перевірте, чи відкочування був успішним і Deployment працює як очікується, виконавши:
kubectl get deployment nginx-deployment
Вивід буде подібний до цього:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 30m
Отримайте опис Deployment:
kubectl describe deployment nginx-deployment
Вивід буде подібний до цього:
Name: nginx-deployment
Namespace: default
CreationTimestamp: Sun, 02 Sep 2018 18:17:55 -0500
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision=4
Selector: app=nginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.16.1
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: nginx-deployment-c4747d96c (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 12m deployment-controller Scaled up replica set nginx-deployment-75675f5897 to 3
Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 1
Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 2
Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 2
Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 1
Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 3
Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 0
Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-595696685f to 1
Normal DeploymentRollback 15s deployment-controller Rolled back deployment "nginx-deployment" to revision 2
Normal ScalingReplicaSet 15s deployment-controller Scaled down replica set nginx-deployment-595696685f to 0
Масштабування Deployment
Ви можете масштабувати Deployment за допомогою такої команди:
Припускаючи, що горизонтальне автомасштабування Podʼів увімкнено у вашому кластері, ви можете налаштувати автомасштабувальник для вашого Deployment і вибрати мінімальну та максимальну кількість Podʼів, які ви хочете запускати, на основі використання CPU вашими наявними Podʼами.
Deployments RollingUpdate підтримують виконання кількох версій застосунку одночасно. Коли ви або автомасштабувальник масштабуєте Deployment RollingUpdate, який перебуває посеред розгортання (у процесі або призупиненого), контролер Deployment балансує додаткові репліки в наявних активних ReplicaSets (ReplicaSets з Podʼами), щоб помʼякшити ризик. Це називається пропорційним масштабуванням.
Переконайтеся, що у вашому Deployment працює 10 реплік.
kubectl get deploy
Вивід буде подібний до цього:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 10 10 10 10 50s
Ви оновлюєте образ, який, як виявляється, неможливо знайти в межах кластера.
kubectl set image deployment/nginx-deployment nginx=nginx:sometag
Вивід буде подібний до цього:
deployment.apps/nginx-deployment image updated
Оновлення образу розпочинає нове розгортання з ReplicaSet nginx-deployment-1989198191, але воно блокується через вимогу maxUnavailable, згадану вище. Перевірте стан розгортання:
kubectl get rs
Вивід буде подібний до цього:
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 5 5 0 9s
nginx-deployment-618515232 8 8 8 1m
Потім надходить новий запит на масштабування для Deployment. Автомасштабувальник збільшує репліки Deployment до 15. Контролер Deployment повинен вирішити, куди додати цих нових 5 реплік. Якби ви не використовували пропорційне масштабування, всі 5 реплік були б додані в новий ReplicaSet. З пропорційним масштабуванням ви розподіляєте додаткові репліки між всіма ReplicaSets. Більші частки йдуть в ReplicaSets з найбільшою кількістю реплік, а менші частки йдуть в ReplicaSets з меншою кількістю реплік. Залишки додаються до ReplicaSet з найбільшою кількістю реплік. ReplicaSets з нульовою кількістю реплік не масштабуються.
У нашому прикладі вище 3 репліки додаються до старого ReplicaSet, а 2 репліки — до нового ReplicaSet. Процес розгортання повинен зрештою перемістити всі репліки в новий ReplicaSet, за умови, що нові репліки стають справними. Для підтвердження цього виконайте:
kubectl get deploy
Вивід буде подібний до цього:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 15 18 7 8 7m
Статус розгортання підтверджує, як репліки були додані до кожного ReplicaSet.
kubectl get rs
Вивід буде подібний до цього:
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 7 7 0 7m
nginx-deployment-618515232 11 11 11 7m
Призупинення та відновлення розгортання Deployment
Під час оновлення Deployment або планування оновлення ви можете призупинити розгортання для цього Deployment перед тим, як запустити одне чи кілька оновлень. Коли ви готові застосувати зміни, ви відновлюєте розгортання для Deployment. Цей підхід дозволяє вам застосовувати кілька виправлень між призупиненням та відновленням без зайвих розгортань.
Наприклад, для створеного Deployment:
Отримайте деталі Deployment:
kubectl get deploy
Вивід буде подібний до цього:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx 3 3 3 3 1m
Отримайте стан розгортання:
kubectl get rs
Вивід буде подібний до цього:
NAME DESIRED CURRENT READY AGE
nginx-2142116321 3 3 3 1m
Призупиніть розгортання за допомогою такої команди:
kubectl rollout pause deployment/nginx-deployment
Вивід буде подібний до цього:
deployment.apps/nginx-deployment paused
Потім оновіть образ в Deployment:
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
Вивід буде подібний до цього:
deployment.apps/nginx-deployment image updated
Зверніть увагу, що нове розгортання не розпочалося:
kubectl rollout history deployment/nginx-deployment
Початковий стан Deployment до призупинення його розгортання продовжить працювати, але нові оновлення до Deployment не матимуть жодного впливу, поки розгортання Deployment призупинено.
У кінці відновіть розгортання Deployment і спостерігайте, як новий ReplicaSet зʼявляється з усіма новими оновленнями:
NAME DESIRED CURRENT READY AGE
nginx-2142116321 0 0 0 2m
nginx-3926361531 3 3 3 28s
Примітка:
Ви не можете відкотити призупинене розгортання Deployment, доки ви його не відновите.
Статус Deployment
Deployment переходить через різні стани протягом свого життєвого циклу. Він може бути в процесі, коли виконується розгортання нового ReplicaSet, може бути завершеним або не зможе просуватися.
Deployment в процесі
Kubernetes позначає Deployment як в процесі (progressing), коли виконується одне з таких завдань:
Deployment створює новий ReplicaSet.
Deployment масштабує вгору свій новий ReplicaSet.
Deployment масштабує вниз свої старі ReplicaSets.
Нові Podʼи стають готовими або доступними (готові принаймні MinReadySeconds).
Коли розгортання стає "в процесі" (progressing), контролер Deployment додає стан з такими атрибутами до .status.conditions Deployment:
Ви можете відстежувати хід розгортання за допомогою kubectl rollout status.
Завершений Deployment
Kubernetes позначає Deployment як завершений (complete), коли він має такі характеристики:
Всі репліки, повʼязані з Deployment, були оновлені до останньої версії, яку ви вказали. Це означає, що всі запитані вами оновлення були завершені.
Всі репліки, повʼязані з Deployment, доступні.
Не працюють жодні старі репліки для Deployment.
Коли розгортання стає "завершеним" (complete), контролер Deployment встановлює стан з такими атрибутами в .status.conditions Deployment:
type: Progressing
status: "True"
reason: NewReplicaSetAvailable
Цей стан Progressing буде зберігати значення статусу "True" до тих пір, поки не буде запущено нове розгортання. Стан залишається незмінним навіть тоді, коли змінюється доступність реплік (що натомість впливає на стан Available).
Ви можете перевірити, чи завершено Deployment, використовуючи kubectl rollout status. Якщо розгортання завершилося успішно, kubectl rollout status повертає код виходу нуль (успіх).
kubectl rollout status deployment/nginx-deployment
Вивід буде подібний до цього:
Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx-deployment" successfully rolled out
і код виходу з kubectl rollout дорівнює 0 (успіх):
echo$?
0
Невдалий Deployment
Ваш Deployment може застрягти під час спроби розгорнути свій найновіший ReplicaSet і ніколи не завершитися. Це може статися через такі чинники:
Недостатні квоти
Збій проб readiness
Помилки завантаження образів
Недостатні дозволи
Діапазони обмежень (limit ranges)
Неправильна конфігурація середовища виконання застосунку
Один із способів виявлення цього стану — це вказати параметр крайнього терміну у специфікації вашого Deployment: (.spec.progressDeadlineSeconds). .spec.progressDeadlineSeconds вказує кількість секунд, протягом яких контролер Deployment чекатиме, перш ніж вказати (в статусі Deployment), що прогрес розгортання зупинився.
Ця команда kubectl встановлює специфікацію з progressDeadlineSeconds, щоб змусити контролер повідомляти про відсутність прогресу розгортання для Deployment після 10 хвилин:
Після того як крайній термін закінчився, контролер Deployment додає DeploymentCondition з такими атрибутами до .status.conditions Deployment:
type: Progressing
status: "False"
reason: ProgressDeadlineExceeded
Цей стан також може стати невдалим на ранніх етапах, і тоді він встановлюється в значення статусу "False" з причинами, такими як ReplicaSetCreateError. Крім того, після завершення розгортання крайній термін більше не враховується.
Kubernetes не вживає ніяких заходів щодо Deployment, що застряг, окрім повідомлення про стан у статусі з reason: ProgressDeadlineExceeded. Оркестратори вищого рівня можуть використовувати це і відповідним чином діяти, наприклад, відкотити Deployment до його попередньої версії.
Примітка:
Якщо ви призупините розгортання Deployment, Kubernetes не перевірятиме прогрес відносно вказаного вами крайнього терміну. Ви можете безпечно призупинити розгортання Deployment в середині процесу розгортання та відновити його, не активуючи стан перевищення крайнього терміну.
Ви можете зіткнутися з тимчасовими помилками у Deployment, або через низький таймаут, який ви встановили, або через будь-який інший вид помилок, який можна розглядати як тимчасовий. Наприклад, припустімо, що у вас недостатні квоти. Якщо ви
опишете Deployment, ви помітите такий розділ:
kubectl describe deployment nginx-deployment
Вивід буде подібний до цього:
<...>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True ReplicaSetUpdated
ReplicaFailure True FailedCreate
<...>
Якщо ви виконаєте kubectl get deployment nginx-deployment -o yaml, статус Deployment схожий на це:
Зрештою, коли крайній термін прогресу Deployment буде перевищений, Kubernetes оновить статус і причину стану Progressing:
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing False ProgressDeadlineExceeded
ReplicaFailure True FailedCreate
Ви можете вирішити проблему недостатньої квоти, зменшивши масштаб вашого Deployment, зменшивши масштаб інших контролерів, які ви можете виконувати, або збільшивши квоту у вашому просторі імен. Якщо ви задовольните умови квоти
і контролер Deployment завершить розгортання, ви побачите, що статус Deployment оновлюється успішним станом (status: "True" та reason: NewReplicaSetAvailable).
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
type: Available з status: "True" означає, що у вас є мінімальна доступність Deployment. Мінімальна доступність визначається параметрами, вказаними в стратегії розгортання. type: Progressing з status: "True" означає, що ваш Deployment або перебуває посеред розгортання і прогресує, або він успішно завершив свій прогрес, і доступна мінімально необхідна нова кількість реплік (див. причину стану для конкретики — у нашому випадку reason: NewReplicaSetAvailable означає, що Deployment завершено).
Ви можете перевірити, чи Deployment не зміг просуватися, за допомогою kubectl rollout status. kubectl rollout status повертає код виходу, відмінний від нуля, якщо Deployment перевищив крайній термін виконання.
kubectl rollout status deployment/nginx-deployment
Вивід буде подібний до цього:
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
error: deployment "nginx" exceeded its progress deadline
і код виходу з kubectl rollout дорівнює 1 (позначає помилку):
echo$?
1
Операції з невдалим Deployment
Всі дії, які застосовуються до завершеного Deployment, також застосовуються до невдалого Deployment. Ви можете масштабувати його вгору/вниз, відкотити на попередню ревізію або навіть призупинити, якщо вам потрібно застосувати кілька змін у шаблоні Podʼа Deployment.
Політика очищення
Ви можете встановити поле .spec.revisionHistoryLimit у Deployment, щоб вказати, скільки старих ReplicaSets для цього Deployment ви хочете зберегти. Решту прибере збір сміття у фоновому режимі. Типове значення становить 10.
Примітка:
Якщо явно встановити це поле на 0, буде виконано очищення всієї історії вашого Deployment, і цей Deployment не зможе виконати відкочування.
Очищення починається лише після того, як Deployment досягне завершеного стану. Якщо ви встановите .spec.revisionHistoryLimit у 0, будь-яке розгортання все одно спричинить створення нового ReplicaSet до того, як Kubernetes видалить старий.
Навіть з ненульовим обмеженням історії ревізій ви можете мати більше ReplicaSets, ніж ви налаштували. Наприклад, якщо Podʼи зациклені на збоях і з часом запускається кілька подій поетапного оновлення, ви можете мати більше ReplicaSets, ніж встановлено .spec.revisionHistoryLimit, оскільки Deployment ніколи не досягає завершеного стану.
Канаркові розгортання
Якщо ви хочете впроваджувати релізи для підмножини користувачів чи серверів, використовуючи Deployment, ви можете створити кілька Deployments, по одному для кожного релізу, дотримуючись канаркового шаблону, описаного в розділі керування ресурсами.
Як і з усіма іншими конфігураціями Kubernetes, у Deployment потрібні поля .apiVersion, .kind і .metadata. Для загальної інформації щодо роботи з файлами конфігурацій дивіться документи розгортання застосунків, налаштування контейнерів та використання kubectl для керування ресурсами.
Коли панель управління створює нові Podʼи для Deployment, .metadata.name Deployment є частиною основи для назв цих Podʼів. Назва Deployment повинна бути дійсним значенням DNS-піддомену, але це може призводити до неочікуваних результатів для імен хостів Podʼів. Для найкращої сумісності назва повинна відповідати суворішим правилам DNS-мітки.
.spec.template та .spec.selector — єдині обовʼязкові поля .spec.
.spec.template — це шаблон Podʼа. Він має точно таку саму схему, як і Pod, за винятком того, що він вкладений і не має apiVersion або kind.
Крім обовʼязкових полів для Podʼа, шаблон Podʼа в Deployment повинен вказувати відповідні мітки та відповідну політику перезапуску. Щодо міток, переконайтеся, що вони не перекриваються з іншими контролерами. Дивіться селектор.
.spec.replicas — це необовʼязкове поле, яке вказує кількість бажаних Podʼів. Стандартно встановлено значення 1.
Якщо ви вручну масштабуєте Deployment, наприклад, через kubectl scale deployment deployment --replicas=X, а потім ви оновлюєте цей Deployment на основі маніфесту (наприклад: виконуючи kubectl apply -f deployment.yaml), то застосування цього маніфесту перезаписує ручне масштабування, виконане раніше.
Якщо HorizontalPodAutoscaler (або будь-який аналогічний API для горизонтального масштабування) відповідає за масштабування Deployment, не встановлюйте значення в .spec.replicas.
Замість цього дозвольте панелі управління Kubernetes автоматично керувати полем .spec.replicas.
Селектор
.spec.selector — обовʼязкове поле, яке вказує селектор міток для Podʼів, на які спрямований цей Deployment.
.spec.selector повинен відповідати .spec.template.metadata.labels, інакше його відхилить API.
В API-версії apps/v1.spec.selector та .metadata.labels не набувають стандартно значення .spec.template.metadata.labels, якщо їх не задано. Тому їх слід задавати явно. Також слід зазначити, що .spec.selector неможливо змінити після створення Deployment в apps/v1.
Deployment може примусово завершити Podʼи, мітки яких відповідають селектору, якщо їх шаблон відмінний від .spec.template або якщо загальна кількість таких Podʼів перевищує .spec.replicas. Він запускає нові Podʼи з .spec.template, якщо кількість Podʼів менше, ніж бажана кількість.
Примітка:
Вам не слід створювати інші Podʼи, мітки яких відповідають цьому селектору, або безпосередньо, створюючи інший Deployment, або створюючи інший контролер, такий як ReplicaSet або ReplicationController. Якщо ви це зробите, перший Deployment вважатиме, що він створив ці інші Podʼи. Kubernetes не забороняє вам робити це.
Якщо у вас є кілька контролерів із селекторами, що перетинаються, контролери будуть конфліктувати між собою і не поводитимуться коректно.
Стратегія
.spec.strategy визначає стратегію, якою замінюються старі Podʼи новими. .spec.strategy.type може бути "Recreate" або "RollingUpdate". Типовим значенням є "RollingUpdate".
Перестворення Deployment
Всі поточні Podʼи примусово зупиняються та вилучаються, перш ніж створюються нові, коли .spec.strategy.type==Recreate.
Примітка:
Це гарантує завершення Podʼів перед створенням лише для оновлень. Якщо ви оновлюєте Deployment, всі Podʼи старої ревізії будуть негайно завершені. Успішне видалення очікується перед створенням будь-якого Podʼа нової ревізії. Якщо ви вручну видаляєте Pod, життєвим циклом керує ReplicaSet, і заміну буде створено негайно (навіть якщо старий Pod все ще перебуває в стані Terminating). Якщо вам потрібна гарантія "at most" для ваших Podʼів, вам слід розглянути використання StatefulSet.
Поетапне оновлення Deployment
Deployment оновлює Podʼи в режимі поетапного оновлення (поступово зменшуючи масштаб старих ReplicaSets і збільшуючи масштаб нового), коли .spec.strategy.type==RollingUpdate. Ви можете вказати maxUnavailable та maxSurge, щоб контролювати процес поетапного оновлення.
Максимум недоступних
.spec.strategy.rollingUpdate.maxUnavailable — це необовʼязкове поле, яке вказує максимальну кількість Podʼів, які можуть бути недоступні під час процесу оновлення. Значення може бути абсолютним числом (наприклад, 5) або відсотком від бажаної кількості Podʼів (наприклад, 10%). Абсолютне число обчислюється з відсотків округленням униз. Значення не може бути 0, якщо .spec.strategy.rollingUpdate.maxSurge дорівнює 0. Стандартне значення — 25%.
Наприклад, якщо це значення встановлено на 30%, старий ReplicaSet може бути зменшений до 70% від бажаної кількості Podʼів негайно, коли починається поетапне оновлення. Як тільки нові Podʼи готові, старий ReplicaSet може бути ще більше масштабований вниз, а після цього може бути збільшено масштаб нового ReplicaSet, забезпечуючи, що загальна кількість Podʼів, доступних у будь-який час під час оновлення, становить принаймні 70% від бажаної кількості Podʼів.
Максимальне перевищення
.spec.strategy.rollingUpdate.maxSurge — це необовʼязкове поле, яке вказує максимальну кількість Podʼів, які можуть бути створені понад бажану кількість Podʼів. Значення може бути абсолютним числом (наприклад, 5) або відсотком від бажаної кількості Podʼів (наприклад, 10%). Значення не може бути 0, якщо maxUnavailable дорівнює 0. Абсолютне число обчислюється з відсотків округленням угору. Стандартне значення - 25%.
Наприклад, якщо це значення встановлено на 30%, новий ReplicaSet може бути масштабований негайно, коли починається поетапне оновлення, таким чином, щоб загальна кількість старих і нових Podʼів не перевищувала 130% від бажаної кількості Podʼів. Щойно старі Podʼи буде завершено, новий ReplicaSet може бути масштабований ще більше, забезпечуючи, що загальна кількість Podʼів, які працюють в будь-який час під час оновлення, становить найбільше 130% від бажаної кількості Podʼів.
Ось кілька прикладів поетапного оновлення Deployment за допомогою maxUnavailable та maxSurge:
.spec.progressDeadlineSeconds — це необовʼязкове поле, яке вказує кількість секунд, протягом яких ви хочете чекати на просування вашого Deployment, перш ніж система повідомить, що Deployment не зміг просуватися, — це відображається як стан з type: Progressing, status: "False" та reason: ProgressDeadlineExceeded в статусі ресурсу. Контролер Deployment буде продовжувати повторювати спроби Deployment. Стандартно це значення становить 600.
Якщо вказано це поле, воно повинно бути більше, ніж значення .spec.minReadySeconds.
Min Ready Seconds
.spec.minReadySeconds — це необовʼязкове поле, яке вказує мінімальну кількість секунд, протягом яких новостворений Pod повинен бути готовим без збоїв будь-якого з його контейнерів, щоб вважатися доступним. Стандартно це значення становить 0 (Pod буде вважатися доступним, як тільки він буде готовий). Щоб дізнатися більше про те, коли Pod вважається готовим, див. Проби контейнерів.
Podʼи, що завершують роботу
СТАН ФУНКЦІОНАЛУ:Beta since Kubernetes v1.35; (стандартно увімкнено)
Podʼи, що завершують роботу через видалення або зменшення масштабу, можуть завершуватися тривалий час і впродовж цього періоду споживати додаткові ресурси. Як наслідок, загальна кількість усіх Podʼів може тимчасово перевищити .spec.replicas. Podʼи, що завершують роботу, можна відстежувати за допомогою поля .status.terminatingReplicas в Deployment.
Обмеження історії ревізій
Історія ревізій Deployment зберігається в ReplicaSets, якими він керує.
.spec.revisionHistoryLimit — це необовʼязкове поле, яке вказує кількість старих ReplicaSets, які слід зберігати для можливості відкочування. Ці старі ReplicaSets витрачають ресурси в etcd та захаращують вивід kubectl get rs. Конфігурація кожної ревізії Deployment зберігається в його ReplicaSets; отже, після видалення старого ReplicaSet ви втрачаєте можливість відкотитися до цієї ревізії Deployment. Стандартно буде збережено 10 старих ReplicaSets, але ідеальне значення залежить від частоти та стабільності нових Deployment.
Зокрема, встановлення цього поля рівним нулю означає, що всі старі ReplicaSets з 0 репліками буде очищено. У цьому випадку нове розгортання Deployment не може бути скасовано, оскільки його історія ревізій очищена.
Пауза
.spec.paused — це необовʼязкове булеве поле для призупинення та відновлення Deployment. Єдина відмінність між призупиненим Deployment і тим, який не призупинений, полягає в тому, що будь-які зміни в PodTemplateSpec призупиненого Deployment не викличуть нових розгортань, поки він призупинений. Deployment типово не призупинений під час створення.
Призначення ReplicaSet полягає в забезпеченні стабільного набору реплік Podʼів, які працюють у будь-який момент часу. Зазвичай ви визначаєте Deployment та дозволяєте цьому Deployment автоматично керувати ReplicaSets.
Призначення ReplicaSet полягає в забезпеченні стабільного набору реплік Podʼів, які працюють у будь-який момент часу. Тому ReplicaSet часто використовується для гарантування наявності вказаної кількості ідентичних Podʼів.
Як працює ReplicaSet
ReplicaSet визначається полями, включаючи селектор, який вказує, як ідентифікувати Podʼи, які він може отримати, кількість реплік, що вказує, скільки Podʼів він повинен підтримувати, і шаблон Podʼа, який вказує дані для нових Podʼів, які слід створити для відповідності критеріям кількості реплік. ReplicaSet виконує своє призначення, створюючи та видаляючи Podʼи за необхідності для досягнення їх бажаної кількості. Коли ReplicaSet потребує створення нових Podʼів, він використовує свій шаблон Podʼа.
ReplicaSet повʼязаний зі своїми Podʼами через поле metadata.ownerReferences Podʼа, яке вказує, якому ресурсу належить поточний обʼєкт. Усі Podʼи, які отримав ReplicaSet, мають у полі ownerReferences ідентифікаційну інформацію ReplicaSet, що ними володіє. Завдяки цим посиланням ReplicaSet знає про стан Podʼів, які він підтримує, і планує дії відповідно.
ReplicaSet визначає нові Podʼи для отримання за допомогою свого селектора. Якщо існує Pod, який не має OwnerReference або OwnerReference не є контролером, і він відповідає селектору ReplicaSet, цей ReplicaSet негайно його отримає.
Коли використовувати ReplicaSet
ReplicaSet забезпечує наявність вказаної кількості реплік Podʼів у будь-який момент часу. Проте Deployment є концепцією вищого рівня, яка керує ReplicaSets і надає декларативні оновлення для Podʼів разом із багатьма іншими корисними можливостями. Тому ми рекомендуємо використовувати Deployments замість безпосереднього використання ReplicaSets, хіба що вам потрібне власне оркестрування оновлень або оновлення взагалі не потрібні.
Це означає, що вам, можливо, ніколи не доведеться працювати з обʼєктами ReplicaSet: використовуйте Deployment та визначайте ваш застосунок у розділі spec.
apiVersion:apps/v1kind:ReplicaSetmetadata:name:frontendlabels:app:guestbooktier:frontendspec:# modify replicas according to your casereplicas:3selector:matchLabels:tier:frontendtemplate:metadata:labels:tier:frontendspec:containers:- name:php-redisimage:us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5
Якщо зберегти цей маніфест у файл frontend.yaml та застосувати його до кластера Kubernetes, буде створено визначений ReplicaSet та Podʼи, якими він керує.
Хоча ви можете без проблем створювати окремі Podʼи, наполегливо рекомендується переконатися, що ці окремі Podʼи не мають міток, які відповідають селектору одного з ваших ReplicaSets. Причина цього полягає в тому, що ReplicaSet не обмежується володінням Podʼами, зазначеними в його шаблоні — він може отримати інші Podʼи у спосіб, визначений в попередніх розділах.
Візьмемо приклад попереднього ReplicaSet для фронтенду та Podʼів, визначених у цьому маніфесті:
Оскільки ці Podʼи не мають контролера (або будь-якого обʼєкта) як власника та відповідають селектору ReplicaSet для фронтенду, вони одразу перейдуть у його володіння.
Припустимо, ви створюєте Podʼи після того, як ReplicaSet для фронтенду було розгорнуто і він налаштував свої початкові репліки Podʼів для виконання вимог до кількості реплік:
Ви побачите, що ReplicaSet отримав Podʼи та створив нові лише відповідно до свого опису, доки кількість його нових Podʼів та оригінальних не відповідала його бажаній кількості. Якщо отримати Podʼи:
kubectl get pods
Вивід покаже, що:
NAME READY STATUS RESTARTS AGE
frontend-hmmj2 1/1 Running 0 9s
pod1 1/1 Running 0 36s
pod2 1/1 Running 0 36s
Таким чином, ReplicaSet може володіти неоднорідним набором Podʼів.
Написання маніфесту ReplicaSet
Як і усі інші обʼєкти API Kubernetes, ReplicaSet потребує полів apiVersion, kind та metadata. Для ReplicaSet kind завжди є ReplicaSet.
Коли панель управління створює нові Podʼи для ReplicaSet, .metadata.name ReplicaSet є частиною основи для назв цих Podʼів. Назва ReplicaSet повинна бути дійсним значенням DNS-піддомену, але це може призвести до неочікуваних результатів для імен хостів Podʼів. Для найкращої сумісності назва має відповідати суворішим правилам для DNS-мітки.
.spec.template — це шаблон Podʼа, який також повинен мати встановлені мітки. У нашому прикладі frontend.yaml ми мали одну мітку: tier: frontend. Будьте обережні, щоб селектори не перекривалися з селекторами інших контролерів, інакше вони можуть спробувати перейняти цей Pod.
Для поля політики перезапуску шаблону, .spec.template.spec.restartPolicy, допустимим є тільки значення Always, яке є стандартним.
Селектор Podʼа
Поле .spec.selector є селектором міток. Як обговорювалося раніше, це мітки, які використовуються для ідентифікації потенційних Podʼів для володіння. У нашому прикладі frontend.yaml селектор був:
matchLabels:tier:frontend
У ReplicaSet .spec.template.metadata.labels має відповідати spec.selector, інакше він буде відхилений API.
Примітка:
Для 2 ReplicaSets, які вказують однаковий .spec.selector, але різні поля .spec.template.metadata.labels та .spec.template.spec, кожен ReplicaSet ігнорує Podʼи, створені іншим ReplicaSet.
Репліки
Ви можете вказати, скільки Podʼів мають виконуватись одночасно, встановивши значення .spec.replicas. ReplicaSet буде створювати/видаляти свої Podʼи, щоб кількість Podʼів відповідала цьому числу.
Якщо ви не вказали .spec.replicas, то типово значення дорівнює 1.
Робота з ReplicaSets
Видалення ReplicaSet та його Podʼів
Щоб видалити ReplicaSet і всі його Podʼи, використовуйте kubectl delete. Збирач сміття стандартно автоматично видаляє всі залежні Podʼи.
Під час використання REST API або бібліотеки client-go вам потрібно встановити propagationPolicy в Background або Foreground в опції -d. Наприклад:
Ви можете видалити ReplicaSet, не впливаючи на його Podʼи, за допомогою kubectl delete з опцією --cascade=orphan. Під час використання REST API або бібліотеки client-go вам потрібно встановити propagationPolicy в Orphan. Наприклад:
Після видалення оригіналу ви можете створити новий ReplicaSet для заміни. Поки старий та новий .spec.selector однакові, новий перейме старі Podʼи. Однак він не намагатиметься привести наявні Podʼи у відповідність до нового, іншого шаблону Podʼа. Для оновлення Podʼів до нової специфікації у контрольований спосіб використовуйте Deployment, оскільки ReplicaSets безпосередньо не підтримують поетапне оновлення.
Podʼи, що завершують роботу
СТАН ФУНКЦІОНАЛУ:Beta since Kubernetes v1.35; (стандартно увімкнено)
Podʼи, що завершують роботу через видалення або зменшення масштабу, можуть завершуватися тривалий час і впродовж цього періоду споживати додаткові ресурси. Як наслідок, загальна кількість усіх Podʼів може тимчасово перевищити .spec.replicas. Podʼи, що завершують роботу, можна відстежувати за допомогою поля .status.terminatingReplicas в ReplicaSet.
Ізолювання Podʼів від ReplicaSet
Ви можете видалити Podʼи з ReplicaSet, змінивши їх мітки. Цей метод може бути використаний для вилучення Podʼів з обслуговування з метою налагодження, відновлення даних тощо. Podʼи, які вилучаються цим способом, будуть автоматично замінені (за умови, що кількість реплік також не змінюється).
Масштабування ReplicaSet
ReplicaSet можна легко масштабувати вгору або вниз, просто оновивши поле .spec.replicas. Контролер ReplicaSet гарантує, що бажана кількість Podʼів з відповідним селектором міток доступна та працює.
Під час зменшення масштабу контролер ReplicaSet вибирає Podʼи для видалення, сортуючи доступні Podʼи, щоб визначити, які Podʼи видаляти в першу чергу, за таким загальним алгоритмом:
Перш за все прибираються Podʼи, що перебувають в очікуванні (і непридатні для планування).
Якщо встановлено анотацію controller.kubernetes.io/pod-deletion-cost, то Pod із меншим значенням буде видалено першим.
Podʼи на вузлах з більшою кількістю реплік йдуть перед Podʼами на вузлах з меншою кількістю реплік.
Якщо часи створення Podʼів відрізняються, то Pod, створений пізніше, йде перед старішим Podʼом (часи створення групуються за цілочисельною логарифмічною шкалою).
Якщо все вище вказане збігається, вибір випадковий.
Вартість видалення Podʼа
СТАН ФУНКЦІОНАЛУ:Beta since Kubernetes v1.22
За допомогою анотації controller.kubernetes.io/pod-deletion-cost користувачі можуть встановити уподобання щодо порядку видалення Podʼів під час зменшення масштабу ReplicaSet.
Анотація повинна бути встановлена на Podʼі, діапазон — [-2147483648, 2147483647]. Вона представляє вартість видалення Podʼа порівняно з іншими Podʼами, які належать тому ж ReplicaSet. Podʼи з меншою вартістю видалення видаляються раніше за Podʼи з більшою вартістю видалення.
Неявне значення для цієї анотації для Podʼів, які його не мають, — 0; допустимі відʼємні значення. Неприпустимі значення будуть відхилені API-сервером.
Ця функція перебуває на стадії бета та типово увімкнена. Ви можете вимкнути її, використовуючи функціональну можливістьPodDeletionCost як в kube-apiserver, так і в kube-controller-manager.
Примітка:
Це враховується за принципом best-effort, тому порядок видалення Podʼів не гарантується.
Користувачам слід уникати частого оновлення анотації, такого як оновлення її на основі значення метрики, оскільки це призведе до значного числа оновлень Podʼів на apiserver.
Приклад використання
Різні Podʼи застосунку можуть мати різний рівень використання. Під час зменшення масштабу застосунок може віддавати перевагу видаленню Podʼів з меншим використанням. Щоб уникнути частого оновлення Podʼів, застосунок повинен оновити controller.kubernetes.io/pod-deletion-cost один раз перед зменшенням масштабу (встановлення анотації в значення, пропорційне рівню використання Podʼа). Це працює, якщо сам застосунок контролює масштабування вниз; наприклад, Pod-драйвер розгортання Spark.
ReplicaSet як ціль горизонтального автомасштабування Podʼа
ReplicaSet також може бути ціллю для горизонтального автомасштабування Podʼа (HPA). Іншими словами, ReplicaSet може автоматично масштабуватися за допомогою HPA. Ось приклад HPA, який застосовується до ReplicaSet, створеного в попередньому прикладі.
Збереження цього маніфесту в hpa-rs.yaml та його застосування до кластера Kubernetes повинно створити визначене HPA, яке автоматично змінює масштаб цільового ReplicaSet залежно від використання CPU реплікованими Podʼами.
Deployment — це обʼєкт, який може володіти ReplicaSets і оновлювати їх та їхні Podʼи через декларативні поетапні оновлення на стороні сервера. Хоча ReplicaSets можуть використовуватися незалежно, на сьогодні вони головним чином використовуються Deployments як механізм для оркестрування створення, видалення та оновлення Podʼів. Коли ви використовуєте Deployments, вам не потрібно турбуватися про керування ReplicaSets, які вони створюють. Deployments володіють і керують своїми ReplicaSets. Таким чином, рекомендується використовувати Deployments, коли вам потрібні ReplicaSets.
Окремі Podʼи
На відміну від випадку, коли користувач безпосередньо створює Podʼи, ReplicaSet замінює Podʼи, які видаляються або завершуються з будь-якої причини, такої як відмова вузла чи обслуговування вузла з порушенням роботи, наприклад, оновлення ядра. З цієї причини ми рекомендуємо використовувати ReplicaSet, навіть якщо ваш застосунок вимагає лише одного Podʼа. Подібно до наглядача процесів, він наглядає за кількома Podʼами на різних вузлах замість окремих процесів на одному вузлі. ReplicaSet делегує перезапуск локальних контейнерів до агента на вузлі, такого як Kubelet.
Job
Використовуйте Job замість ReplicaSet для Podʼів, які повинні завершитися самостійно (тобто пакетні завдання).
DaemonSet
Використовуйте DaemonSet замість ReplicaSet для Podʼів, які надають функції на рівні машини, такі як моніторинг машини або логування машини. Ці Podʼи мають термін служби, який повʼязаний з терміном служби машини: Pod повинен працювати на машині перед тим, як інші Podʼи почнуть роботу, і їх можна безпечно завершити, коли машина готова до перезавантаження/вимкнення.
ReplicationController
ReplicaSets є наступниками ReplicationControllers. Обидва мають те саме призначення та поводяться схоже, за винятком того, що ReplicationController не підтримує вимоги селектора на основі множини, як описано в посібнику про мітки. Тому ReplicaSets мають перевагу над ReplicationControllers.
ReplicaSet — це ресурс верхнього рівня у REST API Kubernetes. Прочитайте визначення обʼєкта
ReplicaSet, щоб зрозуміти API для ReplicaSets.
Дізнайтеся про PodDisruptionBudget та як ви можете використовувати його для керування доступністю застосунку під час порушень.
3 - StatefulSets
StatefulSet запускає групу Podʼів і зберігає стійку ідентичність для кожного з цих Podʼів. Це корисно для керування застосунками, які потребують постійного сховища або стабільної, унікальної мережевої ідентичності.
StatefulSet — це обʼєкт API робочого навантаження, який використовується для керування застосунками зі збереженням стану.
StatefulSet керує розгортанням і масштабуванням групи Podʼів, і забезпечує гарантії щодо порядку та унікальності цих Podʼів.
Як і Deployment, StatefulSet керує Podʼами, які базуються на ідентичній специфікації контейнерів. На відміну від Deployment, StatefulSet зберігає постійну ідентичність для кожного свого Podʼа. Ці Podʼи створюються за однаковою специфікацією, але не є взаємозамінними: у кожного є постійний ідентифікатор, який він зберігає під час будь-якого перепланування.
Якщо ви хочете використовувати томи для забезпечення постійності вашого робочого навантаження, ви можете використовувати StatefulSet як частину рішення. Хоча окремі Podʼи в StatefulSet можуть вийти з ладу, постійні ідентифікатори Podʼів полегшують зіставлення наявних томів із новими Podʼами, які замінюють ті, що вийшли з ладу.
Використання StatefulSets
StatefulSets є цінним інструментом для застосунків, які потребують одного або кількох із таких елементів:
Стабільних, унікальних мережевих ідентифікаторів.
Стабільного, постійного сховища.
Упорядкованого, плавного розгортання та масштабування.
Тут «стабільний» означає збереження під час (пере)планування Podʼів. Якщо застосунок не потребує стабільних ідентифікаторів або упорядкованого розгортання, видалення чи масштабування, вам слід розгортати його за допомогою обʼєкта робочого навантаження, який забезпечує набір реплік без збереження стану (stateless). Deployment або ReplicaSet можуть краще підійти для ваших stateless-потреб.
Обмеження
Сховище для певного Podʼа має бути виділене PersistentVolume Provisioner на основі запитаного storage class або попередньо виділене адміністратором.
Видалення та/або масштабування StatefulSet вниз не призведе до видалення томів, повʼязаних з StatefulSet. Це зроблено для забезпечення безпеки даних, яка загалом є важливішою, ніж автоматичне очищення всіх повʼязаних ресурсів StatefulSet.
Наразі для StatefulSets обовʼязково потрібний Headless Service, щоб відповідати за мережеву ідентичність Podʼів. Ви відповідаєте за створення цього Service.
StatefulSets не надають жодних гарантій щодо завершення роботи Podʼів під час видалення StatefulSet. Для досягнення упорядкованого та плавного завершення роботи Podʼів у StatefulSet можна зменшити масштаб StatefulSet до 0 перед видаленням.
apiVersion:v1kind:Servicemetadata:name:nginxlabels:app:nginxspec:ports:- port:80name:webclusterIP:Noneselector:app:nginx---apiVersion:apps/v1kind:StatefulSetmetadata:name:webspec:selector:matchLabels:app:nginx# has to match .spec.template.metadata.labelsserviceName:"nginx"replicas:3# by default is 1minReadySeconds:10# by default is 0template:metadata:labels:app:nginx# has to match .spec.selector.matchLabelsspec:terminationGracePeriodSeconds:10containers:- name:nginximage:registry.k8s.io/nginx-slim:0.24ports:- containerPort:80name:webvolumeMounts:- name:wwwmountPath:/usr/share/nginx/htmlvolumeClaimTemplates:- metadata:name:wwwspec:accessModes:["ReadWriteOnce"]storageClassName:"my-storage-class"resources:requests:storage:1Gi
Примітка:
Цей приклад використовує режим доступу ReadWriteOnce для простоти. Для промислового використання проєкт Kubernetes рекомендує натомість використовувати режим доступу ReadWriteOncePod.
У вищенаведеному прикладі:
Headless Service із назвою nginx використовується для керування мережевим доменом.
StatefulSet із назвою web має Spec, який вказує на те, що буде запущено 3 репліки контейнера nginx в унікальних Podʼах.
volumeClaimTemplates забезпечуватиме стабільне сховище за допомогою PersistentVolumes, виділених PersistentVolume Provisioner.
Назва обʼєкта StatefulSet повинна бути дійсною DNS-міткою.
Селектор Podʼів
Ви повинні встановити поле .spec.selector StatefulSet так, щоб воно збігалося з мітками його .spec.template.metadata.labels. Якщо не вказати відповідний селектор Podʼів, під час створення StatefulSet виникне помилка валідації.
Шаблони заявок на томи
Ви можете встановити поле .spec.volumeClaimTemplates, щоб створити PersistentVolumeClaim. Це забезпечить стабільне сховище для StatefulSet, якщо:
StorageClass, вказаний для заявки на том, налаштовано на використання динамічного виділення.
Кластер вже містить PersistentVolume з правильним StorageClass та достатньою кількістю доступного місця для зберігання.
Мінімальний час готовності
СТАН ФУНКЦІОНАЛУ:GA since Kubernetes v1.25
.spec.minReadySeconds є необовʼязковим полем, яке вказує мінімальну кількість секунд, протягом яких новостворений Pod повинен працювати та бути готовим без збоїв будь-якого з його контейнерів, щоб вважатися доступним. Це використовується для перевірки прогресу розгортання під час використання стратегії поетапного оновлення. Це поле стандартно дорівнює 0 (Pod вважатиметься доступним одразу після готовності). Докладніше про те, коли Pod вважається готовим, див. Проби контейнера.
Ідентичність Podʼа
Podʼи StatefulSet мають унікальну ідентичність, яка складається з порядкового номера, стабільного мережевого ідентифікатора та стабільного сховища. Ця ідентичність залишається прикріпленою до Podʼа незалежно від того, на який вузол його (пере)заплановано.
Порядковий індекс
Для StatefulSet з N реплік кожному Podʼу в StatefulSet буде призначено цілочисельний порядковий номер, унікальний у наборі. Стандартно Podʼам буде призначено порядкові номери від 0 до N-1. Контролер StatefulSet також додасть мітку Podʼа з цим індексом: apps.kubernetes.io/pod-index.
Початковий порядковий номер
СТАН ФУНКЦІОНАЛУ:GA since Kubernetes v1.31; (стандартно увімкнено)
More information about this feature
This is a stable feature in Kubernetes, and has been since version 1.31. It was first available in the v1.26 release.
.spec.ordinals — це необовʼязкове поле, яке дозволяє налаштувати цілочисельні порядкові номери, призначені кожному Podʼу. Стандартно воно встановлено в nil. У межах цього поля ви можете налаштувати такі параметри:
.spec.ordinals.start: Якщо встановлено поле .spec.ordinals.start, Podʼам будуть призначені порядкові номери від .spec.ordinals.start до .spec.ordinals.start + .spec.replicas - 1.
Стабільний мережевий ідентифікатор
Кожен Pod у StatefulSet отримує імʼя хоста з назви StatefulSet та порядкового номера Podʼа. Шаблон для створеного імені хоста має вигляд $(назва statefulset)-$(порядковий номер). У наведеному вище прикладі буде створено три Podʼи з назвами web-0,web-1,web-2. StatefulSet може використовувати Headless Service для керування доменом своїх Podʼів. Домен, яким керує цей Service, має вигляд: $(назва сервісу).$(простір імен).svc.cluster.local, де "cluster.local" — це домен кластера. Під час створення кожен Pod отримує відповідний DNS-піддомен, який має вигляд: $(назва Podʼа).$(домен керівного сервісу), де керівний сервіс визначається полем serviceName у StatefulSet.
Залежно від того, як налаштований DNS у вашому кластері, ви, можливо, не зможете одразу знайти DNS-імʼя нового Podʼа. Це можливо, коли інші клієнти в кластері вже відправили запити на імʼя хоста Podʼа до його створення. Негативне кешування (звичайне для DNS) означає, що результати попередніх невдалих пошуків запамʼятовуються та використовуються повторно навіть після того, як Pod вже працює, принаймні кілька секунд.
Якщо вам потрібно виявити Podʼи негайно після їх створення, у вас є кілька варіантів:
Запитуйте API Kubernetes безпосередньо (наприклад, використовуючи watch), а не покладаючись на DNS-запити.
Зменште час кешування у вашому постачальнику DNS Kubernetes (зазвичай це означає редагування ConfigMap для CoreDNS, який зараз кешує протягом 30 секунд).
Як зазначено в розділі Обмеження, ви відповідаєте за створення Headless Service, відповідального за мережеву ідентичність Podʼів.
Ось деякі приклади варіантів вибору домену кластера, назви Service, назви StatefulSet та того, як це впливає на DNS-імена Podʼів StatefulSet.
Домен кластера
Service (ns/назва)
StatefulSet (ns/назва)
Домен StatefulSet
DNS Podʼа
Імʼя хоста Podʼа
cluster.local
default/nginx
default/web
nginx.default.svc.cluster.local
web-{0..N-1}.nginx.default.svc.cluster.local
web-{0..N-1}
cluster.local
foo/nginx
foo/web
nginx.foo.svc.cluster.local
web-{0..N-1}.nginx.foo.svc.cluster.local
web-{0..N-1}
kube.local
foo/nginx
foo/web
nginx.foo.svc.kube.local
web-{0..N-1}.nginx.foo.svc.kube.local
web-{0..N-1}
Примітка:
Домен кластера буде встановлено як cluster.local, якщо не буде інших налаштувань.
Стабільне сховище
Для кожного запису VolumeClaimTemplate, визначеного в StatefulSet, кожен Pod отримує один PersistentVolumeClaim. У прикладі з nginx кожен Pod отримує один PersistentVolume з StorageClass my-storage-class та 1 GiB виділеного сховища. Якщо StorageClass не вказано, використовуватиметься стандартний StorageClass. Коли Pod (пере)планується на вузол, його volumeMounts монтує PersistentVolumes, повʼязані із його PersistentVolume Claims. Зауважте, що PersistentVolumes, повʼязані із PersistentVolume Claims Podʼів, не видаляються під час видалення Podʼів чи StatefulSet. Це слід робити вручну.
Мітка назви Podʼа
Коли контролер StatefulSet створює Pod, він додає мітку statefulset.kubernetes.io/pod-name, яка дорівнює назві Podʼа. Ця мітка дозволяє прикріплювати Service до конкретного Podʼа в StatefulSet.
Мітка індексу Podʼа
СТАН ФУНКЦІОНАЛУ:GA since Kubernetes v1.32; (стандартно увімкнено)
More information about this feature
This is a stable feature in Kubernetes, and has been since version 1.32. It was first available in the v1.28 release.
Коли контролер StatefulSet створює Pod, новий Pod отримує мітку apps.kubernetes.io/pod-index. Значення цієї мітки — це порядковий індекс Podʼа. Ця мітка дозволяє спрямовувати трафік до певного індексу Podʼа, фільтрувати логи/метрики за допомогою мітки індексу Podʼа тощо. Зверніть увагу, що функціональна можливість PodIndexLabel для цієї функції стандартно увімкнена та заблокована; щоб вимкнути її, користувачам доведеться використовувати емуляцію сервера версії v1.31.
Гарантії розгортання та масштабування
Для StatefulSet із N реплік під час розгортання Podʼи створюються послідовно, у порядку від {0..N-1}.
Під час видалення Podʼів вони завершуються у зворотному порядку, від {N-1..0}.
Перед тим як застосувати масштабування до Podʼа, всі його попередники повинні бути в стані Running та Ready. Якщо встановлено .spec.minReadySeconds, попередники повинні бути доступними (готовими принаймні протягом minReadySeconds).
Перед тим як Pod буде завершено, всі його наступники повинні бути повністю зупинені.
StatefulSet не повинен вказувати pod.Spec.TerminationGracePeriodSeconds рівним 0. Така практика небезпечна і настійно не рекомендується. Докладніше дивіться в розділі примусове видалення Podʼів StatefulSet.
Коли створюється наведений вище приклад nginx, три Podʼи будуть розгорнуті в порядку web-0, web-1, web-2. web-1 не буде розгорнуто, поки web-0 не буде в стані Running та Ready, і web-2 не буде розгорнуто, поки web-1 не буде в стані Running та Ready. Якщо web-0 зазнає збою після того, як web-1 перейде в стан Running та Ready, але до запуску web-2, web-2 не буде запущено, поки web-0 не буде успішно перезапущено і він не перейде в стан Running та Ready.
Якщо користувач масштабує розгорнутий приклад, застосовуючи патч до StatefulSet так, щоб replicas=1, спочатку буде завершено web-2. web-1 не буде завершено, поки web-2 повністю не зупиниться і не буде видалений. Якщо web-0 зазнає збою після того, як web-2 вже завершено і повністю зупинено, але перед завершенням web-1, web-1 не буде завершено, поки web-0 не перейде в стан Running та Ready.
Політики керування Podʼами
StatefulSet дозволяє послабити його гарантії послідовності, зберігаючи при цьому його гарантії унікальності та ідентичності за допомогою поля .spec.podManagementPolicy.
Політика керування Podʼами "OrderedReady"
OrderedReady є типовим значенням політики керування Podʼами для StatefulSet. Вона реалізує поведінку, описану в розділі Гарантії розгортання та масштабування.
Політика керування Podʼами "Parallel"
Parallel вказує контролеру StatefulSet запускати або завершувати всі Podʼи паралельно і не чекати, поки Podʼи перейдуть у стан Running та Ready або повністю завершаться, перед запуском або завершенням іншого Podʼа.
Для операцій масштабування це означає, що всі Podʼи створюються або завершуються одночасно.
Для поетапних оновлень, коли .spec.updateStrategy.rollingUpdate.maxUnavailable більше 1, контролер StatefulSet завершує і створює до maxUnavailable Podʼів одночасно (також відоме як «bursting»). Це може прискорити оновлення, але може призвести до того, що Podʼи стануть готовими в неправильному порядку, що може бути неприйнятним для застосунків, які вимагають суворого порядку.
Стратегії оновлення
Поле .spec.updateStrategy обʼєкта StatefulSet дозволяє налаштовувати та вимикати автоматизовані поетапні оновлення для контейнерів, міток, ресурсів (запити/обмеження) та анотацій для Podʼів у StatefulSet. Є три можливих значення:
OnDelete
Коли поле .spec.updateStrategy.type StatefulSet встановлено в OnDelete, контролер StatefulSet не буде автоматично оновлювати Podʼи в StatefulSet. Користувачам необхідно вручну видаляти Podʼи, щоб спричинити створення контролером нових Podʼів, які відображають зміни, внесені в .spec.template StatefulSet.
RollingUpdate
Стратегія оновлення RollingUpdate реалізує автоматизовані поетапні оновлення для Podʼів у StatefulSet. Це значення є стандартною стратегією оновлення.
Recreate
СТАН ФУНКЦІОНАЛУ:Alpha since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature
To use this feature, you (or a cluster administrator) will need to enable the StatefulSetRecreateStrategy feature gate for all relevant components in your cluster.
Стратегія оновлення Recreate видаляє всі Podʼи StatefulSet перед створенням нових Podʼів, які відображають зміни, внесені в .spec.template StatefulSet. Використання цієї стратегії вимагає увімкнення функціональної можливості StatefulSetRecreateStrategy. Див. Recreate для деталей.
Поетапні оновлення
Коли поле .spec.updateStrategy.type StatefulSet встановлено на RollingUpdate, контролер StatefulSet буде видаляти та знову створювати кожен Pod у StatefulSet. Він буде продовжувати в тому ж порядку, як Podʼи завершують роботу (від найбільшого індексу до найменшого), оновлюючи кожен Pod по одному.
Панель управління Kubernetes чекає, доки оновлений Pod буде переведений в стан Running та Ready, перш ніж оновити його попередника. Якщо ви встановили .spec.minReadySeconds (див. Мінімальний час готовності), панель управління також чекає вказану кількість секунд після того, як Pod стане готовим, перш ніж перейти далі.
Поетапні оновлення частинами
Стратегію оновлення RollingUpdate можна поділити на частини, вказавши .spec.updateStrategy.rollingUpdate.partition. Якщо вказано розділ, всі Podʼи з індексом, який більший або рівний розділу, будуть оновлені при оновленні .spec.template StatefulSet. Усі Podʼи з індексом, який менший за розділ, не будуть оновлені та, навіть якщо вони будуть видалені, вони будуть створені заново з попередньою версією. Якщо .spec.updateStrategy.rollingUpdate.partition StatefulSet більше, ніж .spec.replicas, оновлення .spec.template не буде розповсюджуватися на його Podʼи. У більшості випадків вам не знадобиться використовувати розділ, але він корисний, якщо ви хочете підготувати оновлення, розгорнути канарку або виконати розгортання за фазами.
Максимальна кількість недоступних Podʼів
СТАН ФУНКЦІОНАЛУ:Beta since Kubernetes v1.35
Ви можете контролювати максимальну кількість Podʼів, які можуть бути недоступні під час оновлення, вказавши поле .spec.updateStrategy.rollingUpdate.maxUnavailable. Значення може бути абсолютним числом (наприклад, 5) або відсотком від бажаних Podʼів (наприклад, 10%). Абсолютне число обчислюється з відсоткового значення заокругленням вгору. Це поле не може бути 0. Стандартне значення — 1.
Це поле застосовується до всіх Podʼів у діапазоні від 0 до replicas - 1. Якщо є будь-який недоступний Pod у діапазоні від 0 до replicas - 1, він буде враховуватися в maxUnavailable.
Примітка:
Поле maxUnavailable перебуває на стадії бета і є стандартно увімкненим.
Примусове відкочування
Під час використання поетапних оновлень зі стандартною політикою керування Podʼами (OrderedReady) можна потрапити в несправний стан, який вимагає ручного втручання для виправлення.
Якщо ви оновлюєте шаблон Podʼа до конфігурації, яка ніколи не досягає стану Running та Ready (наприклад, через поганий бінарний файл або помилку конфігурації на рівні застосунку), StatefulSet припинить розгортання і залишиться у стані очікування.
У цьому стані недостатньо повернути шаблон Podʼа до справної конфігурації. Через відомий дефект, StatefulSet продовжуватиме очікувати, доки неробочий Pod стане готовим (що ніколи не відбувається), перед тим як спробувати повернути його до робочої конфігурації.
Після повернення до шаблону вам також слід видалити будь-які Podʼи, які StatefulSet вже намагався запустити з поганою конфігурацією. Після цього StatefulSet почне перестворювати Podʼи, використовуючи відновлений шаблон.
Recreate
СТАН ФУНКЦІОНАЛУ:Alpha since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature
To use this feature, you (or a cluster administrator) will need to enable the StatefulSetRecreateStrategy feature gate for all relevant components in your cluster.
Коли поле .spec.updateStrategy.type StatefulSet встановлено на Recreate, контролер StatefulSet видаляє всі Podʼи StatefulSet одночасно та чекає, доки вони повністю завершать роботу, перш ніж створювати будь-які нові Podʼи з оновленого .spec.template. На відміну від RollingUpdate, стара та нова ревізії Podʼа ніколи не працюють одночасно, тому ця стратегія призводить до простою протягом усього оновлення. Це дзеркально відображає стратегію Recreate для Deployment і є корисною для застосунків, які не можуть запускати дві версії одночасно, наприклад, для робочих навантажень, які потребують ексклюзивного доступу до спільного ресурсу або використовують формат на диску, несумісний між версіями.
Видалення завжди прибирає всі Podʼи разом, незалежно від політики керування Podʼами. Після того, як всі Podʼи завершать роботу, нові Podʼи створюються відповідно до цієї політики: з OrderedReady (стандартно) Podʼи перестворюються по одному, у порядку зростання індексів, чекаючи, доки кожен стане Running та Ready, перш ніж створювати наступний; з Parallel всі Podʼи перестворюються одночасно.
Оскільки це альфа-функція, ви повинні увімкнути функціональну можливість StatefulSetRecreateStrategy на kube-controller-manager та kube-apiserver, щоб використовувати цю стратегію.
Історія ревізій
ControllerRevision — це ресурс API Kubernetes, який використовується контролерами, такими як контролер StatefulSet, для відстеження історичних змін конфігурації.
StatefulSets використовують ControllerRevisions для ведення історії ревізій, що дозволяє виконувати відкочування і відстежувати версії.
Як StatefulSets відстежують зміни за допомогою ControllerRevisions
Коли ви оновлюєте шаблон Podʼа StatefulSet (spec.template), контролер StatefulSet:
Готує новий обʼєкт ControllerRevision
Зберігає знімок шаблону Podʼа і метаданих
Присвоює інкрементний номер ревізії
Ключові властивості
Дивіться ControllerRevision, щоб дізнатися більше про ключові властивості та інші деталі.
Керування історією ревізій
Керуйте збереженими ревізіями за допомогою .spec.revisionHistoryLimit:
apiVersion:apps/v1kind:StatefulSetmetadata:name:webappspec:revisionHistoryLimit:5# Зберігати останні 5 ревізій# ... інші поля spec ...
Стандартно: 10 ревізій зберігаються, якщо не вказано інше
Очищення: найстаріші ревізії прибирає збір сміття, коли перевищено обмеження
Виконання відкочування
Ви можете повернутися до попередньої конфігурації за допомогою:
# Переглянути історію ревізійkubectl rollout history statefulset/webapp
# Відкотитися до певної ревізіїkubectl rollout undo statefulset/webapp --to-revision=3
Це:
Застосує шаблон Podʼа з ревізії 3
Створить новий ControllerRevision з оновленим номером ревізії
Перевірка ControllerRevisions
Щоб переглянути повʼязані ControllerRevisions:
# Перелічити всі ревізії для StatefulSetkubectl get controllerrevisions -l app.kubernetes.io/name=webapp
# Переглянути детальну конфігурацію конкретної ревізіїkubectl get controllerrevision/webapp-3 -o yaml
Найкращі практики
Політика зберігання
Встановіть revisionHistoryLimit в діапазоні 5–10 для більшості робочих навантажень.
Збільшуйте значення тільки в разі потреби в глибокій історії відкочування.
Моніторинг
Регулярно перевіряйте ревізії за допомогою:
kubectl get controllerrevisions
Налаштуйте сповіщення про швидке зростання кількості ревізій.
Уникайте
Ручного редагування обʼєктів ControllerRevision.
Використання ревізій як механізму резервного копіювання (використовуйте справжні інструменти резервного копіювання).
Встановлення revisionHistoryLimit: 0 (вимикає можливість відкочування).
Збереження PersistentVolumeClaim
СТАН ФУНКЦІОНАЛУ:GA since Kubernetes v1.32; (стандартно увімкнено)
More information about this feature
This is a stable feature in Kubernetes, and has been since version 1.32. It was first available in the v1.23 release.
Необовʼязкове поле .spec.persistentVolumeClaimRetentionPolicy контролює, чи і як видаляються PVC під час життєвого циклу StatefulSet. Вам потрібно увімкнути функціональну можливістьStatefulSetAutoDeletePVC на API-сервері та controller manager, щоб використовувати це поле. Після увімкнення ви можете налаштувати дві політики для кожного StatefulSet:
whenDeleted
Налаштовує поведінку збереження томів, яка застосовується під час видалення StatefulSet.
whenScaled
Налаштовує поведінку збереження томів, яка застосовується під час зменшення кількості реплік у StatefulSet, наприклад, під час зменшення масштабу набору.
Для кожної політики, яку ви можете налаштувати, ви можете встановити значення Delete або Retain.
Delete
PVC, створені за допомогою volumeClaimTemplate StatefulSet, видаляються для кожного Podʼа, на який впливає політика. З політикою whenDeleted всі PVC від volumeClaimTemplate видаляються після того, як їхні Podʼи були видалені. З політикою whenScaled видаляються лише PVC, що відповідають реплікам Podʼа, які прибираються під час зменшення масштабу, після того, як їхні Podʼи були видалені.
Retain (стандартно)
PVC від volumeClaimTemplate не змінюються, коли їх Pod видаляється. Це поведінка до цієї нової функції.
Майте на увазі, що ці політики застосовуються лише тоді, коли Podʼи прибираються через видалення StatefulSet або зменшення його масштабу. Наприклад, якщо Pod, повʼязаний із StatefulSet, зазнає збою через відмову вузла, і панель управління створює Pod-замінник, StatefulSet зберігає наявний PVC. Наявний том не зазнає впливу, і кластер приєднає його до вузла, де має запуститися новий Pod.
Стандартно для політик встановлено Retain, відповідно до поведінки StatefulSet до цієї нової функції.
Контролер StatefulSet додає посилання на власника до своїх PVC, які потім видаляються збирачем сміття після завершення Podʼа. Це дозволяє Podʼу чисто демонтувати всі томи перед видаленням PVC (і перед видаленням PV і тому, що лежать в їх основі, залежно від політики збереження). Коли ви встановлюєте політику whenDeleted у Delete, посилання на власника на екземпляр StatefulSet додається до всіх PVC, повʼязані із цим StatefulSet.
Політика whenScaled повинна видаляти PVC тільки під час зменшення масштабу Podʼа, а не під час видалення Podʼа з іншої причини. Під час узгодження контролер StatefulSet порівнює очікувану кількість реплік із фактичними Podʼами, що присутні на кластері. Будь-який Pod StatefulSet, ідентифікатор якого більший за кількість реплік, засуджується та позначається для видалення. Якщо політика whenScaled є Delete, засуджені Podʼи спочатку встановлюються власниками відповідних PVC шаблону StatefulSet, перед видаленням Podʼа. Це призводить до того, що PVC видаляються збирачем сміття лише після завершення засуджених Podʼів.
Це означає, що якщо контролер виходить з ладу і перезапускається, жоден Pod не буде видалено до того моменту, поки його посилання на власника не буде відповідно оновлено згідно з політикою. Якщо засуджений Pod видаляється примусово, коли контролер вимкнено, посилання на власника може бути або встановлене, або ні, залежно від того, коли відбулася аварія контролера. Для оновлення посилань на власника може знадобитися кілька циклів узгодження, тому деякі засуджені Podʼи можуть мати встановлені посилання на власника, а інші — ні. З цієї причини ми рекомендуємо зачекати, поки контролер знову запуститься, що перевірить посилання на власника перед завершенням роботи Podʼів. Якщо це неможливо, оператор повинен перевірити посилання на власника на PVC, щоб забезпечити видалення очікуваних обʼєктів при примусовому видаленні Podʼів.
Репліки
.spec.replicas — це необовʼязкове поле, яке вказує кількість бажаних Podʼів. Стандартно воно дорівнює 1.
Якщо ви вручну масштабуєте StatefulSet через kubectl scale statefulset statefulset --replicas=X, а потім оновлюєте цей StatefulSet на основі маніфесту (наприклад, за допомогою kubectl apply -f statefulset.yaml), то застосування цього маніфесту перезапише попереднє ручне масштабування.
Якщо HorizontalPodAutoscaler (або будь-який подібний API для горизонтального масштабування) керує масштабуванням StatefulSet, не встановлюйте .spec.replicas. Замість цього дозвольте панелі управління Kubernetes автоматично керувати полем .spec.replicas.
StatefulSet є ресурсом верхнього рівня в REST API Kubernetes. Ознайомтесь із визначенням обʼєкта
StatefulSet, щоб зрозуміти API для StatefulSets.
Дізнайтеся про PodDisruptionBudget та як його можна використовувати для керування доступністю застосунків під час порушень.
4 - DaemonSet
DaemonSet визначає Podʼи, які надають локальні для вузлів можливості. Вони можуть бути фундаментальними для роботи вашого кластера, наприклад, допоміжним інструментом для роботи з мережею, або бути частиною надбудови.
DaemonSet гарантує, що всі (або деякі) вузли запускають копію Podʼа. Коли до кластера додаються вузли, на них додаються Podʼи. Коли вузли видаляються з кластера, ці Podʼи прибирає збір сміття. Видалення DaemonSet призведе до очищення створених ним Podʼів.
Типові варіанти використання DaemonSet:
запуск демона кластерного сховища на кожному вузлі
запуск демона збору логів на кожному вузлі
запуск демона моніторингу вузла на кожному вузлі
У простому випадку один DaemonSet, який охоплює всі вузли, може використовуватися для кожного типу демона. Складніше налаштування може використовувати кілька DaemonSets для одного типу демона, але з різними прапорцями та/або різними запитами памʼяті та CPU для різних типів обладнання.
Створення специфікації DaemonSet
Створення DaemonSet
Ви можете описати DaemonSet у файлі YAML. Наприклад, файл daemonset.yaml нижче описує DaemonSet, який запускає Docker-образ fluentd-elasticsearch:
apiVersion:apps/v1kind:DaemonSetmetadata:name:fluentd-elasticsearchnamespace:kube-systemlabels:k8s-app:fluentd-loggingspec:selector:matchLabels:name:fluentd-elasticsearchtemplate:metadata:labels:name:fluentd-elasticsearchspec:tolerations:# these tolerations are to have the daemonset runnable on control plane nodes# remove them if your control plane nodes should not run pods- key:node-role.kubernetes.io/control-planeoperator:Existseffect:NoSchedule- key:node-role.kubernetes.io/masteroperator:Existseffect:NoSchedulecontainers:- name:fluentd-elasticsearchimage:quay.io/fluentd_elasticsearch/fluentd:v5.0.1resources:limits:memory:200Mirequests:cpu:100mmemory:200MivolumeMounts:- name:varlogmountPath:/var/log# it may be desirable to set a high priority class to ensure that a DaemonSet Pod# preempts running Pods# priorityClassName: importantterminationGracePeriodSeconds:30volumes:- name:varloghostPath:path:/var/log
.spec.template — одне з обовʼязкових полів в .spec.
.spec.template — це шаблон Podʼа. Він має ту саму схему, що і Pod, за винятком того, що він вкладений і не має apiVersion або kind.
Окрім обовʼязкових полів для Podʼа, шаблон Podʼа в DaemonSet повинен вказувати відповідні мітки (див. селектор Podʼа).
Шаблон Podʼа в DaemonSet повинен мати RestartPolicy зі значенням Always або не вказувати її, тоді стандартним значенням буде Always.
Селектор Podʼа
Поле .spec.selector — це селектор Podʼа. Воно працює так само, як і .spec.selector в Job.
Ви повинні вказати селектор Podʼа, який відповідає міткам .spec.template. Крім того, після створення DaemonSet його .spec.selector не можна змінити. Зміна селектора Podʼа може призвести до ненавмисного залишення Podʼів сиротами, і це виявилося незрозумілим для користувачів.
.spec.selector — це обʼєкт, що складається з двох полів:
matchExpressions — дозволяє будувати складніші селектори, вказуючи ключ, список значень та оператор, який повʼязує ключ і значення.
Коли вказано обидва, результат обʼєднується логічною операцією AND.
.spec.selector повинен відповідати .spec.template.metadata.labels. Конфігурація, у якій ці два значення не збігаються, буде відхилена API.
Запуск Podʼів на вибраних вузлах
Якщо ви вказуєте .spec.template.spec.nodeSelector, тоді контролер DaemonSet буде створювати Podʼи на вузлах, які відповідають селектору вузла. Так само, якщо ви вказуєте .spec.template.spec.affinity, тоді контролер DaemonSet буде створювати Podʼи на вузлах, які відповідають цій спорідненості вузла. Якщо ви не вказали жодного з них, контролер DaemonSet буде створювати Podʼи на всіх вузлах.
Як плануються Daemon Podʼи
DaemonSet можна використовувати для того, щоб усі придатні вузли запускали копію Podʼа. Контролер DaemonSet створює Pod для кожного придатного вузла та додає поле spec.affinity.nodeAffinity Podʼа для відповідності цільовому хосту. Після створення Podʼа зазвичай у дію вступає стандартний планувальник і привʼязує Pod до цільового хоста, встановлюючи поле .spec.nodeName. Якщо новий Pod не може поміститися на вузлі, стандартний планувальник може витіснити (виселити) деякі наявні Podʼи на основі пріоритету нового Podʼа.
Примітка:
Якщо важливо, щоб Pod DaemonSet запускався на кожному вузлі, часто бажано встановити .spec.template.spec.priorityClassName DaemonSet на PriorityClass з вищим пріоритетом, щоб гарантувати таке виселення.
Користувач може вказати інший планувальник для Podʼів DaemonSet, встановивши поле .spec.template.spec.schedulerName DaemonSet.
Початкова спорідненість вузла, вказана в полі .spec.template.spec.affinity.nodeAffinity (якщо вказано), береться до уваги контролером DaemonSet під час оцінювання придатних вузлів, але замінюється на спорідненість вузла, що відповідає імені придатного вузла, на створеному Podʼі.
Podʼи DaemonSet можуть бути заплановані на вузли, які не є справними або готовими приймати Podʼи. Будь-які Podʼи DaemonSet, які працюють на таких вузлах, не будуть виселені.
Podʼи DaemonSet можуть бути заплановані на вузли, які недоступні з контролера вузла. Будь-які Podʼи DaemonSet, які працюють на таких вузлах, не будуть виселені.
Додається лише для Podʼів DaemonSet, які запитують мережу вузла, тобто для Podʼів із spec.hostNetwork: true. Такі Podʼи DaemonSet можуть бути заплановані на вузли із недоступною мережею.
Ви можете додавати власні tolerations до Podʼів DaemonSet, визначивши їх в шаблоні Podʼа DaemonSet.
Оскільки контролер DaemonSet автоматично встановлює toleration node.kubernetes.io/unschedulable:NoSchedule, Kubernetes може запускати Podʼи DaemonSet на вузлах, позначених як unschedulable.
Якщо ви використовуєте DaemonSet для надання важливої функції на рівні вузла, такої як мережа кластера, то корисно, що Kubernetes розміщує Podʼи DaemonSet на вузлах до того, як вони будуть готові. Наприклад, без цієї спеціальної toleration ви можете опинитися в тупиковій ситуації, коли вузол не позначений як готовий, тому що мережевий втулок не працює там, і в той самий час мережевий втулок не працює на цьому вузлі, оскільки вузол ще не готовий.
Взаємодія з Daemon Podʼами
Деякі можливі шаблони для взаємодії з Podʼами у DaemonSet:
Push: Podʼи в DaemonSet налаштовані надсилати оновлення до іншого сервісу, такого як база даних статистики. У них немає клієнтів.
NodeIP та відомий порт: Podʼи в DaemonSet можуть використовувати hostPort, щоб до них можна було звертатися за IP-адресами вузлів. Клієнти якимось чином знають список IP-адрес вузлів, а порт знають за домовленістю.
DNS: Створіть headless сервіс із тим самим селектором Podʼа, а потім виявіть DaemonSets, використовуючи ресурс endpoints або отримайте кілька записів A з DNS.
Service: Створіть Service із тим самим селектором Podʼа та використовуйте його для звернення до демона на випадковому вузлі. Використовуйте Політику внутрішнього трафіку Service, щоб обмежитися Podʼами на тому самому вузлі.
Оновлення DaemonSet
Якщо мітки вузлів змінюються, DaemonSet негайно додає Podʼи на вузли, які тепер відповідають умовам, і видаляє Podʼи з вузлів, які більше їм не відповідають.
Ви можете змінювати Podʼи, які створює DaemonSet. Проте Podʼи не дозволяють оновлювати всі поля. Крім того, контролер DaemonSet буде використовувати початковий шаблон під час наступного створення вузла (навіть з тим самим імʼям).
Ви можете видалити DaemonSet. Якщо ви вказали --cascade=orphan з kubectl, тоді Podʼи залишаться на вузлах. Якщо ви потім створите новий DaemonSet з тим самим селектором, новий DaemonSet перейме наявні Podʼи. Якщо потрібно замінити які-небудь Podʼи, DaemonSet їх замінює згідно з його updateStrategy.
Звичайно, можна запускати процеси демонів, безпосередньо стартуючи їх на вузлі (наприклад, за допомогою init, upstartd або systemd). Це абсолютно прийнятно. Однак є кілька переваг запуску таких процесів через DaemonSet:
Можливість моніторингу та управління логами для демонів так само як і для застосунків.
Однакова мова конфігурації та інструменти (наприклад, шаблони Podʼа, kubectl) для демонів та застосунків.
Запуск демонів у контейнерах з обмеженням ресурсів підвищує ізоляцію між демонами та контейнерами застосунків. Однак цього також можна досягти, запускаючи демонів у контейнері, але не в Podʼі.
Окремі Podʼи
Можна створювати Podʼи безпосередньо, вказуючи певний вузол для запуску. Проте DaemonSet замінює Podʼи, які видаляються або завершуються з будь-якої причини, такої як збій вузла або обслуговування вузла з порушенням роботи, наприклад, оновлення ядра. З цієї причини слід використовувати DaemonSet замість створення окремих Podʼів.
Статичні Podʼи
Можна створювати Podʼи, записавши файл у певну теку, за якою стежить kubelet. Їх називають статичними Podʼами. На відміну від DaemonSet, статичними Podʼами не можна управляти за допомогою kubectl або інших клієнтів API Kubernetes. Статичні Podʼи не залежать від apiserver, що робить їх корисними в разі початкового налаштування кластера. Також статичні Podʼи можуть бути визнані застарілими в майбутньому.
Deployments
DaemonSets схожі на Deployments тим, що обидва створюють Podʼи, і ці Podʼи мають процеси, завершення яких не очікується (наприклад, вебсервери, сервери зберігання).
Використовуйте Deployment для stateless-сервісів, таких як фронтенди, де збільшення та зменшення кількості реплік і розгортання оновлень важливіші за контроль над тим, на якому саме хості працює Pod. Використовуйте DaemonSet, коли важливо, щоб копія Podʼа завжди працювала на всіх або певних хостах, якщо DaemonSet надає функціональність рівня вузла, яка дозволяє іншим Podʼам правильно працювати на цьому конкретному вузлі.
Наприклад, мережеві втулки часто включають компонент, який працює як DaemonSet. Цей компонент DaemonSet гарантує, що вузол, де він працює, має справну мережу кластера.
DaemonSet — це ресурс верхнього рівня в REST API Kubernetes. Ознайомтесь з визначенням обʼєкта
DaemonSet, щоб зрозуміти API для DaemonSets.
5 - Jobs
Jobs представляють одноразові завдання, які виконуються до завершення, а потім зупиняються.
Job створює один або кілька Podʼів і продовжує повторювати виконання Podʼів, доки вказана їх кількість успішно не завершиться. Коли Podʼи успішно завершуються, Job відстежує ці успішні завершення. Коли досягнуто вказаної кількості успішних завершень, завдання (тобто Job) завершено. Видалення Job видаляє створені ним Podʼи. Призупинення Job видаляє його активні Podʼи, доки Job не буде знову відновлено.
У простому випадку можна створити один обʼєкт Job для надійного запуску одного Podʼа, який працюватиме доки не завершить виконання роботи. Обʼєкт Job буде запускати новий Pod, якщо перший Pod зазнає невдачі або видаляється (наприклад, через відмову апаратного забезпечення вузла або перезавантаження вузла).
Також можна використовувати Job для запуску кількох Podʼів паралельно.
Якщо ви хочете запускати Job (або одне завдання, або кілька паралельно) за розкладом, див. CronJob.
Запуск прикладу Job
Ось конфігурація прикладу Job. Тут обчислюється число π з точністю до 2000 знаків і виконується його вивід. Виконання зазвичай займає близько 10 секунд.
Як і з будь-якою іншою конфігурацією Kubernetes, у Job мають бути вказані поля apiVersion, kind та metadata.
Коли панель управління створює нові Podʼи для Job, .metadata.name Job є частиною основи для назв цих Podʼів. Назва Job повинна бути дійсним значенням DNS-піддомену, але це може призводити до неочікуваних результатів для імен хостів Podʼів. Для найкращої сумісності назва повинна відповідати суворішим правилам для DNS-мітки. Навіть якщо назва є DNS-піддоменом, вона повинна бути не довшою за 63 символи.
Існують три основних типи завдань, які підходять для виконання як Job:
Непаралельні Jobs
зазвичай запускається лише один Pod, якщо тільки він не зазнає збою.
Job завершується, як тільки робота його Podʼа завершується успішно.
Паралельні Jobs із фіксованою кількістю завершень:
вкажіть ненульове додатне значення для .spec.completions.
Job являє собою загальне завдання і є завершеним, коли є .spec.completions успішних Podʼів.
під час використання .spec.completionMode="Indexed", кожен Pod отримує різний індекс у діапазоні від 0 до .spec.completions-1.
Паралельні Jobs із чергою роботи:
не вказуйте .spec.completions, типово встановлюється .spec.parallelism.
Podʼи повинні координувати свої дії між собою або із зовнішнім сервісом, щоб визначити, над чим кожен з них має працювати. Наприклад, Pod може отримати пакет із не більш ніж N елементів з черги роботи.
кожен Pod може незалежно визначити, чи завершилися всі рівноправні з ним Podʼи, а отже, чи завершено весь Job.
коли будь-який Pod з Job завершується успішно, нові Podʼи не створюються.
як тільки хоча б один Pod завершився успішно і всі Podʼи завершені, тоді Job завершується успішно.
як тільки будь-який Pod завершився успішно, жоден інший Pod не повинен виконувати роботу для цього завдання чи записувати будь-який вивід. Вони всі мають бути в процесі завершення.
Для непаралельного Job ви можете залишити як .spec.completions, так і .spec.parallelism не встановленими. Коли обидва не встановлені, обидва типово встановлюються на 1.
Для Job із фіксованою кількістю завершень вам слід встановити .spec.completions на кількість необхідних завершень. Ви можете встановити .spec.parallelism чи залишити його не встановленим, тоді він стандартно дорівнюватиме 1.
Для Job із чергою роботи ви повинні залишити .spec.completions не встановленим і встановити .spec.parallelism у невідʼємне ціле число.
За докладною інформацією про використання різних типів Job, див. розділ патерни Job.
Контроль паралелізму
Запитаний паралелізм (.spec.parallelism) може бути встановлений у будь-яке невідʼємне значення. Якщо значення не вказано, стандартно воно дорівнює 1. Якщо вказано як 0, то Job фактично призупинено, доки значення не буде збільшено.
Фактичний паралелізм (кількість Podʼів, які працюють в будь-який момент) може бути більше чи менше, ніж запитаний паралелізм, з різних причин:
Для Job із фіксованою кількістю завершень, фактична кількість Podʼів, які працюють паралельно, не перевищуватиме кількість решти завершень. Вищі значення .spec.parallelism фактично ігноруються.
Для Job із чергою роботи жоден новий Pod не запускається після успішного завершення будь-якого Podʼа, однак решті Podʼів дозволено завершити роботу.
Якщо контролер Job не зміг створити Podʼи з будь-якої причини (нестача ResourceQuota, відсутність дозволу тощо), тоді може бути менше Podʼів, ніж запитано.
Контролер Job може обмежувати створення нових Podʼів через надмірну кількість збоїв попередніх Podʼів у тому самому Job.
Коли Pod коректно завершується, на його зупинку потрібен час.
Режим завершення
СТАН ФУНКЦІОНАЛУ:GA since Kubernetes v1.24
Для Jobs із фіксованою кількістю завершень, тобто Jobs зі значенням .spec.completions, відмінним від null, може бути встановлено режим завершення, який вказується в .spec.completionMode:
NonIndexed (стандартно): Job вважається завершеним, коли є .spec.completions успішно завершених Podʼів. Іншими словами, завершення всіх Podʼів рівнозначні. Зверніть увагу, що Jobs, у яких .spec.completions дорівнює null, неявно є NonIndexed.
Indexed: Podʼи Job отримують повʼязаний індекс завершення від 0 до .spec.completions-1. Індекс доступний через чотири механізми:
Мітка Podʼа batch.kubernetes.io/job-completion-index (для v1.28 і новіших). Зверніть увагу, що для використання цієї мітки функціональна можливість PodIndexLabel повинна бути увімкнена, і вона типово увімкнена.
Як частина імені хоста Podʼа, за шаблоном $(job-name)-$(index). Коли ви використовуєте Indexed Job у поєднанні з Service, Podʼи всередині Job можуть використовувати детерміністичні імена хостів для адресації одне одного через DNS. Докладні відомості щодо того, як налаштувати це, див. Job із комунікацією між Podʼами.
З контейнера завдання, в змінній середовища JOB_COMPLETION_INDEX.
Хоча це трапляється рідко, може бути запущено більше одного Podʼа для одного і того ж індексу (з різних причин, таких як відмови вузла, перезапуски kubelet чи виселення Podʼа). У цьому випадку лише перший успішно завершений Pod буде враховуватися при підрахунку кількості завершень та оновленні статусу Job. Інші Podʼи, які працюють чи завершили роботу для того ж самого індексу, будуть видалені контролером Job, щойно їх буде виявлено.
Інтеграція з Workload API
СТАН ФУНКЦІОНАЛУ:Alpha since Kubernetes v1.36; (стандартно вимкнено)
More information about this feature
To use this feature, you (or a cluster administrator) will need to enable the WorkloadWithJob feature gate for all relevant components in your cluster.
Коли функціональну можливість WorkloadWithJob увімкнено, контролер Job компілює конфігурацію .spec.scheduling Job в обʼєкти Workload та PodGroup (scheduling.k8s.io/v1beta1) перед створенням будь-яких Podʼів. Це дозволяє вам виражати явний намір планування для Job, такий як групове планування (всі Podʼи плануються разом або жодного), спільне розташування за топологією та поведінку під час порушень.
Коли ви опускаєте .spec.scheduling, Job типово використовує політику планування Basic, яка зберігає стандартний результат планування Pod за Podʼом для звичайного Job. Контролер все одно створює Workload та PodGroup для кожного відповідного Job (включно з Basic), тому спостережувані обʼєкти є узгодженими незалежно від політики.
Конфігурація планування
Поле .spec.scheduling приймає такі поля:
schedulingPolicy: потрібно вказати рівно одне з basic або gang. З gang всі Podʼи мають бути запланованими разом, перш ніж будь-який з них буде привʼязаний. Опущене gang.minCount стандартно дорівнює .spec.parallelism Job. Див. Політики планування PodGroup.
disruptionMode: чи порушується робота Podʼів окремо (single), чи групою (all). Див. порушення та пріоритет.
resourceClaims: динамічні запити на ресурси, спільні для Podʼів Job.
Всі поля .spec.scheduling є незмінними після створення Job, окрім schedulingPolicy.gang.minCount, яке ви можете змінювати, щоб еластично масштабувати групу.
Групове планування
Цей Job запитує групове планування для своїх 8 Podʼів, розташованих в одній зоні, робота яких порушується разом:
apiVersion:batch/v1kind:Jobmetadata:name:distributed-trainingnamespace:trainingspec:parallelism:8completions:8completionMode:Indexedscheduling:schedulingPolicy:gang:{}# minCount пропущено -> стандартно дорівнює parallelism (8)schedulingConstraints:key:- level:topology.kubernetes.io/zonedisruptionMode:all:{}# робота всієї групи порушується разомtemplate:spec:restartPolicy:Nevercontainers:- name:trainerimage:training-image:latestresources:limits:nvidia.com/gpu:1
Коли контролер Job обробляє цей Job, він:
Створює обʼєкт Workload у тому самому просторі імен, що містить podGroupTemplate, скомпільований з .spec.scheduling (тут — політика групового планування з minCount: 8).
Створює обʼєкт PodGroup на основі цього шаблону. PodGroup є одиницею планування під час виконання і містить вбудовану копію політики.
Створює Podʼи з .spec.schedulingGroup.podGroupName, встановленим на імʼя PodGroup, звʼязуючи кожен Pod зі своєю групою планування.
Контролер виявляє ці обʼєкти через посилання у специфікації (Workload.spec.controllerRef та PodGroup.spec.workloadRef), а не за іменем. Обʼєкти, які створює контролер, містять запис ownerReferences, що вказує на Job, тому вони видаляються збирачем сміття, коли Job видаляється.
Типове (Basic) планування
Job, який опускає .spec.scheduling, типово використовує Basic, що діє як неявна відмова від групового планування. Його Podʼи плануються так само, як у звичайного Job, при цьому все одно створюються Workload та PodGroup типу Basic:
apiVersion:batch/v1kind:Jobmetadata:name:batch-processornamespace:batchspec:parallelism:10completions:10# .spec.scheduling пропущено -> типово використовується Basic scheduling.template:spec:restartPolicy:Nevercontainers:- name:processorimage:processor-image:v1
Контролери вищого рівня
Для автономного Job контролер Job володіє як Workload, так і PodGroup. Коли Job натомість містить ownerReference на батьківський контролер, який компілює Workload (наприклад, JobSet), контролер Job делегує володіння Workload цьому батьківському контролеру. Чи створює контролер Job все ще PodGroup під час виконання, залежить від того, що делегує батьківський контролер:
Якщо батьківський контролер встановлює анотацію scheduling.k8s.io/group-template-name на Job, контролер Job створює та володіє PodGroup, зіставленим з іменованим PodGroupTemplate батьківського контролера.
В іншому випадку батьківський контролер володіє обома обʼєктами, і контролер Job не створює жодного; він виявляє наявні обʼєкти та використовує їх під час створення Podʼів.
Якщо в шаблоні Podʼа Job вже задано .spec.template.spec.schedulingGroup, контролер Job не створює жодного обʼєкта, дозволяючи вам (або контролеру вищого рівня) самостійно керувати життєвим циклом Workload/PodGroup.
Поведінка CronJob
Jobs, створені за допомогою CronJob, є автономними; CronJob не створює та не керує обʼєктами Workload. Якщо jobTemplate CronJob встановлює .spec.scheduling, контролер Job створює окремі обʼєкти Workload та PodGroup для кожного екземпляра Job, скомпільовані з .spec.scheduling цього Job (типово Basic, якщо опущено). Ці обʼєкти видаляються збирачем сміття, коли кожен Job завершується або видаляється.
Обмеження для альфа-релізу
Кожен Job відповідає точно одному обʼєкту PodGroup; всі Podʼи в Job поділяють єдину політику планування.
Лише schedulingPolicy.gang.minCount є змінним; всі інші поля .spec.scheduling є незмінними після створення.
Призупинені Jobs зберігають свої обʼєкти Workload та PodGroup; вони не видаляються під час призупинення і не створюються заново під час відновлення.
Обробка збоїв Podʼа та контейнера
Контейнер у Podʼі може вийти з ладу з ряду причин, таких як завершення процесу з ненульовим кодом виходу або примусове припинення роботи контейнера через перевищення обмеження памʼяті тощо. Якщо це стається і .spec.template.spec.restartPolicy = "OnFailure", тоді Pod залишається на вузлі, але контейнер перезапускається. Отже, ваш застосунок повинен обробляти випадок, коли він перезапускається локально, або вказувати .spec.template.spec.restartPolicy = "Never". Докладні відомості про restartPolicy див. в розділі життєвий цикл Podʼа.
Весь Pod також може вийти з ладу з низки причин, таких як коли Pod виштовхується з вузла (вузол оновлюється, перезавантажується, видаляється тощо), або якщо контейнер Podʼа виходить з ладу і .spec.template.spec.restartPolicy = "Never". Коли Pod виходить з ладу, контролер Job запускає новий Pod. Це означає, що ваш застосунок повинен обробляти випадок, коли він перезапускається у новому Podʼі. Зокрема, він повинен обробляти тимчасові файли, блокування, неповний вивід та інше, викликане попередніми запусками.
Додатково ви можете вирішити враховувати збої Podʼа незалежно для кожного індексу в Indexed Job, встановлюючи поле .spec.backoffLimitPerIndex (докладні відомості див. обмеження backoff на індекс).
Зверніть увагу, що навіть якщо ви вказали .spec.parallelism = 1 і .spec.completions = 1 і .spec.template.spec.restartPolicy = "Never", та сама програма може іноді бути запущена двічі.
Якщо ви вказали як .spec.parallelism, так і .spec.completions більше ніж 1, то може бути запущено кілька Podʼів одночасно. Таким чином, ваші Podʼи також повинні бути стійкими до паралелізму.
Якщо ви вказуєте поле .spec.podFailurePolicy, контролер Job не вважає збоєм Pod, що завершується (Pod зі встановленим полем .metadata.deletionTimestamp), доки цей Pod не стане термінальним (його .status.phase є Failed або Succeeded). Однак контролер Job створює Pod-замінник, щойно стає очевидним, що Pod перебуває в процесі завершення. Після того як Pod завершиться, контролер Job оцінює .backoffLimit і .podFailurePolicy для відповідного Job, враховуючи тепер уже завершений Pod.
Якщо хоча б одна з цих вимог не виконана, контролер Job вважає Pod, що завершується, негайним збоєм, навіть якщо цей Pod пізніше завершиться з phase: "Succeeded".
Політика backoff для збоїв Podʼа
Трапляються ситуації, коли ви хочете, щоб Job зазнав збою після певної кількості спроб через логічну помилку в конфігурації тощо. Для цього встановіть .spec.backoffLimit, щоб вказати кількість повторних спроб, після яких Job вважатиметься невдалим.
Стандартне значення .spec.backoffLimit дорівнює 6, якщо не вказано обмеження backoff на індекс (тільки Індексовані Job). Якщо вказано .spec.backoffLimitPerIndex, то .spec.backoffLimit стандартно дорівнює 2147483647 (MaxInt32).
Повʼязані з Job невдалі Podʼи створюються заново контролером Job з експоненціальною затримкою (10s, 20s, 40s …), яка обмежена десятьма хвилинами.
Кількість спроб обчислюється двома способами:
Кількість Podʼів з .status.phase = "Failed".
Під час використання restartPolicy = "OnFailure" кількість спроб у всіх контейнерах Podʼів з .status.phase, що дорівнює Pending або Running.
Якщо хоча б один із розрахунків досягне значення .spec.backoffLimit, Job вважається невдалим.
Примітка:
Якщо ваш Job має restartPolicy = "OnFailure", майте на увазі, що Pod, який виконує Job, буде завершено, щойно буде досягнуто обмеження backoff Job. Це може ускладнити налагодження виконуваного файлу Job. Ми радимо встановлювати restartPolicy = "Never" під час налагодження Job або використовувати систему логування, щоб вивід невдалих Jobs не було випадково втрачено.
обмеження backoff на індекс
СТАН ФУНКЦІОНАЛУ:GA since Kubernetes v1.33
More information about this feature
This is a stable feature in Kubernetes, and has been since version v1.33. It was first available in the v1.28 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate JobBackoffLimitPerIndex, Kubernetes ignores it but does not report any error.
Коли ви запускаєте Indexed Job, ви можете вибрати обробку спроб для збоїв Podʼа незалежно для кожного індексу. Для цього встановіть .spec.backoffLimitPerIndex, щоб вказати максимальну кількість невдалих спроб Podʼа для кожного індексу.
Коли обмеження backoff на індекс перевищується для певного індексу, Kubernetes вважає цей індекс невдалим і додає його до поля .status.failedIndexes. Індекси, які виконались успішно, реєструються в полі .status.completedIndexes, незалежно від того, чи ви встановили поле backoffLimitPerIndex.
Зауважте, що невдалий індекс не перериває виконання інших індексів. Щойно всі індекси завершаться для Job, в якому ви вказали обмеження backoff на індекс, якщо хоча б один з цих індексів виявився невдалим, контролер Job позначає весь Job як невдалий, встановлюючи стан Failed в статусі. Job отримує позначку "невдалий", навіть якщо деякі, можливо, майже всі індекси були оброблені успішно.
Ви також можете обмежити максимальну кількість позначених невдалих індексів, встановивши поле .spec.maxFailedIndexes. Коли кількість невдалих індексів перевищує значення поля maxFailedIndexes, контролер Job запускає завершення всіх Podʼів, що залишаються запущеними в цьому Job. Щойно всі Podʼи будуть завершені, контролер Job позначає весь Job як невдалий, встановлюючи стан Failed в статусі Job.
Ось приклад маніфесту для Job, який визначає backoffLimitPerIndex:
apiVersion:batch/v1kind:Jobmetadata:name:job-backoff-limit-per-index-examplespec:completions:10parallelism:3completionMode:Indexed # required for the featurebackoffLimitPerIndex:1# maximal number of failures per indexmaxFailedIndexes:5# maximal number of failed indexes before terminating the Job executiontemplate:spec:restartPolicy:Never# required for the featurecontainers:- name:exampleimage:pythoncommand:# The jobs fails as there is at least one failed index# (all even indexes fail in here), yet all indexes# are executed as maxFailedIndexes is not exceeded.- python3- -c- | import os, sys
print("Hello world")
if int(os.environ.get("JOB_COMPLETION_INDEX")) % 2 == 0:
sys.exit(1)
У вищенаведеному прикладі контролер Job дозволяє один перезапуск для кожного з індексів. Коли загальна кількість невдалих індексів перевищує 5, тоді весь Job завершується.
Після завершення Job його стан виглядає так:
kubectl get -o yaml job job-backoff-limit-per-index-example
status:completedIndexes:1,3,5,7,9failedIndexes:0,2,4,6,8succeeded:5# 1 succeeded pod for each of 5 succeeded indexesfailed:10# 2 failed pods (1 retry) for each of 5 failed indexesconditions:- message:Job has failed indexesreason:FailedIndexesstatus:"True"type:FailureTarget- message:Job has failed indexesreason:FailedIndexesstatus:"True"type:Failed
Контролер Job додає стан FailureTarget до Job для запуску завершення та очищення Job. Коли всі Podʼи Job завершуються, контролер Job додає стан Failed з тими ж значеннями для reason і message, що й у стану FailureTarget. Для деталей дивіться Завершення Podʼів Job.
Додатково ви можете використовувати обмеження backoff на індекс разом з політикою збоїв Podʼа. Коли використовується обмеження backoff на індекс, доступна нова дія FailIndex, яка дозволяє вам уникати непотрібних повторів всередині індексу.
Політика збоїв Podʼа
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ʼа, визначена за допомогою поля .spec.podFailurePolicy, дозволяє вашому кластеру обробляти збої Podʼа на основі кодів виходу контейнера та станів Podʼа.
У деяких ситуаціях вам може знадобитися кращий контроль обробки збоїв Podʼа, ніж контроль, який надає Політика backoff для збоїв Podʼа, яка базується на .spec.backoffLimit Job. Ось деякі приклади використання:
Для оптимізації витрат на виконання робочих навантажень, уникнення непотрібних перезапусків Podʼа, ви можете завершити Job, як тільки один із його Podʼів відмовить із кодом виходу, що вказує на помилку програмного забезпечення.
Щоб гарантувати, що ваш Job завершиться, навіть якщо є порушення, ви можете ігнорувати збої Podʼів, спричинені порушеннями (такими як витіснення, виселення, ініційоване API або виселення на основі taint), щоб вони не враховувалися в обмеженні спроб .spec.backoffLimit.
Ви можете налаштувати політику збоїв Podʼа в полі .spec.podFailurePolicy, щоб задовольнити наведені вище сценарії використання. Ця політика може обробляти збої Podʼа на основі кодів виходу контейнера та станів Podʼа.
Ось маніфест для Job, який визначає podFailurePolicy:
apiVersion:batch/v1kind:Jobmetadata:name:job-pod-failure-policy-examplespec:completions:12parallelism:3template:spec:restartPolicy:Nevercontainers:- name:mainimage:docker.io/library/bash:5command:["bash"]# example command simulating a bug which triggers the FailJob actionargs:- -c- echo "Hello world!" && sleep 5 && exit 42backoffLimit:6podFailurePolicy:rules:- action:FailJobonExitCodes:containerName:main # optionaloperator: In # one of:In, NotInvalues:[42]- action: Ignore # one of:Ignore, FailJob, CountonPodConditions:- type:DisruptionTarget # indicates Pod disruption
У вищенаведеному прикладі перше правило політики збоїв Podʼа вказує, що Job слід позначити як невдалий, якщо контейнер main завершиться кодом виходу 42. Наступні правила стосуються саме контейнера main:
код виходу 0 означає, що контейнер виконався успішно
код виходу 42 означає, що весь Job завершився невдало
будь-який інший код виходу вказує, що контейнер, а отже, і весь Pod завершилися невдало. Pod буде створено заново, якщо загальна кількість перезапусків менша за backoffLimit. Якщо backoffLimit досягнуто, весь Job завершився невдало.
Примітка:
Оскільки в шаблоні Podʼа вказано restartPolicy: Never, kubelet не перезапускає контейнер main в тому конкретному Podʼі.
Друге правило політики збоїв Podʼа, що вказує дію Ignore для невдалих Podʼів зі станом DisruptionTarget, виключає порушення роботи Podʼів із підрахунку обмеження спроб .spec.backoffLimit.
Примітка:
Якщо Job виявився невдалим через політику збоїв Podʼа чи через політику backoff для збоїв Podʼа, і Job виконується кількома Podʼами, Kubernetes завершує всі Podʼи в цьому Job, які все ще перебувають у статусах Pending або Running.
Ось деякі вимоги та семантика API:
якщо ви хочете використовувати поле .spec.podFailurePolicy для Job, вам також слід визначити шаблон Podʼа цього Job з .spec.restartPolicy, встановленим на Never.
правила політики збоїв Podʼа, які ви визначаєте у spec.podFailurePolicy.rules, оцінюються послідовно. Якщо одне з правил відповідає збою Podʼа, інші правила ігноруються. Якщо жодне правило не відповідає збою Podʼа, застосовується типова обробка.
ви можете обмежити правило певним контейнером, вказавши його імʼя у spec.podFailurePolicy.rules[*].onExitCodes.containerName. Якщо не вказано, правило застосовується до всіх контейнерів. Якщо вказано, воно повинно відповідати імені одного з контейнерів або initContainer у шаблоні Podʼа.
ви можете вказати дію, яка виконується, коли спрацьовує політика збоїв Podʼа, у spec.podFailurePolicy.rules[*].action. Можливі значення:
FailJob: використовуйте це, щоб вказати, що Job цього Podʼа має бути позначений як Failed, а всі запущені Podʼи мають бути завершені.
Ignore: використовуйте це, щоб вказати, що значення лічильника, що рахує .spec.backoffLimit, не повинне збільшуватися, і має бути створений Pod-замінник.
Count: використовуйте це, щоб вказати, що Pod повинен бути оброблений типовим способом. Лічильник .spec.backoffLimit повинен збільшитися.
FailIndex: використовуйте цю дію разом із обмеження backoff на індекс для уникнення непотрібних повторних спроб в межах індексу невдалого Podʼа.
Примітка:
Коли використовується podFailurePolicy, контролер Job враховує лише Podʼи у фазі Failed. Podʼи з відміткою про видалення, які не знаходяться в термінальній фазі (Failed чи Succeeded), вважаються такими, що ще завершуються. Це означає, що такі Podʼи зберігають завершувачі відстеження доки не досягнуть термінальної фази. З Kubernetes 1.27 Kubelet переводить видалені Podʼи в термінальну фазу (див.: Фаза Podʼа). Це забезпечує видалення завершувачів контролером Job.
Примітка:
Починаючи з Kubernetes v1.28, коли використовується політика збоїв Podʼа, контролер Job створює заново Podʼи, що завершуються, лише тоді, коли ці Podʼи досягли термінальної фази Failed. Ця поведінка подібна до podReplacementPolicy: Failed. Докладніше див. Політика заміни Podʼів.
Коли ви використовуєте podFailurePolicy, і Job зазнає невдачі через Pod, що відповідає правилу з дією FailJob, контролер Job запускає процес завершення Job, додаючи стан FailureTarget. Для деталей дивіться Завершення та очищення Job.
Політика успіху
Під час створення Indexed Job ви можете визначити, коли Job може бути визнаний успішним, за допомогою .spec.successPolicy, на основі успішних Podʼів.
Типово Job вважається успішним, коли кількість успішних Podʼів дорівнює .spec.completions. Існують ситуації, коли вам може знадобитися додатковий контроль для визнання Job успішним:
Під час виконання симуляцій з різними параметрами, вам можуть не знадобитися всі симуляції для успішного завершення загального Job.
Під час використання шаблону лідер-виконавець, лише успіх лідера визначає успіх чи невдачу Job. Прикладами цього є фреймворки, такі як MPI та PyTorch тощо.
Ви можете налаштувати політику успіху у полі .spec.successPolicy, щоб задовольнити вищезазначені випадки використання. Ця політика може керувати успіхом Job на основі успішних Podʼів. Після того, як Job відповідає політиці успіху, контролер Job завершує решту Podʼів. Політика успіху визначається правилами. Кожне правило може мати одну з таких форм:
Коли ви вказуєте лише succeededIndexes, одразу після успішного завершення всіх індексів, вказаних у succeededIndexes, контролер Job позначає Job як успішний. succeededIndexes повинен бути списком інтервалів між 0 і .spec.completions-1.
Коли ви вказуєте лише succeededCount, як тільки кількість успішних індексів досягне succeededCount, контролер Job позначає Job як успішний.
Коли ви вказуєте як succeededIndexes, так і succeededCount, як тільки кількість успішних індексів з підмножини індексів, вказаних у succeededIndexes, досягне succeededCount, контролер Job позначає Job як успішний.
Зверніть увагу, що коли ви вказуєте кілька правил у .spec.successPolicy.rules, контролер Job оцінює правила послідовно. Після того, як Job задовольняє правило, контролер Job ігнорує решту правил.
apiVersion:batch/v1kind:Jobmetadata:name:job-successspec:parallelism:10completions:10completionMode:Indexed# Required for the success policysuccessPolicy:rules:- succeededIndexes:0,2-3succeededCount:1template:spec:containers:- name:mainimage:pythoncommand:# Provided that at least one of the Pods with 0, 2, and 3 indexes has succeeded,# the overall Job is a success.- python3- -c- | import os, sys
if os.environ.get("JOB_COMPLETION_INDEX") == "2":
sys.exit(0)
else:
sys.exit(1)restartPolicy:Never
У вищенаведеному прикладі були вказані як succeededIndexes, так і succeededCount. Тому контролер Job позначить Job як успішний і завершить залишкові Podʼи після успіху будь-яких зазначених індексів, 0, 2 або 3. Job, який відповідає політиці успіху, отримує стан SuccessCriteriaMet з причиною SuccessPolicy. Після видалення залишкових Podʼів, Job отримує стан Complete.
Зверніть увагу, що succeededIndexes представлено як інтервали, розділені дефісом. Номери перераховані у вигляді першого та останнього елементів серії, розділених дефісом.
Примітка:
Коли ви вказуєте як політику успіху, так і деякі політики завершення, такі як .spec.backoffLimit і .spec.podFailurePolicy, щойно Job задовольняє будь-яку з політик, контролер Job дотримується політики завершення і ігнорує політику успіху.
Завершення Job та очищення
Коли Job завершується, Podʼи більше не створюються, але Podʼи зазвичай також не видаляються. Якщо їх не видаляти, можна переглядати логи завершених Podʼів для перевірки наявності помилок, попереджень чи іншого діагностичного виводу. Обʼєкт Job також залишається після завершення, щоб ви могли переглядати його статус. Користувач сам видаляє старі Jobs, переглянувши їхній статус. Видаліть Job за допомогою kubectl (наприклад, kubectl delete jobs/pi або kubectl delete -f ./job.yaml). Коли ви видаляєте Job за допомогою kubectl, усі створені ним Podʼи також видаляються.
Стандартно Job буде виконуватися безперервно, якщо тільки Pod не вийде з ладу (restartPolicy=Never) або контейнер не вийде з ладу з помилкою (restartPolicy=OnFailure), після чого Job дотримується .spec.backoffLimit, описаного вище. Як тільки досягнуто .spec.backoffLimit, Job буде позначено як невдалий, і будь-які запущені Podʼи будуть завершені.
Іншим способом завершити Job є встановлення активного крайнього терміну. Це робиться шляхом встановлення в поле .spec.activeDeadlineSeconds Job кількості секунд. activeDeadlineSeconds застосовується до тривалості Job, незалежно від кількості створених Podʼів. Як тільки Job досягає activeDeadlineSeconds, всі його запущені Podʼи завершуються, і статус Job стане type: Failed з reason: DeadlineExceeded.
Зауважте, що .spec.activeDeadlineSeconds Job має пріоритет перед його .spec.backoffLimit. Отже, Job, який повторно запускає один або кілька невдалих Podʼів, не розпочне розгортання додаткових Podʼів, якщо activeDeadlineSeconds вже досягнуто, навіть якщо backoffLimit ще не досягнуто.
Зверніть увагу, що як саме специфікація Job, так і специфікація шаблону Podʼа у межах Job мають поле activeDeadlineSeconds. Переконайтеся, що ви встановлюєте це поле на відповідному рівні.
Памʼятайте, що restartPolicy застосовується до Podʼа, а не до самого Job: автоматичного перезапуску Job не відбудеться, якщо статус Job type: Failed. Тобто механізми завершення Job, активовані за допомогою .spec.activeDeadlineSeconds і .spec.backoffLimit, призводять до остаточного збою Job, який потребує ручного втручання.
Термінальні стани Job
Job має два можливих термінальних стани, кожному з яких відповідає стан Job (condition):
Успішне виконання: стан Job Complete
Невдача: стан Job Failed
Jobs зазнають невдачі з таких причин:
Кількість невдач Podʼа перевищила вказане .spec.backoffLimit у специфікації Job. Для деталей див. Політика backoff для збоїв Podʼа.
Час виконання Job перевищив вказане .spec.activeDeadlineSeconds.
Indexed Job, який використовує .spec.backoffLimitPerIndex, має збійні індекси. Для деталей див. обмеження backoff на індекс.
Кількість невдалих індексів у Job перевищила вказане значення spec.maxFailedIndexes. Для деталей див. обмеження backoff на індекс.
Невдалий Pod відповідає правилу у .spec.podFailurePolicy, яке має дію FailJob. Для деталей про те, як правила політики збоїв Podʼа можуть вплинути на оцінку невдачі, див. Політика збоїв Podʼа.
Jobs успішні з таких причин:
Кількість успішних Podʼів досягла вказаного .spec.completions.
Виконані критерії, зазначені у .spec.successPolicy. Для деталей див. Політика успіху.
У Kubernetes v1.31 та пізніших версіях контролер Job затримує додавання термінальних станів, Failed або Complete, поки всі Podʼи Job не будуть завершені.
У Kubernetes v1.30 та раніших версіях контролер Job додавав термінальні стани Complete або Failed відразу після того, як був запущений процес завершення Job та всі завершувачі Podʼа були видалені. Однак деякі Podʼи все ще могли працювати або завершуватися в момент додавання термінального стану.
У Kubernetes v1.31 та пізніших версіях контролер додає термінальні стани Job лише після завершення всіх Podʼів. Ви можете керувати цією поведінкою за допомогою функціональних можливостейJobManagedBy та JobPodReplacementPolicy (обидві стандартно увімкнені).
Завершення Podʼів Job
Контролер Job додає стан FailureTarget або стан SuccessCriteriaMet до Job, щоб запустити завершення Podʼів після того, як Job відповідає критеріям успіху або невдачі.
Фактори, такі як terminationGracePeriodSeconds, можуть збільшити час від моменту додавання контролером Job стану FailureTarget або стану SuccessCriteriaMet до моменту, коли всі Podʼи Job завершаться і контролер Job додасть термінальний стан (Failed або Complete).
Ви можете використовувати стан FailureTarget або стан SuccessCriteriaMet, щоб оцінити, чи Job зазнав невдачі чи досяг успіху, без необхідності чекати, поки контролер додасть термінальний стан.
Наприклад, ви можете захотіти вирішити, коли створити Job-замінник для невдалого Job. Якщо ви заміните невдалий Job, щойно зʼявиться стан FailureTarget, ваш Job-замінник запуститься раніше, але Podʼи невдалого Job і Job-замінника можуть працювати одночасно, використовуючи додаткові обчислювальні ресурси.
Або, якщо ваш кластер має обмежену місткість ресурсів, ви можете дочекатися появи стану Failed на Job, що затримає ваш Job-замінник, але збереже ресурси, оскільки ви дочекаєтеся видалення всіх невдалих Podʼів.
Автоматичне очищення завершених Jobs
Зазвичай завершені Jobs вже не потрібні в системі. Їх зберігання створює тиск на API-сервер. Якщо Jobs керуються безпосередньо контролером вищого рівня, таким як CronJobs, їх можуть очищати CronJobs на основі заданої політики очищення за місткістю.
Механізм TTL для завершених Jobs
СТАН ФУНКЦІОНАЛУ:GA since Kubernetes v1.23
Ще один спосіб автоматично очищати завершені Jobs (Complete або Failed) — це використовувати механізм TTL, наданий
контролером TTL для завершених ресурсів, вказуючи поле .spec.ttlSecondsAfterFinished у Job.
Коли контролер TTL очищує Job, він каскадно видаляє Job, тобто видаляє його залежні обʼєкти, такі як Podʼи, разом з Job. Зверніть увагу, що під час видалення Job будуть дотримані гарантії його життєвого циклу, такі як завершувачі.
Job pi-with-ttl стане придатним для автоматичного видалення через 100 секунд після завершення.
Якщо поле встановлено в 0, Job стане придатним для автоматичного видалення одразу після завершення. Якщо поле не вказане, Job не буде очищено контролером TTL після завершення.
Примітка:
Рекомендується встановлювати поле ttlSecondsAfterFinished, оскільки некеровані Jobs (Jobs, які ви створили безпосередньо, а не опосередковано через інші API робочого навантаження, такі як CronJob) мають стандартну політику видалення orphanDependents, що призводить до того, що Podʼи, створені некерованим Job, залишаються після того, як Job повністю видалено. Навіть якщо панель управління зрештою прибирає збором сміття Podʼи видаленого Job після їх збою або завершення, іноді ці залишкові Podʼи можуть погіршувати продуктивність кластера або в найгіршому випадку спричинити вихід кластера з ладу через це погіршення.
Ви можете використовувати LimitRanges та ResourceQuotas, щоб обмежити кількість ресурсів, які певний простір імен може споживати.
Патерни використання Job
Обʼєкт Job може використовуватися для обробки набору незалежних, але повʼязаних робочих одиниць. Це можуть бути електронні листи для надсилання, кадри для рендерингу, файли для перекодування, діапазони ключів у базі даних NoSQL для сканування і так далі.
У складній системі може бути кілька різних наборів робочих одиниць. Тут ми розглядаємо лише один набір робочих одиниць, якими користувач хоче керувати разом — пакетне завдання.
Існує кілька різних патернів для паралельних обчислень, кожен з власними перевагами та недоліками. Компроміси:
Один обʼєкт Job для кожної робочої одиниці або один обʼєкт Job для всіх робочих одиниць. Один Job на кожну робочу одиницю створює деяку накладну роботу для користувача та системи під час управління великою кількістю обʼєктів Job. Один Job для всіх робочих одиниць підходить краще для великої кількості одиниць.
Кількість створених Podʼів дорівнює кількості робочих одиниць або кожен Pod може обробляти кілька робочих одиниць. Коли кількість Podʼів дорівнює кількості робочих одиниць, Podʼи зазвичай вимагають менше змін у наявному коді та контейнерах. Кожен Pod, що обробляє кілька робочих одиниць, підходить краще для великої кількості одиниць.
Кілька підходів використовують чергу роботи. Це вимагає запуску сервісу черги та змін наявної програми чи контейнера, щоб вони використовували чергу роботи. Інші підходи легше адаптувати до наявного контейнеризованого застосунку.
Коли Job повʼязаний із headless Service, ви можете дозволити Podʼам у межах Job спілкуватися один з одним для спільних обчислень.
Переваги та недоліки узагальнено у таблиці нижче, де стовпці з 2 по 4 відповідають зазначеним вище питанням. Назви патернів також є посиланнями на приклади та більш детальний опис.
Коли ви вказуєте завершення з .spec.completions, кожний Pod, створений контролером Job, має ідентичний spec. Це означає, що всі Podʼи для завдання матимуть однаковий командний рядок, однаковий образ, однакові томи та (майже) однакові змінні середовища. Ці патерни — це різні способи організації Podʼів для роботи над різними завданнями.
Ця таблиця показує обовʼязкові налаштування для .spec.parallelism та .spec.completions для кожного з патернів. Тут W — це кількість робочих одиниць.
Коли створюється Job, контролер Job негайно починає створювати Podʼи, щоб відповідати вимогам Job і продовжує це робити, доки Job не завершиться. Однак іноді ви можете хотіти тимчасово призупинити виконання Job та відновити його пізніше, або запускати Jobs у призупиненому стані, щоб власний контролер пізніше вирішував, коли їх запустити.
Щоб призупинити Job, ви можете оновити поле .spec.suspend Job на значення true; пізніше, коли ви захочете відновити його, оновіть його на значення false. Створення Job з .spec.suspend встановленим в true створить його в призупиненому стані.
У Kubernetes 1.35 або новіших версіях поле .status.startTime очищується під час призупинення Job, коли увімкнено функціональну можливість MutableSchedulingDirectivesForSuspendedJobs.
Під час відновлення Job після призупинення його поле .status.startTime буде скинуто на поточний час. Це означає, що таймер .spec.activeDeadlineSeconds буде зупинений і перезапущений, коли Job буде призупинено та відновлено.
Коли ви призупиняєте Job, будь-які запущені Podʼи, які не мають статусу Completed, будуть завершені з сигналом SIGTERM. Період коректного завершення Podʼа буде дотримано, і ваш Pod має обробити цей сигнал протягом цього періоду. Це може включати в себе збереження прогресу на майбутнє або скасування змін. Podʼи, завершені у такий спосіб, не враховуватимуться при підрахунку completions Job.
Приклад визначення Job в призупиненому стані може виглядати так:
Статус Job може бути використаний для визначення того, чи Job призупинено чи його було призупинено раніше:
kubectl get jobs/myjob -o yaml
apiVersion:batch/v1kind:Job# .metadata та .spec опущеноstatus:conditions:- lastProbeTime:"2021-02-05T13:14:33Z"lastTransitionTime:"2021-02-05T13:14:33Z"status:"True"type:SuspendedstartTime:"2021-02-05T13:13:48Z"
Стан Job типу "Suspended" зі статусом "True" означає, що Job призупинено; поле lastTransitionTime може бути використане для визначення того, як довго Job було призупинено. Якщо статус цього стану є "False", то Job було раніше призупинено і зараз він працює. Якщо такого стану не існує в статусі Job, то Job ніколи не був зупинений.
Також створюються події, коли Job призупинено та відновлено:
kubectl describe jobs/myjob
Name: myjob
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 12m job-controller Created pod: myjob-hlrpl
Normal SuccessfulDelete 11m job-controller Deleted pod: myjob-hlrpl
Normal Suspended 11m job-controller Job suspended
Normal SuccessfulCreate 3s job-controller Created pod: myjob-jvb44
Normal Resumed 3s job-controller Job resumed
Останні чотири події, зокрема події "Suspended" та "Resumed", є прямим наслідком перемикання поля .spec.suspend. Протягом цього часу ми бачимо, що жоден Pod не був створений, але створення Podʼів розпочалося знову, як тільки Job було відновлено.
Змінні директиви планування
СТАН ФУНКЦІОНАЛУ:GA since Kubernetes v1.27
У більшості випадків паралельний Job потребуватиме, щоб його Podʼи запускалися з певними обмеженнями, типу "всі в одній зоні" або "всі на GPU моделі x або y", але не комбінація обох.
Поле призупинення є першим кроком до такої семантики. Призупинення дозволяє власному контролеру черги вирішувати, коли має початися Job; однак після зняття призупинення власний контролер черги не впливає на те, де насправді будуть розташовані Podʼи Job.
Ця функція дозволяє оновлювати директиви планування Job до запуску, що дає власному контролеру черги змогу впливати на розташування Podʼів, водночас залишаючи саме призначення Podʼів вузлам за kube-scheduler.
Поля в шаблоні Podʼа Job, які можна оновити, це спорідненість вузла, селектор вузла, tolerations, мітки, анотації та scheduling gates.
Змінні директиви планування для призупинених Jobs
СТАН ФУНКЦІОНАЛУ:Beta since Kubernetes v1.36; (стандартно увімкнено)
У Kubernetes 1.34 та раніших версіях змінювати директиви планування Podʼа дозволяється лише для призупинених Jobs, які ніколи не відновлювалися раніше. Починаючи з Kubernetes 1.35, це дозволяється для будь-яких призупинених Jobs, коли увімкнено функціональну можливість MutableSchedulingDirectivesForSuspendedJobs.
Крім того, ця функціональна можливість дозволяє очищати поле .status.startTime при призупиненні Job.
Змінні ресурси Podʼа для призупинених Jobs
СТАН ФУНКЦІОНАЛУ:Beta since Kubernetes v1.36; (стандартно увімкнено)
Адміністратор кластера може визначити контроль допуску в Kubernetes, змінюючи запити на ресурси або обмеження для Job на основі правил політики.
За допомогою цієї функції Kubernetes також дозволяє змінювати шаблон Podʼа для призупиненого Job, щоб змінити вимоги до ресурсів Podʼів у Job. Це відрізняється від зміни розміру Podʼа на місці, яке дозволяє оновлювати ресурси по одному Podʼу за раз для Podʼів, які вже працюють.
Клієнт, який встановлює нові запити на ресурси або обмеження, може відрізнятися від клієнта, який спочатку створив Job, і не обовʼязково має бути адміністратором кластера.
Визначення власного селектора Podʼа
Зазвичай, коли ви створюєте обʼєкт Job, ви не вказуєте .spec.selector. Логіка системного визначення типових значень додає це поле під час створення Job. Вона обирає значення селектора, яке не перетинатиметься з жодним іншим Job.
Однак у деяких випадках вам може знадобитися перевизначити цей автоматично встановлений селектор. Для цього ви можете вказати .spec.selector Job.
Будьте дуже уважні при цьому. Якщо ви вказуєте селектор міток, який не є унікальним для Podʼів цього Job, і який відповідає неповʼязаним Podʼам, то Podʼи неповʼязаного Job можуть бути видалені, або цей Job може зарахувати інші Podʼи як свої завершення, або один чи обидва Jobs можуть відмовитися створювати Podʼи чи виконуватися до завершення. Якщо вибрано неунікальний селектор, інші контролери (наприклад, ReplicationController) та їхні Podʼи також можуть поводитися непередбачувано. Kubernetes не завадить вам помилитися під час вказування .spec.selector.
Ось приклад ситуації, коли вам може знадобитися використовувати цю функцію.
Скажімо, Job old вже запущений. Ви хочете, щоб наявні Podʼи продовжували працювати, але щоб решта Podʼів, які він створює, використовували інший шаблон Podʼа, а Job мав нову назву. Ви не можете оновити Job, оскільки ці поля не можна оновлювати. Отже, ви видаляєте Job old, але залишаєте його Podʼи запущеними, використовуючи kubectl delete jobs/old --cascade=orphan. Перед видаленням ви занотовуєте, який селектор він використовує:
Потім ви створюєте новий Job із назвою new і явно вказуєте той самий селектор. Оскільки наявні Podʼи мають мітку batch.kubernetes.io/controller-uid=a8f3d00d-c6d2-11e5-9f87-42010af00002, вони також контролюються Job new.
Вам потрібно вказати manualSelector: true у новому Job, оскільки ви не використовуєте селектор, який система зазвичай генерує автоматично.
Сам новий Job матиме uid, відмінний від a8f3d00d-c6d2-11e5-9f87-42010af00002. Встановлення manualSelector: true говорить системі, що ви розумієте, що робите, і дозволяє цю невідповідність.
Відстеження Job за допомогою завершувачів
СТАН ФУНКЦІОНАЛУ:GA since Kubernetes v1.26
Панель управління стежить за Podʼами, які належать до будь-якого Job, і виявляє, чи якийсь такий Pod видалено з API-сервера. Для цього контролер Job створює Podʼи з завершувачем batch.kubernetes.io/job-tracking. Контролер видаляє завершувач тільки після того, як Pod був врахований в стані Job, що дозволяє видалити Pod іншими контролерами або користувачами.
СТАН ФУНКЦІОНАЛУ:GA since Kubernetes v1.31; (стандартно увімкнено)
More information about this feature
This is a stable feature in Kubernetes, and has been since version 1.31. It was first available in the v1.27 release.
Ви можете масштабувати Indexed Jobs вгору або вниз, змінюючи як .spec.parallelism, так і .spec.completions разом, так щоб .spec.parallelism == .spec.completions. Під час масштабування вниз Kubernetes видаляє Podʼи з вищими індексами.
Сценарії використання еластичних Indexed Jobs включають пакетні робочі навантаження, які вимагають масштабування Indexed Job, такі як завдання навчання MPI, Horovod, Ray та PyTorch.
Примітка:
Коли функціональна можливість WorkloadWithJob увімкнена і Job використовує групове планування, розмір групи слідує за змінним schedulingPolicy.gang.minCount (або .spec.parallelism, коли minCount не встановлено). Ви можете масштабувати групу одним із двох способів:
встановити .spec.scheduling.schedulingPolicy.gang.minCount безпосередньо, або
змінити .spec.parallelism, коли minCount не встановлено.
При будь-якій зміні контролер перекомпілює Workload та повторно синхронізує розмір PodGroup, масштабуючи групу на місці без перестворення Job. Оновлення застосовуються лише до Podʼів, які оцінюються в майбутніх циклах планування, і не впливають на вже заплановані Podʼи. gang.minCount, більше за .spec.parallelism, відхиляється, оскільки така група ніколи не може бути задоволена.
Відкладене створення Podʼів-замінників
СТАН ФУНКЦІОНАЛУ:GA since Kubernetes v1.34
More information about this feature
This is a stable feature in Kubernetes, and has been since version v1.34. It was first available in the v1.28 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate JobPodReplacementPolicy, Kubernetes ignores it but does not report any error.
Типово контролер Job створює Podʼи заново, щойно вони зазнають збою або почнуть завершуватися (матимуть відмітку видалення). Це означає, що в певний момент часу, коли деякі з Podʼів завершуються, кількість запущених Podʼів для Job може бути більшою, ніж parallelism або більше, ніж один Pod на індекс (якщо ви використовуєте Indexed Job).
Ви можете створювати Podʼи-замінники лише тоді, коли Podʼи, які знаходяться в стані завершення, повністю завершені (мають status.phase: Failed). Для цього встановіть .spec.podReplacementPolicy: Failed. Типова політика заміни залежить від того, чи Job має встановлену політику збоїв Podʼа. Якщо для Job не визначено політику збоїв Podʼа, відсутність поля podReplacementPolicy вибирає політику заміни TerminatingOrFailed: панель управління створює Podʼи-замінники негайно після видалення Podʼів (як тільки панель управління бачить, що Pod для цього Job має встановлене значення deletionTimestamp). Для Jobs із встановленою політикою збоїв Podʼа стандартне значення podReplacementPolicy — це Failed, інших значень не передбачено. Докладніше про політики збоїв Podʼа для Jobs можна дізнатися у розділі Політика збоїв Podʼа.
При увімкненій функціональній можливості у вашому кластері ви можете перевірити поле .status.terminating Job. Значення цього поля — це кількість Podʼів, якими володіє Job, які зараз перебувають у стані завершення.
kubectl get jobs/myjob -o yaml
apiVersion:batch/v1kind:Job# .metadata та .spec опущеноstatus:terminating:3# три Podʼи, які перебувають у стані завершення і ще не досягли стану Failed
Делегування керування обʼєктом Job зовнішньому контролеру
СТАН ФУНКЦІОНАЛУ:GA since Kubernetes v1.35; (стандартно увімкнено)
More information about this feature
This is a stable feature in Kubernetes, and has been since version 1.35. It was first available in the v1.30 release.
Ця функція дозволяє вам вимкнути вбудований контролер Job для конкретного Job і делегувати узгодження цього Job зовнішньому контролеру.
Ви вказуєте контролер, який узгоджує Job, встановлюючи власне значення для поля spec.managedBy — будь-яке значення окрім kubernetes.io/job-controller. Значення поля є незмінним.
Примітка:
Під час використання цієї функції переконайтеся, що контролер, вказаний у полі, встановлено, інакше Job може бути не узгоджений взагалі.
Примітка:
При розробці зовнішнього контролера Job, будьте уважні: ваш контролер повинен працювати відповідно до визначень специфікації API та полів статусу обʼєкта Job.
Докладно ознайомтесь з ними в API Job. Ми також рекомендуємо запустити наскрізні тести сумісності для обʼєкта Job, щоб перевірити вашу реалізацію.
Нарешті, при розробці зовнішнього контролера Job переконайтеся, що він не використовує завершувач batch.kubernetes.io/job-tracking, зарезервований для вбудованого контролера.
Альтернативи
Окремі Podʼи
Коли вузол, на якому працює Pod, перезавантажується або виходить з ладу, Pod завершується і не буде перезапущений. Однак Job створить нові Podʼи для заміни завершених. З цієї причини ми рекомендуємо використовувати Job замість окремого Podʼа, навіть якщо ваш застосунок вимагає тільки одного Podʼа.
Replication Controller
Jobs доповнюють Replication Controllers. Replication Controller керує Podʼами, завершення яких не очікується (наприклад, вебсервери), а Job керує Podʼами, завершення яких очікується (наприклад, пакетні завдання).
Як зазначено в розділі Життєвий цикл Podʼа, Job придатний лише для Podʼів з RestartPolicy, рівним OnFailure або Never.
Примітка:
Якщо RestartPolicy не встановлено, стандартне значення — Always.
Один Job запускає контролер Podʼів
Ще один патерн: один Job створює Pod, який своєю чергою створює інші Podʼи, виступаючи як свого роду власний контролер для цих Podʼів. Це дає найбільшу гнучкість, але може бути дещо складним для початку використання та пропонує меншу інтеграцію з Kubernetes.
Перевагою цього підходу є те, що загальний процес отримує гарантію завершення обʼєкта Job, але при цьому повністю контролюється те, які Podʼи створюються і як їм призначається робота.
Перейдіть за посиланнями в розділі Автоматичне очищення завершених Jobs, щоб дізнатися більше про те, як ваш кластер може очищати завершені та/або невдалі завдання.
Job є частиною REST API Kubernetes. Ознайомтесь з визначенням обʼєкта
Job, щоб зрозуміти API для Jobs.
Прочитайте про CronJob, який ви можете використовувати для визначення серії Jobs, які виконуватимуться за розкладом, подібно до інструмента UNIX cron.
Попрактикуйтесь в налаштуванні обробки відновлюваних і невідновлюваних збоїв Podʼів за допомогою podFailurePolicy на основі покрокових прикладів.
Дізнайтеся про групове планування
для планування паралельних Jobs за принципом "все або нічого".
6 - Автоматичне очищення завершених Jobs
Механізм часу життя (TTL) для очищення старих Jobs, які завершили виконання.
СТАН ФУНКЦІОНАЛУ:GA since Kubernetes v1.23
Коли ваш Job завершився, корисно залишити цей Job в API (і не видаляти його відразу), щоб ви могли визначити, успішно він виконався чи зазнав невдачі.
Контролер TTL-after-finished у Kubernetes забезпечує механізм TTL (time to live), щоб обмежити час життя обʼєктів Job, які завершили виконання.
Очищення завершених Jobs
Контролер TTL-after-finished підтримується лише для Jobs. Ви можете використовувати цей механізм для автоматичного очищення завершених Jobs (як Complete, так і Failed), вказавши поле .spec.ttlSecondsAfterFinished Job, як у цьому прикладі.
Контролер TTL-after-finished вважає, що Job можна очистити через TTL секунд після його завершення. Відлік починається, коли умова статусу Job змінюється, показуючи, що Job є або Complete, або Failed; щойно TTL закінчується, цей Job стає придатним для каскадного видалення. Коли контролер TTL-after-finished очищає Job, він видаляє його каскадно, тобто разом із залежними обʼєктами.
Kubernetes дотримується гарантій життєвого циклу обʼєкта для Job, таких як очікування завершувачів.
Ви можете встановити TTL секунд у будь-який момент. Ось деякі приклади встановлення поля .spec.ttlSecondsAfterFinished Job:
Вкажіть це поле в маніфесті Job, щоб Job можна було автоматично очистити через певний час після його завершення.
Вручну встановіть це поле для наявних, уже завершених Jobs, щоб вони стали придатними для очищення.
Використовуйте змінювальний вебхук допуску для динамічного встановлення цього поля під час створення Job. Адміністратори кластера можуть використовувати це, щоб застосовувати політику TTL для завершених Jobs.
Використовуйте змінювальний вебхук допуску для динамічного встановлення цього поля після завершення Job та вибору різних значень TTL на основі статусу Job і міток. У цьому випадку вебхук повинен виявляти зміни в полі .status Job і встановлювати TTL лише тоді, коли Job позначається як завершений.
Напишіть власний контролер для керування TTL очищення для Jobs, які відповідають певному селектору.
Застереження
Оновлення TTL для завершених Jobs
Ви можете змінювати період TTL, наприклад, поле .spec.ttlSecondsAfterFinished Jobs, після створення або завершення Job. Якщо ви збільшуєте період TTL після закінчення наявного періоду ttlSecondsAfterFinished, Kubernetes не гарантує збереження цього Job, навіть якщо оновлення для збільшення TTL повертає успішну відповідь API.
Зсув часу
Оскільки контролер TTL-after-finished використовує мітки часу, збережені в Jobs Kubernetes, для визначення того, чи минув TTL, ця функція чутлива до зсуву часу в кластері, через що панель управління може очистити обʼєкти Job у неправильний час.
Годинники не завжди точні, але різниця повинна бути дуже малою. Майте на увазі цей ризик під час встановлення ненульового TTL.
CronJob призначений для виконання регулярних запланованих дій, таких як резервне копіювання, генерація звітів та інше. Один обʼєкт CronJob подібний до одного рядка файлу crontab (таблиця cron) у системі Unix. Він запускає Job періодично за заданим розкладом, записаним у форматі Cron.
У CronJob є обмеження та особливості. Наприклад, за певних обставин один CronJob може створювати кілька одночасних Jobs. Див. обмеження нижче.
Коли панель управління створює нові Jobs і (опосередковано) Podʼи для CronJob, .metadata.name CronJob є частиною основи для назв цих Podʼів. Назва CronJob повинна бути дійсним значенням DNS-піддомену, але це може призводити до неочікуваних результатів для імен хостів Podʼів. Для найкращої сумісності назва повинна відповідати суворішим правилам DNS-мітки. Навіть коли назва є DNS-піддоменом, вона не повинна бути довшою за 52 символи. Це тому, що контролер CronJob автоматично додає 11 символів до наданої вами назви, а довжина назви Job не повинна перевищувати 63 символи.
Приклад
Цей приклад маніфесту CronJob виводить поточний час та вітальне повідомлення щохвилини:
Наприклад, 0 3 * * 1 означає, що це завдання планується запускати щотижня в понеділок о 3 ранку.
Формат також включає розширені значення кроків "Vixie cron". Як пояснено в документації FreeBSD:
Значення кроків можна використовувати разом із діапазонами. Якщо після діапазону вказати /<number>, це задає крок із таким значенням у межах діапазону. Наприклад, 0-23/2 можна використовувати в полі годин для вказування виконання команди кожну другу годину (альтернативою в стандарті V7 є 0,2,4,6,8,10,12,14,16,18,20,22). Після зірочки також допускаються кроки, тому, якщо ви хочете сказати "кожні дві години", просто використовуйте */2.
Примітка:
Знак питання (?) у розкладі має той самий зміст, що й зірочка *, тобто позначає будь-яке доступне значення для даного поля.
Окрім стандартного синтаксису, також можна використовувати деякі макроси, такі як @monthly:
Запис
Опис
Еквівалентно
@yearly (або @annually)
Виконувати один раз на рік о півночі 1 січня
0 0 1 1 *
@monthly
Виконувати один раз на місяць о півночі першого дня місяця
0 0 1 * *
@weekly
Виконувати один раз на тиждень о півночі в неділю
0 0 * * 0
@daily (або @midnight)
Виконувати один раз на день о півночі
0 0 * * *
@hourly
Виконувати один раз на годину на початку години
0 * * * *
Для генерації виразів розкладу CronJob можна також використовувати вебінструменти, наприклад crontab.guru.
Шаблон Job
Поле .spec.jobTemplate визначає шаблон для Jobs, які створює CronJob, і воно обовʼязкове. Воно має точно таку саму схему, як Job, за винятком того, що воно вкладене і не має apiVersion або kind. Ви можете вказати спільні метадані для Jobs, створених за шаблоном, такі як мітки або анотації. Інформацію щодо написання .spec Job дивіться в розділі Написання специфікації Job.
Крайній термін для відкладеного запуску Job
Поле .spec.startingDeadlineSeconds є необовʼязковим. Це поле визначає крайній термін (у повних секундах) для запуску Job, якщо цей Job пропускає свій запланований час з будь-якої причини.
Після спливання крайнього терміну CronJob пропускає цей екземпляр Job (майбутні запуски все ще плануються). Наприклад, якщо у вас є Job резервного копіювання, який запускається двічі на день, ви можете дозволити йому запускатися із запізненням до 8 годин, але не пізніше, оскільки резервна копія, зроблена пізніше, не буде корисною: ви б натомість воліли дочекатися наступного запланованого запуску.
Jobs, які пропускають налаштований крайній термін, Kubernetes вважає невдалими. Якщо ви не вказали startingDeadlineSeconds для CronJob, екземпляри Job не мають крайнього терміну.
Якщо поле .spec.startingDeadlineSeconds встановлено (не є null), контролер CronJob вимірює час між тим, коли очікується створення Job, і поточним моментом. Якщо різниця перевищує цю межу, він пропускає це виконання.
Наприклад, якщо воно встановлене на 200, це дозволяє створити Job протягом 200 секунд після фактичного часу за розкладом.
Політика паралелізму
Поле .spec.concurrencyPolicy також є необовʼязковим. Воно визначає, як обробляти паралельні виконання Job, який створюється цим CronJob. Специфікація може вказувати лише одну з таких політик паралелізму:
Allow (стандартно): CronJob дозволяє паралельні запуски Jobs
Forbid: CronJob не дозволяє паралельні запуски; якщо настав час для нового запуску Job і попередній запуск Job ще не завершився, CronJob пропускає новий запуск Job. Також зауважте, що коли попередній запуск Job завершиться, .spec.startingDeadlineSeconds все одно враховується і може призвести до нового запуску Job.
Replace: Якщо настав час для нового запуску Job і попередній запуск Job ще не завершився, CronJob замінює поточний запуск Job новим запуском Job.
Зверніть увагу, що політика паралелізму застосовується лише до Jobs, створених тим самим CronJob. Якщо є кілька CronJobs, їхні відповідні Jobs завжди можуть виконуватися паралельно.
Призупинення розкладу
Ви можете призупинити виконання Jobs для CronJob, встановивши необовʼязкове поле .spec.suspend в значення true. Стандартно поле має значення false.
Це налаштування не впливає на Jobs, які CronJob вже розпочав.
Якщо ви встановите це поле в значення true, всі наступні виконання будуть призупинені (вони залишаються запланованими, але контролер CronJob не запускає Jobs для виконання задач), доки ви не скасуєте призупинення CronJob.
Увага:
Виконання, які призупинені під час запланованого часу, вважаються пропущеними Jobs. Коли .spec.suspend змінюється з true на false для наявного CronJob без крайнього терміну запуску, пропущені Jobs плануються негайно.
Обмеження історії Jobs
Поля .spec.successfulJobsHistoryLimit та .spec.failedJobsHistoryLimit вказують, скільки успішних та невдалих Jobs потрібно зберігати. Обидва поля є необовʼязковими.
.spec.successfulJobsHistoryLimit: Це поле вказує кількість успішно завершених Jobs, які слід зберігати. Стандартне значення — 3. Якщо встановити це поле в 0, успішні Jobs не зберігатимуться.
.spec.failedJobsHistoryLimit: Це поле вказує кількість невдало завершених Jobs, які слід зберігати. Стандартне значення — 1. Якщо встановити це поле в 0, невдалі Jobs не зберігатимуться.
Для CronJobs без вказаного часового поясу kube-controller-manager інтерпретує розклади відносно свого локального часового поясу.
Ви можете вказати часовий пояс для CronJob, встановивши .spec.timeZone на назву дійсного часового поясу. Наприклад, встановлення .spec.timeZone: "Etc/UTC" вказує Kubernetes інтерпретувати розклад відносно всесвітнього координованого часу.
База даних часових поясів зі стандартної бібліотеки Go включена до бінарних файлів і використовується як запасний варіант, якщо зовнішня база даних недоступна в системі.
Обмеження CronJob
Непідтримувані специфікації часових поясів
Зазначення часового поясу за допомогою змінних CRON_TZ або TZ всередині .spec.scheduleофіційно не підтримується (і ніколи не підтримувалося). Якщо ви намагаєтеся встановити розклад, який включає вказування часового поясу TZ або CRON_TZ, Kubernetes не зможе створити чи оновити ресурс через помилку валідації. Натомість слід вказувати часові пояси, використовуючи поле часового поясу.
Зміна CronJob
За задумом CronJob містить шаблон для нових Jobs. Якщо ви змінюєте наявний CronJob, зміни застосовуватимуться до нових Jobs, які почнуть виконуватися після завершення вашої зміни. Jobs (та їхні Podʼи), які вже почали виконуватися, продовжують працювати без змін. Тобто CronJob не оновлює наявні Jobs, навіть якщо вони ще виконуються.
Створення Job
CronJob створює обʼєкт Job приблизно один раз за час виконання свого розкладу. Планування є приблизним, оскільки за певних обставин може бути створено два Jobs або жодного. Kubernetes намагається уникати таких ситуацій, але не повністю запобігає їм. Тому Jobs, які ви визначаєте, повинні бути ідемпотентними.
Починаючи з Kubernetes v1.32, CronJobs застосовують анотацію batch.kubernetes.io/cronjob-scheduled-timestamp до створених ними Jobs. Ця анотація вказує початковий запланований час створення Job і має формат RFC3339.
Якщо startingDeadlineSeconds встановлено на велике значення або залишено не встановленим (типово), і якщо concurrencyPolicy встановлено на Allow, Jobs завжди запускатимуться принаймні один раз.
Увага:
Якщо startingDeadlineSeconds встановлено у значення менше ніж 10 секунд, CronJob може не бути заплановано. Це повʼязано з тим, що контролер CronJob виконує перевірки кожні 10 секунд.
Для кожного CronJob контролер CronJob перевіряє, скільки розкладів він пропустив протягом часу від його останнього запланованого часу до теперішнього часу. Якщо пропущено понад 100 розкладів, то він не запускає Job і записує помилку в лог.
too many missed start times. Set or decrease .spec.startingDeadlineSeconds or check clock skew
Ця поведінка застосовується для планування наздоганяння і не означає, що CronJob припинить роботу.
Наприклад, під час використання concurrencyPolicy: Forbid довготривалі Jobs можуть призвести до пропуску запланованих часів, але новий Job може бути створений після завершення попереднього Job.
Важливо відзначити, що якщо поле startingDeadlineSeconds встановлено (не є nil), контролер підраховує, скільки пропущених Jobs сталося від значення startingDeadlineSeconds до теперішнього часу, а не від останнього запланованого часу до теперішнього часу. Наприклад, якщо startingDeadlineSeconds дорівнює 200, контролер підраховує, скільки Jobs було пропущено за останні 200 секунд.
CronJob вважається пропущеним, якщо не вдалося створити Job в запланований час. Наприклад, якщо concurrencyPolicy встановлено на Forbid і CronJob було спробовано запланувати, коли попередній Job все ще працював, то це враховуватиметься як пропуск.
Наприклад, припустимо, що CronJob встановлено для запуску нового Job кожну хвилину, починаючи з 08:30:00, і його поле startingDeadlineSeconds не встановлено. Якщо контролер CronJob виявиться недоступним з 08:29:00 по 10:21:00, Job не буде запущено, оскільки кількість пропущених Jobs, які пропустили свій розклад, понад 100.
Щоб краще проілюструвати цю концепцію, припустимо, що CronJob встановлено для запуску нового Job кожну хвилину, починаючи з 08:30:00, і його поле startingDeadlineSeconds встановлено на 200 секунд. Якщо контролер CronJob виявиться недоступним протягом того самого періоду, що й у попередньому прикладі (08:29:00 до 10:21:00), Job все одно запуститься о 10:22:00. Це трапляється тому, що тепер контролер перевіряє, скільки пропущених розкладів сталося за останні 200 секунд (тобто 3 пропущені розклади), а не від останнього запланованого часу до теперішнього часу.
CronJob відповідає лише за створення Job, які відповідають його розкладу, а Job, зі свого боку, відповідає за керування Podʼами, які він представляє.
Що далі
Дізнайтесь про Podʼи та Jobs, дві концепції, на які спираються CronJobs.
Дізнайтеся більше про формат поля .spec.schedule в CronJob.
CronJob є частиною REST API Kubernetes. Дивіться довідку
CronJob API для отримання докладних деталей.
8 - ReplicationController
Застарілий API для керування робочими навантаженнями, які можуть горизонтально масштабуватися. Замінено API Deployment та ReplicaSet.
Примітка:
Deployment, який налаштовує ReplicaSet, тепер є рекомендованим способом налаштування реплікації.
ReplicationController гарантує, що завжди запущено зазначену кількість реплік Podʼів. Іншими словами, ReplicationController гарантує, що Pod або однорідний набір Podʼів завжди працює та доступний.
Як працює ReplicationController
Якщо є занадто багато Podʼів, ReplicationController завершує зайві Podʼи. Якщо Podʼів замало, ReplicationController запускає додаткові. На відміну від вручну створених Podʼів, Podʼи, якими керує ReplicationController, автоматично замінюються, якщо вони зазнають збою, видаляються або завершуються. Наприклад, ваші Podʼи створюються на вузлі заново після обслуговування з порушенням роботи, такого як оновлення ядра. З цієї причини ви повинні використовувати ReplicationController, навіть якщо ваш застосунок вимагає лише одного Podʼа. ReplicationController схожий на наглядача процесів, але замість того, щоб наглядати за окремими процесами на одному вузлі, ReplicationController наглядає за кількома Podʼами на різних вузлах.
ReplicationController часто скорочується до "rc" в обговореннях та як скорочення в командах kubectl.
Простим випадком є створення одного обʼєкта ReplicationController для надійного запуску одного екземпляра Podʼа протягом необмеженого часу. Складніший випадок — це запуск кількох ідентичних реплік реплікованого сервісу, наприклад, вебсерверів.
Запуск прикладу ReplicationController
Цей приклад конфігурації ReplicationController запускає три копії вебсервера nginx.
Щоб перелічити всі Podʼи, які належать ReplicationController у формі, придатній для машинного читання, можна використовувати команду на зразок:
pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})echo$pods
Вивід подібний до такого:
nginx-3ntk0 nginx-4ok8v nginx-qrm3m
Тут селектор такий самий, як і селектор для ReplicationController (бачимо у виводі kubectl describe), і в іншій формі у replication.yaml. Опція --output=jsonpath вказує вираз із назвою кожного Podʼа в отриманому списку.
Створення маніфесту ReplicationController
Як і з усіма іншими конфігураціями Kubernetes, для ReplicationController потрібні поля apiVersion, kind і metadata.
Коли панель управління створює нові Podʼи для ReplicationController, .metadata.name ReplicationController є частиною основи для назв цих Podʼів. Назва ReplicationController повинна бути дійсним значенням DNS-піддомену, але це може призводити до неочікуваних результатів для імен хостів Podʼів. Для забезпечення найкращої сумісності назва повинна відповідати суворішим правилам для DNS-мітки.
Для загальної інформації про роботу з файлами конфігурації дивіться управління обʼєктами.
ReplicationController також потребує розділу .spec.
Шаблон Podʼа
.spec.template — єдине обовʼязкове поле в розділі .spec.
.spec.template — це шаблон Podʼа. Він має точно таку саму схему, як і Pod, за винятком того, що він вкладений і не має apiVersion або kind.
Окрім обовʼязкових полів для Podʼа, шаблон Podʼа в ReplicationController повинен вказувати відповідні мітки та відповідну політику перезапуску. Щодо міток, переконайтеся, що вони не перекриваються з іншими контролерами. Див. селектор Podʼа.
Для локальних перезапусків контейнерів ReplicationControllers делегують агентові на вузлі, наприклад, Kubelet.
Мітки на ReplicationController
ReplicationController може мати власні мітки (.metadata.labels). Зазвичай ви встановлюєте їх так само, як і .spec.template.metadata.labels; якщо .metadata.labels не вказано, то вони стандартно встановлюються як .spec.template.metadata.labels. Однак вони можуть бути різними, і .metadata.labels не впливають на поведінку ReplicationController.
Селектор Podʼа
Поле .spec.selector є селектором міток. ReplicationController керує всіма Podʼами з мітками, які відповідають селектору. Він не робить різниці між Podʼами, які він створив чи видалив, і Podʼами, які створив чи видалив інший процес чи особа. Це дозволяє замінити ReplicationController без впливу на запущені Podʼи.
Якщо вказано, то .spec.template.metadata.labels повинні дорівнювати .spec.selector, інакше їх відхилить API. Якщо .spec.selector не вказано, він буде встановлений типово як .spec.template.metadata.labels.
Також, як правило, ви не повинні створювати жодних Podʼів, мітки яких відповідають цьому селектору, безпосередньо, з іншим ReplicationController або з іншим контролером, таким як Job. Якщо ви це зробите, то ReplicationController вважатиме, що він створив інші Podʼи. Kubernetes не забороняє вам це робити.
Якщо у вас все-таки виникає кілька контролерів із селекторами, що перетинаються, вам доведеться керувати видаленням самостійно (див. нижче).
Кілька реплік
Ви можете вказати, скільки Podʼів повинно працювати одночасно, встановивши .spec.replicas рівним кількості Podʼів, які ви хочете мати одночасно. Кількість, що працює в будь-який момент, може бути більшою або меншою, наприклад, якщо репліки тільки що були збільшені або зменшені, чи якщо Pod коректно зупинено, а його заміна запускається раніше.
Якщо ви не вказали .spec.replicas, то типово встановлюється 1.
Робота з ReplicationControllers
Видалення ReplicationController та його Podʼів
Щоб видалити ReplicationController та всі його Podʼи, використовуйте команду kubectl delete. Kubectl масштабує ReplicationController до нуля і чекає, доки кожний Pod буде видалено, перед видаленням самого ReplicationController. Якщо цю команду kubectl перервати, її можна перезапустити.
Під час використання REST API або бібліотеки клієнта вам потрібно виконати кроки явно (масштабування реплік до 0, очікування видалення Podʼів, а потім видалення самого ReplicationController).
Видалення лише ReplicationController
Ви можете видалити ReplicationController, не впливаючи на його Podʼи.
Під час використання kubectl вкажіть опцію --cascade=orphan команді kubectl delete.
Під час використання REST API або бібліотеки клієнта ви можете видалити обʼєкт ReplicationController.
Після видалення оригіналу ви можете створити новий ReplicationController, щоб замінити його. Поки старий та новий .spec.selector однакові, новий перейме старі Podʼи. Однак він не буде вживати жодних зусиль, щоб наявні Podʼи відповідали новому, відмінному від оригінального, шаблону Podʼа. Щоб оновити Podʼи за новою специфікацією у керований спосіб, використовуйте поетапне оновлення.
Ізолювання Podʼів від ReplicationController
Podʼи можуть бути вилучені із цільового набору ReplicationController зміною їхніх міток. Цей метод може бути використаний для виведення Podʼів з обслуговування для налагодження та відновлення даних. Podʼи, вилучені цим способом, будуть автоматично замінені (за умови, що кількість реплік також не змінюється).
Поширені шаблони використання
Перепланування
Як було зазначено вище, чи у вас є 1 Pod, який вам потрібно тримати в роботі, чи 1000, ReplicationController гарантує, що зазначена кількість Podʼів існує, навіть у випадку відмови вузла або завершення Podʼа (наприклад, через дію іншого агента управління).
Масштабування
ReplicationController дозволяє масштабувати кількість реплік вгору або вниз, як вручну, так і за допомогою агента автомасштабування, оновлюючи поле replicas.
Поетапні оновлення
ReplicationController призначений для полегшення поетапного оновлення сервісу за допомогою заміни Podʼів один за одним.
Як пояснено в #1353, рекомендований підхід — створити новий ReplicationController з 1 реплікою, масштабувати нові (+1) та старі (-1) контролери по одному, а потім видалити старий контролер після досягнення 0 реплік. Це передбачувано оновлює набір Podʼів незалежно від неочікуваних відмов.
В ідеалі контролер поетапного оновлення мав би враховувати готовність застосунку і гарантувати, що достатня кількість Podʼів у будь-який момент продуктивно обслуговує запити.
Обом ReplicationControllers потрібно створювати Podʼи із принаймні однією відмінною міткою, такою як теґ образу основного контейнера Podʼа, оскільки саме оновлення образів зазвичай спонукають до поетапних оновлень.
Кілька каналів випуску
Окрім запуску кількох випусків застосунку під час поетапного оновлення, часто запускають кілька випусків протягом тривалого часу або навіть постійно, використовуючи кілька каналів випуску. Канали розрізняються за допомогою міток.
Наприклад, сервіс може охоплювати всі Podʼи з tier in (frontend), environment in (prod). Тепер скажімо, у вас є 10 реплікованих Podʼів, які складають цей рівень. Але ви хочете мати можливість випробувати нову версію цього компонента як канарку (canary). Ви можете налаштувати ReplicationController із replicas, встановленим на 9 для більшості реплік, з мітками tier=frontend, environment=prod, track=stable, та інший ReplicationController із replicas, встановленим на 1 для канарки, з мітками tier=frontend, environment=prod, track=canary. Тепер сервіс охоплює як канаркові, так і не канаркові Podʼи. Але ви можете окремо працювати з ReplicationControllers, щоб щось перевіряти, відстежувати результати тощо.
Використання ReplicationControllers із Services
Кілька ReplicationControllers можуть працювати за одним сервісом, так що, наприклад, частина трафіку іде до старої версії, а частина до нової.
ReplicationController ніколи не завершиться самостійно, але не очікується, що він житиме так довго, як сервіси. Сервіси можуть складатися з Podʼів, контрольованих кількома ReplicationControllers, і передбачається, що протягом життя сервісу (наприклад, для виконання оновлення Podʼів, які забезпечують роботу сервісу) буде створено і знищено багато ReplicationControllers. І самі сервіси, і їхні клієнти не повинні нічого знати про ReplicationControllers, які підтримують Podʼи цих сервісів.
Написання програм для реплікації
Podʼи, створені ReplicationController, призначені бути взаємозамінними та семантично ідентичними, хоча їхні конфігурації з часом можуть ставати неоднорідними. Це очевидно підходить для реплікованих stateless-серверів, але ReplicationControllers також можна використовувати для забезпечення доступності застосунків із вибором master, шардованих застосунків і застосунків із пулом робочих процесів. Такі застосунки повинні використовувати механізми динамічного призначення роботи, такі як черги роботи RabbitMQ, на відміну від статичного / одноразового налаштування конфігурації кожного Podʼа, що вважається антипатерном. Будь-яке налаштування Podʼа, таке як вертикальне автоматичне визначення розміру ресурсів (наприклад, CPU чи памʼяті), повинно виконуватися іншим онлайн-процесом контролера, подібним до самого ReplicationController.
Обовʼязки ReplicationController
ReplicationController гарантує, що бажана кількість Podʼів відповідає його селектору міток і працює. Наразі з його підрахунку виключаються лише завершені Podʼи. У майбутньому можливо буде враховувати інформацію про готовність та інші дані, доступні від системи, можливо буде додано більше елементів керування політикою заміни, і планується генерація подій, які можуть використовуватися зовнішніми клієнтами для впровадження як завгодно складних політик заміни та / або зменшення масштабу.
ReplicationController назавжди обмежений цією вузькою відповідальністю. Він сам не виконуватиме проби готовності чи життєздатності. Замість автоматичного масштабування він призначений для управління зовнішнім автомасштабувальником (як обговорюється в #492), який буде змінювати його поле replicas. Ми не будемо додавати політик планування (наприклад, розподілення) до ReplicationController. Він також не повинен перевіряти, чи відповідають контрольовані Podʼи поточному зазначеному шаблону, оскільки це заважало б автоматичному визначенню розміру та іншим автоматизованим процесам. Так само крайні терміни завершення, залежності порядку, розширення конфігурації та інші функції мають бути в інших місцях. Навіть планується виділити механізм масового створення Podʼів (#170).
ReplicationController призначений бути компонованим базовим примітивом. Ми очікуємо, що на його основі та на основі інших доповнювальних примітивів у майбутньому буде побудовано високорівневі API та / або інструменти для зручності користувачів. "Макро" операції, які наразі підтримуються kubectl (run, scale), є прикладами перевірки цієї концепції. Наприклад, можемо уявити щось на зразок Asgard, що управляє ReplicationControllers, автомасштабувальниками, сервісами, політиками планування, канарковими розгортаннями та іншими аспектами.
Обʼєкт API
ReplicationController є ресурсом верхнього рівня в REST API Kubernetes. Докладніша інформація про обʼєкт API є за посиланням: Обʼєкт API ReplicationController.
Альтернативи ReplicationController
ReplicaSet
ReplicaSet — це ReplicationController нового покоління, який підтримує новий селектор міток на основі множини. Він використовується головним чином Deployment як механізм для оркестрування створення, видалення та оновлення Podʼів. Зауважте, що ми рекомендуємо використовувати Deployments замість безпосереднього використання ReplicaSets, хіба що вам потрібне власне оркестрування оновлень або оновлення взагалі не потрібні.
Deployment (Рекомендовано)
Deployment — це обʼєкт API вищого рівня, який оновлює свої базові ReplicaSets та їхні Podʼи. Deployments рекомендуються, якщо вам потрібна функціональність поетапного оновлення, оскільки вони є декларативними, виконуються на сервері та мають додаткові функції.
Окремі Podʼи
На відміну від випадку, коли користувач створює Podʼи безпосередньо, ReplicationController замінює Podʼи, які видаляються або завершуються з будь-якої причини, такої як відмова вузла або обслуговування вузла з порушенням роботи, наприклад, оновлення ядра. З цієї причини ми рекомендуємо використовувати ReplicationController, навіть якщо ваш застосунок вимагає лише одного Podʼа. Вважайте це подібним наглядачу процесів, тільки він наглядає за кількома Podʼами на кількох вузлах, а не за окремими процесами на одному вузлі. ReplicationController делегує локальні перезапуски контейнерів деякому агенту на вузлі, наприклад kubelet.
Job
Використовуйте Job замість ReplicationController для Podʼів, які мають завершуватись самі по собі (іншими словами, пакетні завдання).
DaemonSet
Використовуйте DaemonSet замість ReplicationController для Podʼів, які забезпечують функцію рівня машини, таку як моніторинг машини або логування машини. Ці Podʼи мають термін служби, який повʼязаний із терміном служби машини: Pod повинен працювати на машині перед тим, як інші Podʼи почнуть працювати, і може бути безпечно завершений, коли машина готова до перезавантаження або вимкнення.
Дізнайтеся більше про Deployment, альтернативу ReplicationController.
ReplicationController — це частина REST API Kubernetes. Ознайомтесь з визначенням обʼєкта
ReplicationController, щоб зрозуміти API для контролерів реплікації.