Перейти к основному содержимому

Блочные тома в 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
ПараметрЗначениеЧто означает
provisionerblock.csi.tatnet.ruДиск создаёт CSI-драйвер TatNet
volumeBindingModeWaitForFirstConsumerВыбор узла предшествует созданию диска
reclaimPolicyDeleteУдаление PVC приводит к удалению диска и данных
allowVolumeExpansiontrueРазмер PVC можно увеличивать
csi.storage.k8s.io/fstypeext4Файловая система для нового тома

Создание 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 в /datarunAsUser, 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 для пересоздания или обновления приложения.