Deployment создаёт взаимозаменяемые Pod. Stateful-приложения требуют стабильного имени Pod, собственного хранилища для каждой реплики, предсказуемого порядка запуска. Другим workload-ам нужен один агент на каждом узле. Для этих задач — StatefulSet и DaemonSet.
[source: kubernetes.io/docs/concepts/workloads/controllers/statefulset/]
StatefulSet
StatefulSet управляет stateful-приложениями со стабильной идентичностью Pod и постоянным хранилищем.
Чем отличается от Deployment
Свойства StatefulSet
Стабильная сетевая идентичность:
- Pod именуются
<statefulset-name>-<ordinal>:postgres-0,postgres-1,postgres-2 - Каждый Pod получает стабильный DNS:
<pod-name>.<headless-service>.<namespace>.svc.cluster.local
Упорядоченное развёртывание:
- Pod создаются последовательно: pod-0 → pod-1 → pod-2
- Каждый следующий стартует только после готовности предыдущего (readinessProbe)
- При удалении — обратный порядок: pod-2 → pod-1 → pod-0
Стабильное хранилище:
volumeClaimTemplatesсоздают отдельный PVC для каждого Pod- При пересоздании Pod привязывается к тому же PVC — данные сохраняются
- При удалении Pod PVC не удаляются автоматически
Headless Service
StatefulSet требует Headless Service (clusterIP: None). Он не балансирует трафик — обеспечивает DNS-записи для каждого Pod напрямую.
apiVersion: v1
kind: Service
metadata:
name: postgres-headless
spec:
clusterIP: None
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
Манифест StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres-headless
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16
ports:
- containerPort: 5432
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: pg-secret
key: password
volumeMounts:
- name: pg-data
mountPath: /var/lib/postgresql/data
readinessProbe:
exec:
command:
- pg_isready
- -U
- postgres
initialDelaySeconds: 10
periodSeconds: 5
volumeClaimTemplates:
- metadata:
name: pg-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: fast-ssd
Результат:
- Pod:
postgres-0,postgres-1,postgres-2 - PVC:
pg-data-postgres-0,pg-data-postgres-1,pg-data-postgres-2 - DNS:
postgres-0.postgres-headless.default.svc.cluster.local
Масштабирование StatefulSet
# Масштабирование — последовательно
kubectl scale statefulset postgres --replicas=5
# Статус
kubectl get statefulsets
kubectl get sts
# Детали
kubectl describe sts postgres
# Удалить Pod (StatefulSet пересоздаст с тем же именем и PVC)
kubectl delete pod postgres-2
Типичные use cases для StatefulSet
- Базы данных: PostgreSQL, MySQL, MongoDB
- Очереди сообщений: Kafka, RabbitMQ
- Кеши с репликацией: Redis Sentinel/Cluster
- Распределённые хранилища: Elasticsearch, Cassandra, etcd
DaemonSet
DaemonSet гарантирует, что на каждом (или выбранном) узле кластера запущен ровно один экземпляр Pod.
[source: kubernetes.io/docs/concepts/workloads/controllers/daemonset/]
Поведение
- При добавлении нового узла — DaemonSet автоматически создаёт Pod на нём
- При удалении узла — Pod удаляется вместе с ним
- При удалении DaemonSet — удаляются все его Pod
Манифест DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
labels:
app: fluentd
spec:
selector:
matchLabels:
app: fluentd
template:
metadata:
labels:
app: fluentd
spec:
containers:
- name: fluentd
image: fluent/fluentd:v1.17
resources:
requests:
cpu: 100m
memory: 200Mi
limits:
cpu: 200m
memory: 400Mi
volumeMounts:
- name: varlog
mountPath: /var/log
readOnly: true
volumes:
- name: varlog
hostPath:
path: /var/log
Выбор узлов
По умолчанию DaemonSet запускает Pod на всех узлах. Для ограничения используются nodeSelector и tolerations:
spec:
template:
spec:
nodeSelector:
node-type: monitoring
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
tolerations позволяют запускать Pod на control plane узлах с taint NoSchedule по умолчанию.
Стратегии обновления DaemonSet
spec:
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
Типичные use cases для DaemonSet
- Сбор логов: Fluentd, Filebeat, Fluent Bit
- Мониторинг: Prometheus Node Exporter, Datadog Agent
- Сетевые плагины: Calico, Cilium, Weave
- Хранилища: Ceph, Longhorn агенты
Когда использовать
StatefulSet — стабильная идентичность Pod (имя, DNS) или собственное хранилище: БД, очереди, кластеризованные системы, важный порядок запуска/остановки.
DaemonSet — агент на каждом узле: логирование, мониторинг, сетевые агенты, storage agents.
Deployment — stateless, взаимозаменяемые Pod.
Типичные ошибки
StatefulSet без Headless Service. serviceName должен ссылаться на существующий Headless Service. Без него Pod создадутся, но DNS-записи для них — нет.
Удалить StatefulSet, ожидая удаления PVC. PVC не удаляются автоматически — это защита данных. Удаляй PVC вручную после StatefulSet.
Scale down ждёт по одному Pod. Идёт последовательно pod-2 → pod-1. Для Kafka, Cassandra убедись, что данные реплицированы перед уменьшением реплик.
DaemonSet без resource limits. Агент на каждом узле без limits может монополизировать ресурсы. Всегда задавай requests и limits.
DaemonSet вместо Deployment с nodeSelector. DaemonSet не позволяет задать replicas. Если нужно "N Pod на узлах с label X" — это Deployment с nodeSelector + HPA.
Альтернативы
Helm charts для stateful приложений (Bitnami charts для PostgreSQL, Redis, Kafka) — production-ready StatefulSet с probes, limits, backup.
Операторы — для сложных stateful систем (PostgreSQL Operator, Kafka Operator) предоставляют CRD и управляют репликацией, failover, backup.
Native sidecar containers вместо DaemonSet — alpha в 1.28, beta on-by-default в 1.29, stable в 1.33. Для logging-агентов с изоляцией по namespace можно запускать sidecar в Pod приложения вместо node-wide DaemonSet (глава 02).