StatefulSet и headless Service
Четыре гарантии StatefulSet, per-pod DNS через clusterIP None и как volumeClaimTemplates выдаёт каждой реплике свой диск.
StatefulSet против Deployment
Deployment - контроллер, который держит заданное число одинаковых Pod. Pod - наименьшая единица, которую запускает Kubernetes. Под управлением Deployment Pod взаимозаменяемы. Один упал, контроллер поднял новый со случайным именем, и разницы нет. Это подходит для stateless-сервисов (без своего состояния и диска): nginx, REST API, фронтенд.
StatefulSet - контроллер для приложений, где у каждой реплики своя постоянная привязка. Это устойчивое имя, свой диск и своё сетевое имя. Он даёт четыре гарантии.
- Имена Pod фиксированные и нумерованные:
db-0,db-1. Номер называют ordinal index. - Старт по порядку:
db-1запускается только после готовностиdb-0. - У каждого Pod свой постоянный PVC. PVC - запрос на хранилище.
db-0всегда подключает свой диск,db-1тоже свой. - Устойчивое DNS-имя на каждый Pod.
Это нужно базам данных (Postgres, MySQL), очередям (Kafka) и координаторам (etcd).
Headless Service
Service - объект, который даёт группе Pod единый сетевой адрес. Обычный Service выдаёт один cluster IP и распределяет запросы между Pod. Какой именно Pod ответит, неважно.
StatefulSet требует обращаться к конкретному Pod. Для этого Service
делают headless (без единого cluster IP): задают clusterIP: None.
Тогда DNS вместо одного адреса Service возвращает адреса всех Pod по
отдельности.
db-0.db.<namespace>.svc.cluster.local
db-1.db.<namespace>.svc.cluster.local
Headless Service добавляет каждому Pod своё DNS-имя:
apiVersion: v1
kind: Service
metadata:
name: db
spec:
clusterIP: None
selector:
app: db
ports:
- port: 5432
protocol: TCP
Эти имена работают, только если в StatefulSet задано поле
serviceName со ссылкой на этот Service.
volumeClaimTemplates
volumeClaimTemplates - шаблон PVC для StatefulSet. Это не один общий
диск на всех. По шаблону каждой реплике создаётся свой PVC.
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
При replicas: 2 контроллер создаст два PVC. Имя PVC строится по
формуле <template-name>-<sts-name>-<ordinal>. Для шаблона data и
StatefulSet db это data-db-0 и data-db-1.
db-0 ─┬─ PVC data-db-0
└─ DNS db-0.db
db-1 ─┬─ PVC data-db-1
└─ DNS db-1.db
Том монтируется в контейнер по имени шаблона. volumeMounts.name: data
подключает PVC data-db-0 к Pod db-0.
Полный минимальный манифест
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: db
spec:
serviceName: db
replicas: 2
selector:
matchLabels:
app: db
template:
metadata:
labels:
app: db
spec:
containers:
- name: db
image: busybox:1.36
command: ["sh", "-c", "echo running; sleep 3600"]
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
Поле serviceName: db ссылается на headless Service. Без него
per-pod DNS не появится.
Поле selector.matchLabels должно совпадать с
template.metadata.labels. Если они расходятся, apply упадёт с ошибкой
selector does not match template labels.
Удаление Pod и удаление StatefulSet
Pod db-0 удалили: контроллер создаст его заново с тем же именем.
PVC data-db-0 остаётся отдельным объектом, и новый db-0 снова
смонтирует тот же диск. Данные на месте.
Весь StatefulSet удалили через kubectl delete sts db: PVC по
умолчанию не удаляются. Данные не теряются. Чтобы убрать тома,
PVC удаляют отдельно.
Поведение настраивается полем spec.persistentVolumeClaimRetentionPolicy
(стабильно с 1.32). В нём два ключа, whenDeleted и whenScaled, у
обоих значения Retain (умолчание) или Delete. При
whenScaled: Delete уменьшение реплик уносит PVC лишних Pod вместе с
ними.
Полезные команды
# Список объектов StatefulSet
kubectl get sts
# Подробно: serviceName, ordinals, PVC
kubectl describe sts db
# Проверка per-pod DNS из временного Pod
kubectl run dns-test --rm -it --image=busybox:1.36 -- nslookup db-0.db
# PVC, созданные по шаблону
kubectl get pvc
Домашка
Теорию закрепляет задание на своём кластере: 2 шага с проверкой. Кластер поднимается по треку Kubernetes локально, задания лежат в репозитории k8s-practice.
./run.sh start k8s-statefulset # развернуть стартовое состояние
./run.sh verify k8s-statefulset # проверить текущий шаг
Коротко
- StatefulSet даёт стабильные имена, порядок старта, персональный PVC и per-pod DNS.
- Per-pod DNS появляется только при headless Service
(
clusterIP: None) и заполненномserviceName. - Имена PVC строятся как
<template>-<sts>-<ordinal>, напримерdata-db-0. - Удаление Pod не трогает его PVC: новый Pod с тем же именем получит тот же диск.
- Удаление StatefulSet по умолчанию оставляет PVC; поведение меняет
persistentVolumeClaimRetentionPolicy.
Дрилл · вопросы как на собесе
Проверь себя без подсказок
Сформулируй ответ вслух или письменно, потом раскрой и честно отметь: знал или нет.
В чём разница между Deployment и StatefulSet?
K8S-014Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс