Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# StatefulSet в Kubernetes
Определение
StatefulSet — это Kubernetes ресурс для управления приложениями, которым требуется:
- Уникальная идентичность для каждого pod'а
- Стабильное имя хоста и DNS
- Упорядоченное развертывание/удаление
- Persistent storage (постоянное хранилище)
- Состояние (stateful) — pod должен помнить кто он такой
Основные характеристики
StatefulSet vs Deployment
| Характеристика | StatefulSet | Deployment |
|---|---|---|
| Pod идентичность | Уникальная | Одноразовая |
| Имя pod'а | app-0, app-1, app-2 | app-xyz123, app-abc456 |
| Порядок развертывания | Последовательный (app-0 → app-1) | Параллельный |
| Storage | PersistentVolume требуется | Обычно ephemeral |
| Масштабирование | Медленнее | Быстрее |
| Использование | БД, кеши, очереди | Веб-сервисы, API |
Как StatefulSet работает
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql-cluster
spec:
serviceName: mysql # ВАЖНО! Headless Service для DNS
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-storage
mountPath: /var/lib/mysql
# ВАЖНО! Persistent storage для каждого pod'а
volumeClaimTemplates:
- metadata:
name: mysql-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
---
# Headless Service (без ClusterIP)
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
clusterIP: None # ← Headless!
selector:
app: mysql
ports:
- port: 3306
Идентичность pod'ов
Уникальное имя
# При создании StatefulSet с 3 репликами:
kubectl get pods
NAME READY STATUS
mysql-cluster-0 1/1 Running ← Индекс 0
mysql-cluster-1 1/1 Running ← Индекс 1
mysql-cluster-2 1/1 Running ← Индекс 2
# При удалении pod'а:
# kubectl delete pod mysql-cluster-1
# Kubernetes создаёт новый mysql-cluster-1 (ТОТ ЖЕ ИМЯ!)
# А не случайное имя
Stable DNS
Кажды pod получает stable DNS имя:
# Headless Service mysql с label selector app: mysql
# создаёт DNS записи:
mysql-cluster-0.mysql.default.svc.cluster.local
mysql-cluster-1.mysql.default.svc.cluster.local
mysql-cluster-2.mysql.default.svc.cluster.local
# Другие pod'ы могут обращаться:
mysql-cluster-1.mysql # Сокращённая форма в том же namespace
Упорядоченное развертывание
При масштабировании UP
kubectl scale statefulset mysql-cluster --replicas=5
# Развертывание последовательное:
Время: mysql-cluster-0 mysql-cluster-1 mysql-cluster-2 mysql-cluster-3 mysql-cluster-4
0s Running Running Running
10s Ready Ready Ready Creating
20s Ready Ready Ready Running
30s Ready Ready Ready Ready Creating
40s Ready Ready Ready Ready Running
При масштабировании DOWN
kubectl scale statefulset mysql-cluster --replicas=1
# Удаление в обратном порядке:
40s mysql-cluster-2 завершается
30s mysql-cluster-1 завершается
20s mysql-cluster-0 остаётся (Single replica)
Этот порядок критичен для приложений вроде консенсус-кластеров (Zookeeper, etcd, Elasticsearch).
Persistent Storage
volumeClaimTemplates
Создаёт отдельный PersistentVolume для каждого pod'а:
volumeclaimtemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
Результат:
kubectl get pvc
NAME STATUS VOLUME
data-mysql-0 Bound pvc-12345
data-mysql-1 Bound pvc-67890
data-mysql-2 Bound pvc-24680
# Каждый pod имеет собственный volume!
# Даже если pod удалится и пересоздастся, volume сохранится
Praktical Use Cases
1. Database Cluster (MySQL, PostgreSQL)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres-ha
spec:
serviceName: postgres
replicas: 3
# ...
volumeClaimTemplates:
- metadata:
name: postgres-storage
spec:
storageClassName: fast-ssd
resources:
requests:
storage: 100Gi
Почему: PostgreSQL нужна уникальная идентичность для репликации, stable DNS, и персистентное хранилище.
2. Message Queue (RabbitMQ, Kafka)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: kafka-cluster
spec:
serviceName: kafka
replicas: 3
# ...
Почему: Kafka брокеры должны иметь стабильные имена хостов для gossip протокола, и нужны local volumes для данных.
3. Search Engine (Elasticsearch)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: elasticsearch
spec:
serviceName: elasticsearch
replicas: 3
# ...
Почему: Nodes должны отслеживать свой индекс, плюс требуется large persistent storage.
4. In-Memory Cache (Redis Cluster)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-cluster
spec:
serviceName: redis
replicas: 6 # Minumum для cluster mode
# ...
Инициализация и управление состоянием
Init Container для setup
spec:
template:
spec:
initContainers:
- name: init-mysql
image: mysql:8.0
command:
- bash
- -c
- |
set -ex
ordinal=${HOSTNAME##*-} # Получаем индекс: 0, 1, 2
if [[ $ordinal -eq 0 ]]; then
# Это primary node
mysql --user=root --password=$MYSQL_ROOT_PASSWORD \
-e "SET GLOBAL server_id=$(( ordinal + 1 ));"
else
# Это replica node
mysql --user=root --password=$MYSQL_ROOT_PASSWORD \
-e "CHANGE MASTER TO MASTER_HOST='mysql-0.mysql.default', ..."
fi
Lifecycle Hooks
preStop для graceful shutdown
spec:
template:
spec:
containers:
- name: app
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 15"]
# Даёшь 15 сек на graceful shutdown перед force kill
Мониторинг StatefulSet'а
# Посмотреть статус
kubectl describe statefulset mysql-cluster
# Посмотреть pod'ы
kubectl get pods -l app=mysql
# Посмотреть PVC'и
kubectl get pvc
# Логи pod'а
kubectl logs mysql-cluster-0
# Exec в pod
kubectl exec -it mysql-cluster-0 -- bash
Важные различия от Deployment
# Deployment — для stateless приложений
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
# Любые pod'ы с одинаковой configuration
# Быстрое масштабирование
# Нет persistent storage
---
# StatefulSet — для stateful приложений
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres # ТРЕБУЕТСЯ!
replicas: 3
# Упорядоченные pod'ы (postgres-0, postgres-1, postgres-2)
# Медленное, но контролируемое масштабирование
# Требуется persistent storage
volumeClaimTemplates: [ ... ]
Итоговый ответ
StatefulSet — это Kubernetes ресурс для приложений, которым нужна идентичность и состояние:
- Уникальные имена pod'ов (app-0, app-1, app-2)
- Стабильные DNS имена
- Упорядоченное развертывание
- Persistent storage для каждого pod'а
Используй для баз данных, очередей, кешей, поисковых движков, а не для веб-сервисов (используй Deployment).