Блочные тома в Kubernetes
В managed Kubernetes класс tatnet-block создаёт
блочный том TatNet по запросу PersistentVolumeClaim
(PVC). CSI-драйвер подключает диск к узлу и монтирует его в под. Данные
сохраняются при пересоздании пода и плановом переносе на другой узел в том же
регионе.
Тома доступны в регионах с общим блочным хранилищем. CSI-драйвер устанавливается платформой; вручную создавать диск в панели или форматировать его на узле не нужно.
Подключение к кластеру
Скачайте kubeconfig своего кластера из панели и укажите его явно:
export KUBECONFIG="$HOME/.kube/tatnet.yaml"
kubectl get nodes
kubectl get storageclass tatnet-block
kubectl -n tatnet-csi get pods
Перед созданием приложения дождитесь готовности узлов и CSI-подов. Проверьте параметры класса:
kubectl get storageclass tatnet-block -o yaml
| Параметр | Значение | Что означает |
|---|---|---|
provisioner | block.csi.tatnet.ru | Диск создаёт CSI-драйвер TatNet |
volumeBindingMode | WaitForFirstConsumer | Выбор узла предшествует созданию диска |
reclaimPolicy | Delete | Удаление PVC приводит к удалению диска и данных |
allowVolumeExpansion | true | Размер PVC можно увеличивать |
csi.storage.k8s.io/fstype | ext4 | Файловая система для нового тома |
Создание PVC и приложения
Сохраните следующий пример как volume-demo.yaml. Он создаёт отдельное
пространство имён, том на 1 ГиБ и приложение, использующее каталог /data.
apiVersion: v1
kind: Namespace
metadata:
name: volume-smoke
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data
namespace: volume-smoke
spec:
accessModes: [ReadWriteOnce]
volumeMode: Filesystem
storageClassName: tatnet-block
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: volume-demo
namespace: volume-smoke
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: volume-demo
template:
metadata:
labels:
app: volume-demo
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: busybox:1.37
command: [sh, -c, 'while true; do sleep 3600; done']
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
resources:
requests:
cpu: 10m
memory: 16Mi
limits:
memory: 64Mi
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: data
Примените манифест и дождитесь запуска:
kubectl apply -f volume-demo.yaml
kubectl -n volume-smoke rollout status deployment/volume-demo --timeout=300s
kubectl -n volume-smoke get pvc,pods -o wide
PVC должен перейти в Bound, под — в Running. Пока нет пода-потребителя,
Pending у PVC с WaitForFirstConsumer — нормальное состояние. Создавайте
PVC вместе с приложением; ожидание Bound до создания пода не завершится.
Для выбора узла используйте nodeSelector или affinity, а не nodeName,
который обходит планировщик.
ReadWriteOnce допускает подключение диска к одному узлу одновременно.
Несколько подов на одном узле могут использовать этот PVC, но совместную
запись должно поддерживать приложение. ReadWriteMany между узлами не
поддерживается. Для нескольких реплик базы используйте отдельный PVC на
реплику, например через volumeClaimTemplates StatefulSet.
В примере одна реплика и стратегия Recreate: при обновлении старый под
завершается до создания нового. Это предотвращает одновременный запуск
старой и новой реплик с общим диском. fsGroup: 1000 позволяет контейнеру
с UID 1000 писать на том без root.
Проверка сохранности данных
Запишите файл и сохраните его контрольную сумму:
kubectl -n volume-smoke exec deployment/volume-demo -- sh -c \
'printf "tatnet-volume-smoke-20261014\n" > /data/proof.txt; sync; sha256sum /data/proof.txt'
Пересоздайте под, сохранив PVC:
kubectl -n volume-smoke rollout restart deployment/volume-demo
kubectl -n volume-smoke rollout status deployment/volume-demo --timeout=300s
kubectl -n volume-smoke exec deployment/volume-demo -- sha256sum /data/proof.txt
Контрольная сумма должна совпасть. Удаление пода само по себе не удаляет PVC.
Перенос на другой узел
Для проверки нужны два готовых рабочих узла. Посмотрите текущий узел пода и
выберите другой из kubectl get nodes:
kubectl -n volume-smoke get pods -o wide
kubectl get nodes
Подставьте имя второго рабочего узла вместо SECOND_WORKER:
kubectl -n volume-smoke patch deployment volume-demo --type=merge \
-p '{"spec":{"template":{"spec":{"nodeSelector":{"kubernetes.io/hostname":"SECOND_WORKER"}}}}}'
kubectl -n volume-smoke rollout status deployment/volume-demo --timeout=300s
kubectl -n volume-smoke get pods -o wide
kubectl -n volume-smoke exec deployment/volume-demo -- sha256sum /data/proof.txt
Новый под должен оказаться на выбранном узле, а контрольная сумма — совпасть.
Перенос включает размонтирование, отключение и повторное подключение диска.
Кратковременное событие Waiting for detach возможно, пока старое подключение
освобождается. Не отсоединяйте диск вручную в панели. При аварии узла время
восстановления зависит от обнаружения отказа и безопасного отключения диска;
эта проверка демонстрирует плановый перенос.
Увеличение тома
Увеличьте запрос существующего PVC с 1 до 2 ГиБ:
kubectl -n volume-smoke patch pvc data --type=merge \
-p '{"spec":{"resources":{"requests":{"storage":"2Gi"}}}}'
kubectl -n volume-smoke wait pvc/data \
--for=jsonpath='{.status.capacity.storage}'=2Gi --timeout=300s
kubectl -n volume-smoke exec deployment/volume-demo -- df -h /data
kubectl -n volume-smoke exec deployment/volume-demo -- sha256sum /data/proof.txt
CSI увеличивает диск и ext4 на работающем поде. Перезапуск пода и ручной
resize2fs не нужны. Уменьшение размера не поддерживается. Изменяйте запрос
PVC, а не ёмкость PV вручную. После расширения обновите размер и в своём
исходном манифесте, чтобы он соответствовал фактическому состоянию.
Том оплачивается по выделенному объёму, включая свободное место.
Просмотр и диагностика
kubectl -n volume-smoke describe pvc data
kubectl -n volume-smoke get events --sort-by=.lastTimestamp
kubectl -n volume-smoke describe pod <ИМЯ_ПОДА>
kubectl get pv
kubectl get volumeattachments
kubectl -n tatnet-csi get pods
| Симптом | Что проверить |
|---|---|
PVC Pending, пода нет | Создайте под-потребитель: действует WaitForFirstConsumer |
Под Pending | Готовность узлов, доступные CPU/память, taints и nodeSelector |
ProvisioningFailed | События PVC, доступность CSI, квоты, баланс и поддержку томов в регионе |
FailedAttachVolume | Завершение старого пода и отключение от прежнего узла; один диск нельзя подключить к двум узлам |
Permission denied в /data | runAsUser, runAsGroup и fsGroup приложения |
| Запрос увеличен, ёмкость прежняя | События PVC и состояние CSI; дождитесь завершения расширения |
Поле spec.csi.volumeHandle у PV содержит ID тома TatNet. В панели том
помечен принадлежностью к Kubernetes-кластеру и доступен только для чтения:
управляйте им через PVC. CSI-секреты и ключ API в манифест приложения не нужны.
Снимки CSI и встроенное резервное копирование томов не поддерживаются;
резервные копии данных организуйте на уровне приложения.
Удаление тестовых ресурсов
У стандартного tatnet-block политика Delete. Удаление PVC удаляет
соответствующий PV и диск TatNet вместе с данными. Удаление пространства имён
также удаляет находящиеся в нём PVC. Перед удалением сделайте нужные резервные
копии.
Сначала остановите приложение, затем удалите PVC:
kubectl -n volume-smoke delete deployment volume-demo --wait=true
kubectl -n volume-smoke wait --for=delete pod -l app=volume-demo --timeout=300s
kubectl -n volume-smoke delete pvc data --wait=true --timeout=300s
kubectl delete namespace volume-smoke
Проверьте, что тестовый PV исчез из kubectl get pv, а том — из списка томов
в панели. Не удаляйте рабочие PVC для пересоздания или обновления приложения.