CSI, snapshots и volume expansion
В предыдущих уроках мы видели storage абстрактно: PV, PVC, SC. А кто реально создаёт EBS volume в AWS, делает mount на node, expand-ит размер? Это работа storage driver. В современном Kubernetes стандарт для этого — Container Storage Interface (CSI).
CSI — gRPC-based plugin interface. Driver работает как отдельный pod-набор в кластере, K8s общается с ним через стандартизированные RPC: CreateVolume, DeleteVolume, ControllerPublishVolume, NodeStageVolume, и т.д. До CSI storage drivers были “in-tree” — встроены в код kubelet и kube-controller-manager. Это создавало проблемы: для добавления нового storage нужно было патчить ядро K8s. CSI решает это: driver — это отдельный компонент, разрабатывается storage vendor-ом, деплоится в любой K8s кластер.
В этом уроке: архитектура CSI, snapshots, cloning, volume expansion. CKAD scope — концептуальное знание, без deep-dive в driver development (это CKA / CKS territory).
VFS: единый интерфейс над ext4, xfs, btrfs, tmpfs
Архитектура CSI
CSI driver — это набор компонентов, обычно деплоится как два workloads:
- Controller plugin (Deployment или StatefulSet) — единственный на кластер. Обрабатывает provisioning, attach, snapshot. Содержит CSI driver + набор Kubernetes-side sidecars.
- Node plugin (DaemonSet) — по экземпляру на каждой node. Делает mount/unmount volumes на свою node. Содержит CSI driver + node-registrar sidecar.
# Структура controller pod (псевдо)
spec:
containers:
- name: csi-provisioner # K8s sidecar
image: registry.k8s.io/sig-storage/csi-provisioner:v5.0.0
- name: csi-attacher # K8s sidecar
image: registry.k8s.io/sig-storage/csi-attacher:v4.6.0
- name: csi-resizer # K8s sidecar (опционально)
image: registry.k8s.io/sig-storage/csi-resizer:v1.10.0
- name: csi-snapshotter # K8s sidecar (опционально)
image: registry.k8s.io/sig-storage/csi-snapshotter:v8.0.0
- name: ebs-csi-controller # сам driver (AWS-specific)
image: amazon/aws-ebs-csi-driver:v1.30.0
Каждый sidecar — это отдельный процесс, который watch K8s API и вызывает соответствующие RPC у driver-а:
external-provisioner— watch PVC, на PVC create вызываетCreateVolume, на PVC delete —DeleteVolumeexternal-attacher— watchVolumeAttachmentобъекты, вызываетControllerPublishVolume(attach to node) иControllerUnpublishVolume(detach)external-resizer— watch PVC size changes, вызываетControllerExpandVolumeexternal-snapshotter— watch VolumeSnapshot, вызываетCreateSnapshot/DeleteSnapshot
Driver — это сам бинарник от vendor-а, реализующий CSI gRPC spec.
Эта архитектура — почему K8s storage экосистема такая разнообразная: vendor пишет driver один раз, и он работает в любом кластере. Список CSI drivers — десятки активных проектов.
Популярные CSI drivers
| Backend | Driver | Особенности |
|---|---|---|
| AWS EBS | ebs.csi.aws.com | Block, RWO, zonal. gp3/io2/sc1, online expansion, snapshots, encryption |
| AWS EFS | efs.csi.aws.com | NFS, RWX, регион-wide. Access points, dynamic provisioning |
| GCP Persistent Disk | pd.csi.storage.gke.io | Block, RWO, zonal или regional. SSD/balanced/standard |
| GCP Filestore | filestore.csi.storage.gke.io | NFS, RWX |
| Azure Disk | disk.csi.azure.com | Block, RWO, zonal |
| Azure Files | file.csi.azure.com | SMB / NFS, RWX |
| Ceph RBD | rbd.csi.ceph.com | Block, RWO/ROX, on-prem |
| Ceph FS | cephfs.csi.ceph.com | Distributed FS, RWX |
| Longhorn | driver.longhorn.io | Distributed block, Rancher project, snapshots+backups |
| OpenEBS Mayastor | io.openebs.csi-mayastor | NVMe-oF, high-performance |
| NFS | nfs.csi.k8s.io | Generic NFS, RWX |
| Local | kubernetes.io/no-provisioner | Не CSI, статический PV, на конкретной node |
In-tree drivers (kubernetes.io/aws-ebs, kubernetes.io/gce-pd) deprecated и удаляются. CSI Migration переписывает их calls в CSI calls под капотом, чтобы существующие PV/SC продолжали работать.
VolumeSnapshot: point-in-time копии
Снапшот — это снимок состояния PV в конкретный момент. Storage backend поддерживает COW (copy-on-write): после snapshot первоначальное содержимое сохранено, а новые записи в исходный volume не затрагивают snapshot.
Снапшоты API стабилизировался: snapshot.storage.k8s.io/v1 GA с v1.20. Три объекта:
VolumeSnapshotClass
Аналог StorageClass для снапшотов:
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: ebs-snapshot-class
driver: ebs.csi.aws.com
deletionPolicy: Delete
parameters:
tagSpecification_1: "Environment=production"
VolumeSnapshot
User-level запрос на снапшот PVC:
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: app-data-snap-2025-05-13
spec:
volumeSnapshotClassName: ebs-snapshot-class
source:
persistentVolumeClaimName: app-data
K8s через external-snapshotter вызывает у driver CreateSnapshot(volume-handle). AWS API создаёт EBS snapshot, возвращает snapshot ID.
VolumeSnapshotContent
Cluster-level объект, автоматически создаётся: ссылается на backend snapshot ID. Аналогия с PV/PVC — VolumeSnapshot это claim, VolumeSnapshotContent это actual snapshot.
kubectl get volumesnapshot
# NAME READYTOUSE SOURCEPVC SNAPSHOTCLASS AGE
# app-data-snap-2025-05-13 true app-data ebs-snapshot-class 10s
kubectl get volumesnapshotcontent
# NAME READYTOUSE DRIVER AGE
# snapcontent-abc12345-def6-... true ebs.csi.aws.com 10s
Restore: snapshot → new PVC
Снапшот сам по себе бесполезен — нужно создать новый PVC из него:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data-restored
spec:
storageClassName: fast-ssd
dataSource:
name: app-data-snap-2025-05-13
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 50Gi
dataSource указывает на snapshot. Provisioner создаёт новый PV, инициализированный из snapshot — содержимое идентично исходному PVC на момент создания snapshot. Это используется для:
- Восстановления после сбоя приложения
- Создания test/staging environment из production data
- Клонирования environment для отладки
Snapshot не равно backup
Тонкость, которая ловит много людей:
Snapshot — не backup. Снапшот существует в том же storage backend, что и исходный volume. Если backend упал (диск умер, регион потерян, AWS account удалён) — снапшоты потеряны вместе с исходными данными. Snapshot защищает от: случайного удаления, поломки данных приложением, нужды откатиться к моменту времени. Backup защищает от: catastrophic failure backend-а, потери региона, ransomware на storage. Backup — это снапшот + копирование в external storage (S3 в другом регионе, on-prem tape, off-site storage, через инструмент типа Velero).
Типичная стратегия в production:
- Snapshots — частые, дешёвые, быстрые (3 раза в день, retention 7 дней)
- Backups — реже, дороже, для recovery (1 раз в день, retention 30+ дней, off-site)
Tool типа Velero делает: создаёт VolumeSnapshot, копирует данные snapshot в S3 (Azure Blob, GCS), при restore — копирует обратно и создаёт PV. Так получается настоящий backup.
Volume cloning
С v1.16 — клонирование PVC без посредника-snapshot:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-data-clone
spec:
storageClassName: fast-ssd
dataSource:
name: app-data
kind: PersistentVolumeClaim
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 50Gi
Driver под капотом делает clone (или snapshot+restore, в зависимости от backend). Result — новый PVC с копией данных source.
Limitations:
- Source и clone должны быть в одном namespace и одном StorageClass
- Не все CSI drivers поддерживают (driver капабилити
CLONE_VOLUME) - Size clone должен быть ≥ size source
Use case: создать копию production DB для тестов без остановки production.
Volume expansion
Уже видели в предыдущем уроке: allowVolumeExpansion: true в SC + patch PVC. Технически:
- PVC
spec.resources.requests.storageменяется через kubectl patch / edit external-resizerловит event, вызываетControllerExpandVolumeу driver- Driver делает expand на backend (AWS ModifyVolume)
- На node
NodeExpandVolumeзапускает filesystem resize:- ext4:
resize2fs /dev/xxx - xfs:
xfs_growfs /mountpoint
- ext4:
- PVC.status.capacity обновляется
Online expansion (без рестарта Pod-а) поддерживают:
- ext4, xfs (resize online)
- Современные CSI drivers (EBS, GCP PD, Azure Disk)
Offline expansion (требует рестарт Pod-а) — для старых FS или drivers без online capability.
Ограничения:
- Можно только увеличивать, не уменьшать (shrink на ext4/xfs опасен и не поддерживается)
- Некоторые backends имеют limits (например, EBS gp3 max 16 TiB)
- Cooling period: EBS не позволяет повторный modify volume в течение 6 часов
CSIDriver и CSINode
Два cluster-level объекта, связанных с CSI:
kubectl get csidriver
# NAME ATTACHREQUIRED PODINFOONMOUNT STORAGECAPACITY FSGROUPPOLICY AGE
# ebs.csi.aws.com true false false File 10d
# efs.csi.aws.com false false false File 10d
kubectl get csinode
# NAME DRIVERS AGE
# ip-10-0-1-15 2 10d
# ip-10-0-2-22 2 10d
- CSIDriver — параметры driver-а в кластере: нужен ли attach (для NFS-like не нужен), какой fsGroupPolicy, support ли storage capacity reporting.
- CSINode — какие drivers зарегистрированы на конкретной node, какие topology keys (zone, region).
CKAD не требует deep знаний этих объектов, но полезно знать что они есть для troubleshooting.
Troubleshooting CSI
Когда что-то идёт не так с volume, типичные шаги:
# Состояние PVC
kubectl describe pvc app-data
# Events PV
kubectl describe pv <pv-name>
# Логи provisioner sidecar
kubectl logs -n kube-system deploy/ebs-csi-controller -c csi-provisioner
kubectl logs -n kube-system deploy/ebs-csi-controller -c csi-attacher
# Логи node plugin на конкретной node
kubectl logs -n kube-system daemonset/ebs-csi-node -c ebs-plugin
# VolumeAttachment объекты
kubectl get volumeattachment
# CSI drivers зарегистрированные в кластере
kubectl get csidriver
Типичные проблемы:
- PVC stuck Pending: SC не существует, provisioner упал, нет capacity в backend, mismatch access mode
- Pod stuck ContainerCreating с FailedAttachVolume: Multi-Attach (RWO волюм уже attached), zone mismatch, IAM permission issue
- Mount failed: filesystem corrupted, fsType mismatch, wrong fsGroup
- Expansion stuck: SC не имеет allowVolumeExpansion, backend в cooling period, FS не поддерживает resize
CKAD scope: что нужно знать
CKAD focused на пользовательском уровне:
- Понимать что такое CSI и его роль (driver = vendor code)
- Уметь читать
kubectl get csidriverчтобы видеть, что доступно - Знать концепции VolumeSnapshot, VolumeSnapshotClass — уметь создавать snapshots и restore
- Знать что snapshot ≠ backup
- Уметь expand PVC через patch (если SC позволяет)
Управление CSI drivers (установка, конфигурация sidecars, debug RPC) — это CKA / CKS / Platform Engineer territory. На CKAD-задачах driver обычно уже работает.