Увеличение томов PVC в StatefulSet Kubernetes

Kubernetes не позволяет прямо изменить поле volumeClaimTemplates в манифесте StatefulSet. Чтобы увеличить размер томов, вручную измените PVC, затем временно удалите (orphan) StatefulSet, примените обновлённый манифест и перезапустите поды. Этот процесс минимизирует простой и гарантирует фактическое расширение томов при условии, что драйвер хранения поддерживает расширение.
Быстрые ссылки
Создание StatefulSet
Ручное изменение размера томов StatefulSet
Воссоздание StatefulSet
Краткое резюме
Введение
StatefulSet в Kubernetes используют для развёртывания stateful-приложений внутри кластера. Каждый Pod в StatefulSet получает свой собственный PersistentVolumeClaim (PVC), который привязан к Pod и остаётся за ним даже после перезапуска. Это позволяет Pod-ам хранить уникальное состояние, отдельное от соседей.
Важно: стандартный объект StatefulSet не поддерживает изменение размера поля volumeClaimTemplates.spec.resources.requests.storage — оно считается неизменяемым после создания манифеста. Поэтому попытка просто изменить YAML и выполнить kubectl apply приведёт к ошибке.
Проблема: immutable volumeClaimTemplates
Поле
volumeClaimTemplatesв манифесте StatefulSet содержит шаблон для PVC, и большинство его свойств становятся неизменяемыми после создания StatefulSet. Например, попытка изменить “storage” с 1Gi на 10Gi в этом шаблоне выдаст ошибку вида:
The StatefulSet "nginx" is invalid: spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'template', 'updateStrategy', 'persistentVolumeClaimRetentionPolicy' and 'minReadySeconds' are forbiddenЭто ограничение заставляет администраторов выполнять дополнительные ручные шаги для увеличения размера томов.
Создание StatefulSet
Ниже — пример YAML, используемый в демонстрации. Скопируйте в файл
ss.yamlи примените:
apiVersion: v1kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
selector:
app: nginx
ports:
- name: nginx
port: 80
clusterIP: None
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 3
serviceName: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- name: web
containerPort: 80
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [“ReadWriteOnce”]
resources:
requests:
storage: 1Gi
Примените в кластер:
$ kubectl apply -f ss.yaml
Ожидаемый вывод:
service/nginx created
statefulset.apps/nginx created
Это создаёт StatefulSet с тремя репликами NGINX и PVC размером 1Gi для каждого Pod. В реальной среде размер данных может вырасти — и вам потребуется увеличить объём.
## Когда прямое изменение не сработает
Если вы отредактируете ss.yaml и измените volumeClaimTemplates.spec.resources.requests.storage на 10Gi, а затем выполните kubectl apply, вы получите ошибку (см. раздел выше). Это нормальное поведение — манифест StatefulSet в этом отношении иммутабелен.
## Ручное изменение размера PVC
Обходной путь — напрямую изменить каждый PVC, созданный на основе volumeClaimTemplates. После этого потребуется заставить Kubernetes фактически выполнить расширение тома — обычно это достигается временным освобождением PVC от контроллера StatefulSet и перезапуском подов.
Шаги:
1. Найдите PVC, связанные с вашим StatefulSet:
$ kubectl get pvc
Пример вывода:
NAME STATUS VOLUME CAPACITY ACCESS MODES
data-nginx-0 Bound pvc-ccb2c835-e2d3-4632-b8ba-4c8c142795e4 1Gi RWO
data-nginx-1 Bound pvc-1b0b27fe-3874-4ed5-91be-d8e552e515f2 1Gi RWO
data-nginx-2 Bound pvc-4b7790c2-3ae6-4e04-afee-a2e1bae4323b 1Gi RWO
2. Отредактируйте каждый PVC и измените spec.resources.requests.storage на желаемый объём:
$ kubectl edit pvc data-nginx-0
В редакторе найдите:
spec: resources:
requests:
storage: 10Gi
Сохраните и закройте редактор. Kubectl сообщит об успешном редактировании:
persistentvolumeclaim/data-nginx-0 edited
Повторите для остальных PVC.
3. Проверьте PV — провиженер должен отразить новый размер:
$ kubectl get pv
Пример:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM
pvc-0a0d0b15-241f-4332-8c34-a24b61944fb7 10Gi RWO Delete Bound default/data-nginx-2
pvc-33af452d-feff-429d-80cd-a45232e700c1 10Gi RWO Delete Bound default/data-nginx-0
pvc-49f3a1c5-b780-4580-9eae-17a1f002e9f5 10Gi RWO Delete Bound default/data-nginx-1
Обратите внимание: PVC могут временно показывать старый размер, пока томы всё ещё примонтированы к запущенным подам. Расширение файловой системы внутри пода обычно выполняется после размонтирования/перемонтирования или перезапуска пода.
## Освобождение томов и воссоздание StatefulSet
Чтобы фактически применить увеличение, нужно освободить PVC от контроллера StatefulSet, не удаляя сами поды. Для этого удалите StatefulSet с флагом --cascade=orphan:
$ kubectl delete statefulset –cascade=orphan nginx
Это удалит объект StatefulSet, но не поды и не PVC. После этого поды продолжают работать, но уже не контролируются StatefulSet.
Далее обновите ss.yaml, чтобы volumeClaimTemplates указывал новый размер (например, 10Gi), и снова примените его:
$ kubectl apply -f ss.yaml
Ожидаемый вывод:
service/nginx unchanged
statefulset.apps/nginx created
Новый StatefulSet «заберёт» существующие поды, поскольку они удовлетворяют его селекторам и требованиям. Часто потребуется инициировать контролируемый rollout, чтобы поды были перезапущены по одному и файловые системы увидели новый размер:
$ kubectl rollout restart statefulset nginx
Rollout будет выполняться последовательно (по одному Pod-у одновременно), что минимизирует простой.
После перезапуска проверьте PVC:
$ kubectl get pvc
Они должны показать обновлённый размер:
NAME STATUS VOLUME CAPACITY ACCESS MODES
data-nginx-0 Bound pvc-33af452d-feff-429d-80cd-a45232e700c1 10Gi RWO
data-nginx-1 Bound pvc-49f3a1c5-b780-4580-9eae-17a1f002e9f5 10Gi RWO
data-nginx-2 Bound pvc-0a0d0b15-241f-4332-8c34-a24b61944fb7 10Gi RWO
Подключитесь внутрь пода и проверьте размер:
$ kubectl exec -it nginx-0 bash
Внутри пода:
root@nginx-0:/# df -h /usr/share/nginx/html
Filesystem Size Used Avail Use% Mounted on
/dev/disk/by-id/scsi-0DO_Volume_pvc-33af452d-feff-429d-80cd-a45232e700c1 9.9G 4.5M 9.4G 1% /usr/share/nginx/html
Файловая система показывает ожидаемые ~10 Gi.
## Ограничения и требования
- Драйвер хранения должен поддерживать динамическое расширение (allowVolumeExpansion). Начиная с Kubernetes v1.24 это стало общедоступной возможностью, но не все провайдеры или дистрибуции поддерживают её одинаково. Проверьте:
$ kubectl get sc
и убедитесь, что в колонке ALLOWVOLUMEEXPANSION стоит true для используемого StorageClass.
- Расширение блоковых томов обычно работает без проблем. Для расширения файловой системы внутри пода может потребоваться её размонтировать/перемонтировать или перезапустить под.
- Если том используется одновременно несколькими нодами в режиме, несовместимом с расширением, вы не сможете увеличить размер онлайн.
## Риски и смягчения
- Риск: человеческая ошибка при редактировании PVC приведёт к потере данных.
- Смягчение: делайте snapshot/backup перед операцией, выполняйте изменения поочерёдно и проверяйте состояние PV/PVC.
- Риск: StorageClass не поддерживает расширение.
- Смягчение: проверить поддержку заранее и подготовить план миграции томов (создание нового PV + синхронизация данных).
- Риск: несовместимость с облачным провайдером.
- Смягчение: протестировать процедуру в тестовом кластере перед PROD.
## Побочные подходы и альтернативы
1. Миграция данных на новый PVC / PV
- Создайте новый PVC с нужным размером.
- Распакуйте или синхронизируйте данные (rsync, tar, копирование внутри кластера).
- Обновите Deployment/StatefulSet для использования нового PVC (может потребовать создания нового StatefulSet и поочерёдного переключения).
Плюсы: не зависит от allowVolumeExpansion. Минусы: сложнее и дольше.
2. Использовать CSI-операторы или кастомные контроллеры
- Некоторые CSI-драйверы или операторы предоставляют дополнительные возможности по управлению томами и миграциям.
3. Планирование и мониторинг заполнения
- Используйте метрики (Prometheus) и оповещения, чтобы заранее узнавать, что томы заполняются, и выполнять resize заранее.
## Пошаговый SOP для администратора (Playbook)
1. Подготовка
- Убедитесь, что у вас есть бэкап/снимок данных.
- Проверьте allowVolumeExpansion у StorageClass: `kubectl get sc`.
- Оповестите команду о плановом окне.
2. Изменение PVC
- Для каждого PVC выполните `kubectl edit pvc <имя>` и обновите `spec.resources.requests.storage`.
- Подтвердите изменение: `kubectl get pv` — проверьте CAPACITY.
3. Освобождение StatefulSet
- Выполните `kubectl delete statefulset --cascade=orphan `.
4. Обновление манифеста
- Обновите volumeClaimTemplates в ss.yaml на новый размер.
- Примените `kubectl apply -f ss.yaml`.
5. Rollout
- Запустите `kubectl rollout restart statefulset `.
- Мониторьте статус: `kubectl rollout status statefulset `.
6. Верификация
- Для каждого пода: `kubectl exec -it -- df -h `.
- Проверьте приложения и метрики.
7. Откат (если необходимо)
- Если обнаружены проблемы, восстановите данные из бэкапа и верните предыдущий манифест.
## Роль‑ориентированные контрольные списки
Администратор кластера
- Проверить allowVolumeExpansion в StorageClass.
- Сделать snapshot или бэкап.
- Координировать окно изменений.
DevOps / Разработчик
- Обновить ss.yaml с новым размером.
- Подтвердить, что приложение корректно перезагружается.
Storage‑администратор
- Подтвердить поддержку расширения в провайдере хранения.
- Проверить состояние PV после изменений.
## Быстрый чек-лист для тестирования (Test cases)
- После изменения PVC PV показывает новый CAPACITY.
- После перезапуска pod внутри df -h показывает ожидаемый размер.
- Нагрузка на приложение остаётся в допустимых пределах во время поочередного rollout.
## Полезные heuristics и ментальные модели
- Всегда работайте с одним PVC за раз в продакшене, если не уверены в проводимости процесса.
- Подход «orphan и reapply» минимизирует время, когда поды вовсе отсутствуют, т.к. они остаются запущенными.
- Хранение данных и контроль за их размерами — плановая задача мониторинга, а не реактивная операция.
## Troubleshooting — распространённые проблемы и решения
Проблема: PVC не расширился, PV остался прежнего размера.
- Возможная причина: драйвер хранения не поддерживает динамическое расширение.
- Решение: проверьте StorageClass, обратитесь к поставщику, используйте миграцию на новый PV.
Проблема: файл система внутри пода не показывает увеличение после расширения PV.
- Причина: файловая система не была расширена автоматически.
- Решение: перезапустите pod или выполните ручное расширение (например, resize2fs для ext4) внутри пода.
Проблема: при удалении StatefulSet с --cascade=orphan поды утрачивают нужные метаданные и не привязываются обратно.
- Решение: проверьте селекторы и labels в манифесте нового StatefulSet. Они должны совпадать с теми, что есть у существующих подов.
## Совместимость и миграция
Проверьте следующее перед операцией:
- StorageClass.allowVolumeExpansion = true
- Версия Kubernetes >= 1.24 (рекомендуется) для стабильного поведения расширения томов
- Документация облачного провайдера/CSI-драйвера на предмет известных ограничений
Если driver не поддерживает расширение:
- Рассмотрите миграцию данных на новый PVC с желаемым размером.
- Используйте инструменты синхронизации (rsync) или snapshot/restore.
## Мермад-диаграмма решения (decision tree)
flowchart TD A[Нужно увеличить том StatefulSet?] –> B{Поддерживает ли StorageClass allowVolumeExpansion?} B – Да –> C[Редактировать PVC напрямую и изменить size] C –> D{Прикреплён ли PVC к запущенным подам?} D – Да –> E[Удалить StatefulSet –cascade=orphan] D – Нет –> F[Применить новый манифест StatefulSet] E –> F F –> G[Rollout restart StatefulSet] G –> H[Проверить df -h внутри пода] B – Нет –> I[Создать новый PVC + синхронизация данных] I –> J[Перенести приложение на новый PVC]
## Краткое резюме
- StatefulSet не позволяет менять размер volumeClaimTemplates напрямую.
- Рабочий обход: отредактировать PVC, удалить StatefulSet с --cascade=orphan, обновить манифест и перезапустить rollout.
- Убедитесь, что StorageClass поддерживает allowVolumeExpansion. Всегда имейте резервную копию данных.
Важно: процесс требует аккуратности и тестирования в непроизводственной среде перед применением в продакшене.
## Глоссарий (1 строка каждого термина)
- PVC: PersistentVolumeClaim — запрос на постоянный том в Kubernetes.
- PV: PersistentVolume — реальный том, предоставленный кластером.
- StorageClass: класс хранения, описывающий провиженер и параметры PV.
- StatefulSet: контроллер Kubernetes для управляния stateful-приложениями.
---
Ниже приведены ключевые команды для быстрой работы:
kubectl get pvc kubectl edit pvc <имя> kubectl get pv kubectl delete statefulset –cascade=orphan
Важно: перед операциями на продакшене делайте бэкап и тестируйте процедуру в staging.