Learning Platform
Глоссарий Troubleshooting
Урок 08.05 · 22 мин
Продвинутый
CSIContainer Storage InterfaceVolumeSnapshotVolume cloningVolume expansionSnapshots vs backups

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 — DeleteVolume
  • external-attacher — watch VolumeAttachment объекты, вызывает ControllerPublishVolume (attach to node) и ControllerUnpublishVolume (detach)
  • external-resizer — watch PVC size changes, вызывает ControllerExpandVolume
  • external-snapshotter — watch VolumeSnapshot, вызывает CreateSnapshot / DeleteSnapshot

Driver — это сам бинарник от vendor-а, реализующий CSI gRPC spec.

CSI: разделение Kubernetes и vendor кода
K8s API serverИсточник правды. Все объекты PVC, PV, VolumeAttachment, VolumeSnapshot живут здесь. Sidecars подписаны на их watch.
K8s-side sidecars (общие для всех drivers)
external-provisionerSidecar от sig-storage. Watch PVC events. На create вызывает gRPC CreateVolume у driver. На delete — DeleteVolume. Универсальный, не зависит от backend.
external-attacherWatch VolumeAttachment объекты (создаются kube-controller-manager при появлении Pod-а с PVC). Вызывает ControllerPublishVolume у driver — реально attach storage к node.
external-resizerWatch изменения PVC.spec.resources. Вызывает ControllerExpandVolume у driver. Online expansion работает без рестарта Pod-а.
external-snapshotterWatch VolumeSnapshot объекты. Вызывает CreateSnapshot/DeleteSnapshot у driver. Создаёт VolumeSnapshotContent с pointer на backend snapshot.
gRPC к driver
CSI Driver (vendor)Бинарник от vendor-а: AWS EBS CSI, Ceph CSI, Longhorn, и т.д. Реализует CSI gRPC spec. Внутри — логика общения с storage backend через AWS API / Ceph RBD / NFS / любой проприетарный protocol.
API storage backend-а
Storage backendСам storage: AWS EBS API, GCP PD API, Ceph cluster, NFS server, или local disks. Driver — это адаптер K8s → backend.

Эта архитектура — почему K8s storage экосистема такая разнообразная: vendor пишет driver один раз, и он работает в любом кластере. Список CSI drivers — десятки активных проектов.


Популярные CSI drivers

BackendDriverОсобенности
AWS EBSebs.csi.aws.comBlock, RWO, zonal. gp3/io2/sc1, online expansion, snapshots, encryption
AWS EFSefs.csi.aws.comNFS, RWX, регион-wide. Access points, dynamic provisioning
GCP Persistent Diskpd.csi.storage.gke.ioBlock, RWO, zonal или regional. SSD/balanced/standard
GCP Filestorefilestore.csi.storage.gke.ioNFS, RWX
Azure Diskdisk.csi.azure.comBlock, RWO, zonal
Azure Filesfile.csi.azure.comSMB / NFS, RWX
Ceph RBDrbd.csi.ceph.comBlock, RWO/ROX, on-prem
Ceph FScephfs.csi.ceph.comDistributed FS, RWX
Longhorndriver.longhorn.ioDistributed block, Rancher project, snapshots+backups
OpenEBS Mayastorio.openebs.csi-mayastorNVMe-oF, high-performance
NFSnfs.csi.k8s.ioGeneric NFS, RWX
Localkubernetes.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 и restore flow
PVC: app-data (running)Исходный PVC, используемый Pod-ом. Например, PostgreSQL data.
kubectl apply VolumeSnapshot
VolumeSnapshot созданAPI объект. external-snapshotter ловит, вызывает CreateSnapshot у driver. EBS API создаёт snap-xyz789. VolumeSnapshotContent создаётся с ссылкой на snap-xyz789.
kubectl apply PVC с dataSource
Новый PVC: restoreddataSource: VolumeSnapshot указывает на snap. external-provisioner вызывает CreateVolume с source=snap-xyz789. EBS создаёт новый volume vol-abc456, инициализированный из snapshot.
Pod использует restored PVC
Pod видит данные на момент snapshotСодержимое идентично source на момент CreateSnapshot. С момента snapshot изменения в source PVC не затрагивают restored PVC (это два независимых backend volumes).

Snapshot не равно backup

Тонкость, которая ловит много людей:

DANGER

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:

  1. Snapshots — частые, дешёвые, быстрые (3 раза в день, retention 7 дней)
  2. 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. Технически:

  1. PVC spec.resources.requests.storage меняется через kubectl patch / edit
  2. external-resizer ловит event, вызывает ControllerExpandVolume у driver
  3. Driver делает expand на backend (AWS ModifyVolume)
  4. На node NodeExpandVolume запускает filesystem resize:
    • ext4: resize2fs /dev/xxx
    • xfs: xfs_growfs /mountpoint
  5. 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 обычно уже работает.


Проверка знанийKnowledge check
Команда настроила автоматические VolumeSnapshot для production баз данных через CronJob, который каждые 6 часов создаёт VolumeSnapshot объекты. Retention 7 дней. Через год региональный outage AWS привёл к недоступности всех EBS volumes и снапшотов в этом регионе. Команда не смогла восстановить данные. Что было сделано неправильно и какая должна быть правильная стратегия?
ОтветAnswer
Ключевая ошибка — путаница snapshot и backup. VolumeSnapshot в Kubernetes — это interface к snapshot функционалу storage backend (EBS snapshots в данном случае). Эти snapshots живут в том же storage backend, что и исходные volumes — для AWS EBS это означает тот же регион (и тот же AWS account). Если регион упал, потерян, или account скомпрометирован — snapshots исчезают вместе с volumes. Snapshot защищает от: (1) accidental data deletion в самом приложении (rollback на 6 часов назад), (2) data corruption из-за бага в приложении, (3) необходимости создать testing environment из текущих данных. Snapshot НЕ защищает от: catastrophic failure storage backend, потери региона, ransomware на cloud account, accidental deletion AWS account. Правильная стратегия — два уровня: (1) Snapshots для quick recovery — частые (6h), retention короткая (7d), бесплатно через AWS API. (2) Backups для disaster recovery — daily, retention 30-90 дней, копируются OFF-SITE: в S3 другого региона, или GCS, или on-prem. Tools: Velero (создаёт VolumeSnapshot + копирует данные в S3 в другом регионе), Kasten K10, Stash. Cross-region replication для AWS — встроенная фича EBS, но требует явной настройки. Эти backups дают true RPO/RTO гарантии при регионе или account loss. Минимально: помимо snapshots делать ещё application-level дампы (pg_dump для PostgreSQL) и складывать в S3 другого региона.

Проверьте понимание

Результат: 0 из 0
Аналитический
Вопрос 1 из 5. Что такое CSI sidecar (например, external-provisioner или external-attacher) и зачем он нужен отдельно от собственно driver-а?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5