Задача 17. StatefulSet, PVC и данные, которые пережили под

Уменьшили StatefulSet с 5 реплик до 3, вернули обратно — и получили старые данные. Разбираем, почему PVC живут дольше подов, чем StatefulSet отличается от Deployment и как reclaim policy решает судьбу данных.
Опубликовано:

Задача

StatefulSet базы данных на 5 реплик. Для экономии его временно уменьшили до 3:

BASH
kubectl scale statefulset db --replicas=3
Нажмите, чтобы развернуть и увидеть больше

Поды db-3 и db-4 удалены. Через неделю нагрузка вернулась, реплики подняли обратно до 5.

Вопрос: что окажется на дисках у новых db-3 и db-4 — пустые тома или данные недельной давности?

Что кажется очевидным

«Поды удалены — значит, и данные удалены. Новые реплики начнут с чистого листа и синхронизируются с остальными».

Это неверно, и последствия могут быть серьёзными.

Как это работает на самом деле

PVC переживают удаление подов. Это принципиальное отличие StatefulSet от Deployment.

volumeClaimTemplates создаёт для каждого пода свой PVC с предсказуемым именем:

YAML
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: db
spec:
  replicas: 5
  serviceName: db-headless
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: [ReadWriteOnce]
        resources:
          requests:
            storage: 100Gi
Нажмите, чтобы развернуть и увидеть больше

Имена получаются вида data-db-0, data-db-1, …, data-db-4.

При уменьшении числа реплик Kubernetes удаляет поды, но не удаляет PVC. Это сделано намеренно: данные считаются ценными, и автоматическое удаление было бы опасным.

Когда реплики возвращают обратно, под db-3 получает имя db-3, ищет PVC data-db-3находит существующий и монтирует его со старыми данными.

Почему это может быть проблемой

Для многих СУБД подключение узла с устаревшими данными — не «ускоренное восстановление», а риск:

Поэтому решение «вернуть реплики обратно» должно быть осознанным: либо вы хотите переиспользовать данные (быстрое восстановление узла), либо PVC нужно удалить вручную перед масштабированием вверх.

StatefulSet против Deployment

DeploymentStatefulSet
Имена подовСлучайный суффиксПорядковые: db-0, db-1
ТомаОбщий PVC или без негоСвой PVC на каждый под
Порядок запускаПараллельноПоследовательно, 012
Порядок удаленияПроизвольныйВ обратном порядке
DNSОбщий ServiceСтабильное имя на под (с headless Service)
Замена подаНовое имя и IPТо же имя и тот же том

Стабильная идентичность — главное, ради чего существует StatefulSet: под db-0 после перезапуска остаётся db-0 с тем же именем, тем же DNS-именем и тем же диском.

Ответ

На дисках окажутся данные недельной давности. PVC, созданные через volumeClaimTemplates, не удаляются при уменьшении числа реплик, и новые поды подхватывают существующие тома по имени.

Что с этим делать

Управление жизненным циклом PVC

Если нужно, чтобы тома удалялись автоматически, есть политика на уровне StatefulSet:

YAML
spec:
  persistentVolumeClaimRetentionPolicy:
    whenScaled: Delete # удалять PVC при уменьшении реплик
    whenDeleted: Retain # но сохранять при удалении StatefulSet
Нажмите, чтобы развернуть и увидеть больше

Значения по умолчанию для обоих — Retain (сохранять). Ставьте Delete осознанно: для кэшей и легко воссоздаваемых данных это удобно, для баз — опасно.

Ручное удаление, когда нужен чистый старт:

BASH
kubectl delete pvc data-db-3 data-db-4
Нажмите, чтобы развернуть и увидеть больше

Reclaim policy: судьба самого тома

Есть второй уровень — что происходит с PersistentVolume после удаления PVC. Определяется reclaimPolicy у StorageClass:

Для продовых данных используйте Retain. Это последний рубеж между случайным kubectl delete и безвозвратной потерей.

BASH
kubectl get storageclass
kubectl patch pv pvc-xxxx -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
Нажмите, чтобы развернуть и увидеть больше

Практические правила


Дальше: Задача 18. RBAC: кто здесь и что ему можно.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
ESC
⌘K Горячая клавиша