StatefulSet — це обʼєкт API робочого навантаження, який використовується для керування застосунками зі збереженням стану.
StatefulSet керує розгортанням і масштабуванням групи Podʼів, і забезпечує гарантії щодо порядку та унікальності цих Podʼів.
Як і Deployment, StatefulSet керує Podʼами, які базуються на ідентичній специфікації контейнерів. На відміну від Deployment, StatefulSet зберігає постійну ідентичність для кожного свого Podʼа. Ці Podʼи створюються за однаковою специфікацією, але не є взаємозамінними: у кожного є постійний ідентифікатор, який він зберігає під час будь-якого перепланування.
Якщо ви хочете використовувати томи для забезпечення постійності вашого робочого навантаження, ви можете використовувати StatefulSet як частину рішення. Хоча окремі Podʼи в StatefulSet можуть вийти з ладу, постійні ідентифікатори Podʼів полегшують зіставлення наявних томів із новими Podʼами, які замінюють ті, що вийшли з ладу.
StatefulSets є цінним інструментом для застосунків, які потребують одного або кількох із таких елементів:
Тут «стабільний» означає збереження під час (пере)планування Podʼів. Якщо застосунок не потребує стабільних ідентифікаторів або упорядкованого розгортання, видалення чи масштабування, вам слід розгортати його за допомогою обʼєкта робочого навантаження, який забезпечує набір реплік без збереження стану (stateless). Deployment або ReplicaSet можуть краще підійти для ваших stateless-потреб.
OrderedReady) можна потрапити в несправний стан, який вимагає ручного втручання для виправлення.Наведений нижче приклад демонструє компоненти StatefulSet.
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
minReadySeconds: 10 # by default is 0
template:
metadata:
labels:
app: nginx # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: registry.k8s.io/nginx-slim:0.24
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "my-storage-class"
resources:
requests:
storage: 1Gi
ReadWriteOnce для простоти. Для промислового використання проєкт Kubernetes рекомендує натомість використовувати режим доступу ReadWriteOncePod.У вищенаведеному прикладі:
nginx використовується для керування мережевим доменом.web має Spec, який вказує на те, що буде запущено 3 репліки контейнера nginx в унікальних Podʼах.volumeClaimTemplates забезпечуватиме стабільне сховище за допомогою PersistentVolumes, виділених PersistentVolume Provisioner.Назва обʼєкта StatefulSet повинна бути дійсною DNS-міткою.
Ви повинні встановити поле .spec.selector StatefulSet так, щоб воно збігалося з мітками його .spec.template.metadata.labels. Якщо не вказати відповідний селектор Podʼів, під час створення StatefulSet виникне помилка валідації.
Ви можете встановити поле .spec.volumeClaimTemplates, щоб створити PersistentVolumeClaim. Це забезпечить стабільне сховище для StatefulSet, якщо:
.spec.minReadySeconds є необовʼязковим полем, яке вказує мінімальну кількість секунд, протягом яких новостворений Pod повинен працювати та бути готовим без збоїв будь-якого з його контейнерів, щоб вважатися доступним. Це використовується для перевірки прогресу розгортання під час використання стратегії поетапного оновлення. Це поле стандартно дорівнює 0 (Pod вважатиметься доступним одразу після готовності). Докладніше про те, коли Pod вважається готовим, див. Проби контейнера.
Podʼи StatefulSet мають унікальну ідентичність, яка складається з порядкового номера, стабільного мережевого ідентифікатора та стабільного сховища. Ця ідентичність залишається прикріпленою до Podʼа незалежно від того, на який вузол його (пере)заплановано.
Для StatefulSet з N реплік кожному Podʼу в StatefulSet буде призначено цілочисельний порядковий номер, унікальний у наборі. Стандартно Podʼам буде призначено порядкові номери від 0 до N-1. Контролер StatefulSet також додасть мітку Podʼа з цим індексом: apps.kubernetes.io/pod-index.
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ʼи негайно після їх створення, у вас є кілька варіантів:
Як зазначено в розділі Обмеження, ви відповідаєте за створення 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} |
Для кожного запису 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. Це слід робити вручну.
Коли контролер StatefulSet створює Pod, він додає мітку statefulset.kubernetes.io/pod-name, яка дорівнює назві Podʼа. Ця мітка дозволяє прикріплювати Service до конкретного Podʼа в StatefulSet.
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.
.spec.minReadySeconds, попередники повинні бути доступними (готовими принаймні протягом minReadySeconds).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.
StatefulSet дозволяє послабити його гарантії послідовності, зберігаючи при цьому його гарантії унікальності та ідентичності за допомогою поля .spec.podManagementPolicy.
OrderedReady є типовим значенням політики керування Podʼами для StatefulSet. Вона реалізує поведінку, описану в розділі Гарантії розгортання та масштабування.
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.RollingUpdateRollingUpdate реалізує автоматизовані поетапні оновлення для Podʼів у StatefulSet. Це значення є стандартною стратегією оновлення.RecreateTo use this feature, you (or a cluster administrator) will need to enable the StatefulSetRecreateStrategy feature gate for all relevant components in your cluster.
See Enable Or Disable Feature Gates for more information.
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ʼів, які можуть бути недоступні під час оновлення, вказавши поле .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ʼи, використовуючи відновлений шаблон.
To use this feature, you (or a cluster administrator) will need to enable the StatefulSetRecreateStrategy feature gate for all relevant components in your cluster.
See Enable Or Disable Feature Gates for more information.
Коли поле .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 для ведення історії ревізій, що дозволяє виконувати відкочування і відстежувати версії.
Коли ви оновлюєте шаблон Podʼа StatefulSet (spec.template), контролер StatefulSet:
Дивіться ControllerRevision, щоб дізнатися більше про ключові властивості та інші деталі.
Керуйте збереженими ревізіями за допомогою .spec.revisionHistoryLimit:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: webapp
spec:
revisionHistoryLimit: 5 # Зберігати останні 5 ревізій
# ... інші поля spec ...
Ви можете повернутися до попередньої конфігурації за допомогою:
# Переглянути історію ревізій
kubectl rollout history statefulset/webapp
# Відкотитися до певної ревізії
kubectl rollout undo statefulset/webapp --to-revision=3
Це:
Щоб переглянути повʼязані ControllerRevisions:
# Перелічити всі ревізії для StatefulSet
kubectl get controllerrevisions -l app.kubernetes.io/name=webapp
# Переглянути детальну конфігурацію конкретної ревізії
kubectl get controllerrevision/webapp-3 -o yaml
revisionHistoryLimit в діапазоні 5–10 для більшості робочих навантажень.Регулярно перевіряйте ревізії за допомогою:
kubectl get controllerrevisions
Налаштуйте сповіщення про швидке зростання кількості ревізій.
revisionHistoryLimit: 0 (вимикає можливість відкочування).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:
whenDeletedwhenScaledДля кожної політики, яку ви можете налаштувати, ви можете встановити значення Delete або Retain.
DeletevolumeClaimTemplate StatefulSet, видаляються для кожного Podʼа, на який впливає політика. З політикою whenDeleted всі PVC від volumeClaimTemplate видаляються після того, як їхні Podʼи були видалені. З політикою whenScaled видаляються лише PVC, що відповідають реплікам Podʼа, які прибираються під час зменшення масштабу, після того, як їхні Podʼи були видалені.Retain (стандартно)volumeClaimTemplate не змінюються, коли їх Pod видаляється. Це поведінка до цієї нової функції.Майте на увазі, що ці політики застосовуються лише тоді, коли Podʼи прибираються через видалення StatefulSet або зменшення його масштабу. Наприклад, якщо Pod, повʼязаний із StatefulSet, зазнає збою через відмову вузла, і панель управління створює Pod-замінник, StatefulSet зберігає наявний PVC. Наявний том не зазнає впливу, і кластер приєднає його до вузла, де має запуститися новий Pod.
Стандартно для політик встановлено Retain, відповідно до поведінки StatefulSet до цієї нової функції.
Ось приклад політики:
apiVersion: apps/v1
kind: StatefulSet
...
spec:
persistentVolumeClaimRetentionPolicy:
whenDeleted: Retain
whenScaled: Delete
...
Контролер 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.