Модуль 4.3: StorageClasses та динамічне надання
Складність:
[MEDIUM]— Автоматизація надання сховищаЧас на виконання: 35–45 хвилин
Передумови: Модуль 4.2 (PV та PVC), Модуль 1.2 (CSI)
Що ви зможете робити
Розділ «Що ви зможете робити»Після цього модуля ви зможете:
- Створити StorageClasses для динамічного виділення з хмарними та локальними провізіонерами
- Налаштувати режими прив’язки (Immediate vs WaitForFirstConsumer) і пояснити, коли кожен доречний
- Імплементувати розширення томів на існуючих PVC та пояснити вимоги
- Дебажити збої динамічного виділення, перевіряючи StorageClass, поди провізіонера та події
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»У Модулі 4.2 ви вручну створювали PersistentVolumes перед створенням PersistentVolumeClaims. Це не масштабується — уявіть адміністратора, який створює сотні PV для кожного запиту на сховище! StorageClasses забезпечують динамічне надання: створіть PVC, і Kubernetes автоматично надає базове сховище. На іспиті CKA перевіряють як розуміння StorageClasses, так і налаштування динамічного надання.
Аналогія з торговим автоматом
Уявіть статичне надання як замовлення меблів на замовлення — хтось повинен їх виготовити, перш ніж ви зможете ними скористатися. Динамічне надання — це як торговий автомат: ви обираєте, що хочете (StorageClass), вставляєте запит (PVC), і отримуєте сховище (PV). StorageClass — це торговий автомат — він знає, як виробляти різні типи сховища на вимогу.
Що ви дізнаєтесь
Розділ «Що ви дізнаєтесь»Після завершення цього модуля ви зможете:
- Розуміти, як StorageClasses забезпечують динамічне надання
- Створювати та налаштовувати StorageClasses
- Встановлювати StorageClass за замовчуванням для кластера
- Використовувати параметри для налаштування наданого сховища
- Розуміти режими прив’язки томів
- Усувати проблеми динамічного надання
Чи знали ви?
Розділ «Чи знали ви?»- Хмарні кластери мають значення за замовчуванням: GKE, EKS та AKS постачаються з попередньо налаштованими StorageClasses за замовчуванням, які надають хмарне сховище
- kind/minikube теж мають provisioners: Навіть локальні кластери включають динамічні provisioners (rancher.io/local-path для kind, k8s.io/minikube-hostpath для minikube)
- StorageClasses є незмінними: Після створення ви не можете змінити StorageClass — потрібно видалити та створити заново
Частина 1: Розуміння StorageClasses
Розділ «Частина 1: Розуміння StorageClasses»1.1 Статичне vs динамічне надання
Розділ «1.1 Статичне vs динамічне надання»┌──────────────────────────────────────────────────────────────────────┐│ Статичне vs динамічне надання ││ ││ СТАТИЧНЕ (Ручне) ДИНАМІЧНЕ (Автоматичне) ││ ─────────────── ──────────────────── ││ ││ 1. Адмін створює PV 1. Адмін створює StorageClass ││ │ │ ││ ▼ ▼ ││ 2. Розробник створює PVC 2. Розробник створює PVC ││ │ │ ││ ▼ ▼ ││ 3. Kubernetes прив'язує 3. Provisioner створює PV ││ PVC до існуючого PV │ ││ ▼ ││ 4. Kubernetes прив'язує PVC ││ до нового PV ││ ││ Плюс: Повний контроль Плюс: Самообслуговування, ││ Мінус: Адмін — вузьке місце масштабованість ││ Мінус: Менше контролю на том │└──────────────────────────────────────────────────────────────────────┘1.2 Компоненти StorageClass
Розділ «1.2 Компоненти StorageClass»apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: fast-ssd annotations: storageclass.kubernetes.io/is-default-class: "true" # Опціональноprovisioner: kubernetes.io/aws-ebs # Хто створює сховищеparameters: # Налаштування, специфічні для provisioner type: gp3 iopsPerGB: "10"reclaimPolicy: Delete # Що відбувається при видаленні PVCvolumeBindingMode: WaitForFirstConsumer # Коли надаватиallowVolumeExpansion: true # Чи можна змінити розмір пізніше?mountOptions: # Параметри монтування для томів - debug1.3 Поширені Provisioners
Розділ «1.3 Поширені Provisioners»| Provisioner | Хмара/Платформа | Тип сховища |
|---|---|---|
| kubernetes.io/aws-ebs | AWS | Томи EBS |
| kubernetes.io/gce-pd | GCP | Persistent Disk |
| kubernetes.io/azure-disk | Azure | Managed Disk |
| kubernetes.io/azure-file | Azure | Azure Files |
| ebs.csi.aws.com | AWS (CSI) | EBS через CSI |
| pd.csi.storage.gke.io | GCP (CSI) | PD через CSI |
| rancher.io/local-path | kind | Локальний шлях |
| k8s.io/minikube-hostpath | minikube | Шлях хоста |
Частина 2: Створення StorageClasses
Розділ «Частина 2: Створення StorageClasses»2.1 Базовий StorageClass
Розділ «2.1 Базовий StorageClass»apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: standardprovisioner: kubernetes.io/aws-ebsparameters: type: gp2reclaimPolicy: DeletevolumeBindingMode: WaitForFirstConsumer2.2 AWS EBS StorageClass
Розділ «2.2 AWS EBS StorageClass»apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: fast-ebsprovisioner: ebs.csi.aws.comparameters: type: gp3 iopsPerGB: "50" throughput: "125" encrypted: "true" kmsKeyId: "arn:aws:kms:us-east-1:123456789:key/abc-123"reclaimPolicy: RetainvolumeBindingMode: WaitForFirstConsumerallowVolumeExpansion: true2.3 GCP Persistent Disk StorageClass
Розділ «2.3 GCP Persistent Disk StorageClass»apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: fast-ssdprovisioner: pd.csi.storage.gke.ioparameters: type: pd-ssd replication-type: regional-pd # Для HAreclaimPolicy: DeletevolumeBindingMode: WaitForFirstConsumerallowVolumeExpansion: true2.4 Azure Disk StorageClass
Розділ «2.4 Azure Disk StorageClass»apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: managed-premiumprovisioner: disk.csi.azure.comparameters: storageaccounttype: Premium_LRS kind: ManagedreclaimPolicy: DeletevolumeBindingMode: WaitForFirstConsumerallowVolumeExpansion: true2.5 Локальна розробка (kind/minikube)
Розділ «2.5 Локальна розробка (kind/minikube)»kind (використовує local-path-provisioner):
apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: local-pathprovisioner: rancher.io/local-pathreclaimPolicy: DeletevolumeBindingMode: WaitForFirstConsumerminikube:
apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: standardprovisioner: k8s.io/minikube-hostpathreclaimPolicy: DeletevolumeBindingMode: ImmediateЧастина 3: StorageClass за замовчуванням
Розділ «Частина 3: StorageClass за замовчуванням»3.1 Встановлення за замовчуванням
Розділ «3.1 Встановлення за замовчуванням»Лише один StorageClass повинен бути за замовчуванням. Позначте його анотацією:
apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: standard annotations: storageclass.kubernetes.io/is-default-class: "true" # Магічна анотаціяprovisioner: kubernetes.io/aws-ebsparameters: type: gp3Або змініть існуючий патчем:
k patch storageclass standard -p '{"metadata": {"annotations": {"storageclass.kubernetes.io/is-default-class": "true"}}}'3.2 Перевірка StorageClass за замовчуванням
Розділ «3.2 Перевірка StorageClass за замовчуванням»k get sc# NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE# standard (default) kubernetes.io/aws-ebs Delete WaitForFirstConsumer# fast-ssd kubernetes.io/aws-ebs Delete Immediate3.3 PVC без StorageClass
Розділ «3.3 PVC без StorageClass»Коли PVC не вказує storageClassName:
apiVersion: v1kind: PersistentVolumeClaimmetadata: name: my-claimspec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi # storageClassName не вказано — використовується за замовчуванням!Поведінка:
- Якщо StorageClass за замовчуванням існує — використовується він, запускається динамічне надання
- Якщо за замовчуванням немає — PVC залишається Pending, поки не з’явиться відповідний PV
3.4 Відмова від динамічного надання
Розділ «3.4 Відмова від динамічного надання»Щоб явно уникнути динамічного надання:
apiVersion: v1kind: PersistentVolumeClaimmetadata: name: static-only-claimspec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: "" # Порожній рядок = без динамічного наданняЧастина 4: Режими прив’язки томів
Розділ «Частина 4: Режими прив’язки томів»4.1 Immediate vs WaitForFirstConsumer
Розділ «4.1 Immediate vs WaitForFirstConsumer»┌──────────────────────────────────────────────────────────────────────┐│ Режими прив'язки томів ││ ││ IMMEDIATE WAITFORFIRSTCONSUMER ││ ───────── ──────────────────── ││ ││ PVC створено PVC створено ││ │ │ ││ ▼ ▼ ││ PV надано PVC залишається Pending ││ негайно │ ││ │ │ ││ │ Под заплановано ││ │ │ ││ │ ▼ ││ │ PV надано ││ │ (у тій самій зоні, що й Под) ││ │ │ ││ ▼ ▼ ││ Под заплановано Под може використовувати сховище ││ (може зазнати невдачі, ││ якщо неправильна зона!) ││ │└──────────────────────────────────────────────────────────────────────┘4.2 Чому WaitForFirstConsumer важливий
Розділ «4.2 Чому WaitForFirstConsumer важливий»Проблема з Immediate:
Вузол: us-east-1a Вузол: us-east-1b┌─────────────┐ ┌─────────────┐│ │ │ Под │ ← Планувальник розміщує Под тут│ │ │ (потребує ││ │ │ сховища) │└─────────────┘ └─────────────┘ ↑ │ Том EBS ✗ Том у неправильній зоні! (наданий ✗ Под не може запуститися! негайно в 1a)Рішення з WaitForFirstConsumer:
Вузол: us-east-1a Вузол: us-east-1b┌─────────────┐ ┌─────────────┐│ │ │ Под │ ← Планувальник розміщує Под тут│ │ │ (потребує ││ │ │ сховища) │└─────────────┘ └─────────────┘ ↑ │ Том EBS ✓ Том у правильній зоні! (наданий ✓ Под запускається успішно! в 1b ПІСЛЯ планування Пода)4.3 Коли використовувати кожен режим
Розділ «4.3 Коли використовувати кожен режим»| Режим | Випадок використання |
|---|---|
| Immediate | NFS, розподілене сховище, сховище без зон |
| WaitForFirstConsumer | Зональне сховище (EBS, GCE PD, Azure Disk), локальне сховище |
Частина 5: Розширення томів
Розділ «Частина 5: Розширення томів»5.1 Увімкнення розширення томів
Розділ «5.1 Увімкнення розширення томів»apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: expandableprovisioner: kubernetes.io/aws-ebsallowVolumeExpansion: true # Має бути true для зміни розміру PVCparameters: type: gp35.2 Розширення PVC
Розділ «5.2 Розширення PVC»# Оригінальний PVC з 10Gik get pvc my-claim# NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS# my-claim Bound pv-001 10Gi RWO expandable
# Змінити для запиту більше місцяk patch pvc my-claim -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'
# Або відредагувати вручнуk edit pvc my-claim# Змініть spec.resources.requests.storage на 20Gi5.3 Процес розширення
Розділ «5.3 Процес розширення»┌─────────────────────────────────────────────────────────────────────┐│ Процес розширення PVC ││ ││ 1. Редагування ──► 2. Контролер змінює ──► 3. Розширення ││ PVC (збільшити розмір базового сховища файлової ││ розмір) (напр., том EBS) системи ││ (при монтув.) ││ ││ Статус показує: ││ - "Resizing" — зміна розміру бекенду сховища ││ - "FileSystemResizePending" — очікування монтування Подом ││ ││ ⚠️ Примітка: Розширення потребує перезапуску Пода для деяких ││ provisioners │└─────────────────────────────────────────────────────────────────────┘5.4 Перевірка статусу розширення
Розділ «5.4 Перевірка статусу розширення»k describe pvc my-claim
# Шукайте conditions:# Conditions:# Type Status# ---- ------# FileSystemResizePending True # Очікування розширення файлової системи# Resizing True # Зміна розміру бекендуВажливо: Ви можете лише збільшувати розмір PVC. Зменшення не підтримується!
Частина 6: Параметри StorageClass
Розділ «Частина 6: Параметри StorageClass»6.1 Довідник параметрів
Розділ «6.1 Довідник параметрів»Параметри специфічні для provisioner. Поширені приклади:
AWS EBS (CSI):
parameters: type: gp3 # gp2, gp3, io1, io2, st1, sc1 iopsPerGB: "50" # Для gp3/io1/io2 throughput: "250" # Для gp3 (MiB/s) encrypted: "true" kmsKeyId: "arn:aws:kms:..." fsType: ext4 # ext4, xfsGCP PD (CSI):
parameters: type: pd-ssd # pd-standard, pd-ssd, pd-balanced replication-type: none # none, regional-pd disk-encryption-kms-key: "projects/..." fsType: ext4Azure Disk (CSI):
parameters: storageaccounttype: Premium_LRS # Standard_LRS, Premium_LRS, StandardSSD_LRS kind: Managed # Managed, Dedicated, Shared cachingMode: ReadOnly fsType: ext46.2 Параметри монтування
Розділ «6.2 Параметри монтування»apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: with-mount-optionsprovisioner: kubernetes.io/aws-ebsmountOptions: - debug - noatime - nodiratimeparameters: type: gp3 fsType: ext4Типові помилки
Розділ «Типові помилки»| Помилка | Проблема | Рішення |
|---|---|---|
| Кілька StorageClasses за замовчуванням | Непередбачувана поведінка | Лише один повинен бути за замовчуванням |
| Неправильний provisioner для платформи | PVC залишається Pending назавжди | Використовуйте правильний provisioner для вашої хмари |
| Режим Immediate з зональним сховищем | Поди не можуть змонтувати томи | Використовуйте WaitForFirstConsumer |
| Забули allowVolumeExpansion | Неможливо змінити розмір PVC пізніше | Завжди встановлюйте true, якщо не навмисно |
| Неправильні параметри для provisioner | Надання не вдається | Перевірте документацію provisioner |
| Спроба зменшити PVC | Не підтримується | Працює лише розширення |
Тест
Розділ «Тест»Q1: StorageClass за замовчуванням
Розділ «Q1: StorageClass за замовчуванням»Що відбувається, коли ви створюєте PVC без вказівки storageClassName у кластері зі StorageClass за замовчуванням?
Відповідь
PVC автоматично використовує StorageClass за замовчуванням і запускає динамічне надання. Новий PV буде створений автоматично provisioner-ом.
Q2: Відмова від динамічного надання
Розділ «Q2: Відмова від динамічного надання»Як створити PVC, який явно не використовує динамічне надання?
Відповідь
Встановіть storageClassName: "" (порожній рядок) у специфікації PVC. Це запобігає використанню будь-якого StorageClass, включно з тим, що за замовчуванням, і PVC буде прив’язуватися лише до вручну створених PV.
Q3: WaitForFirstConsumer
Розділ «Q3: WaitForFirstConsumer»Чому WaitForFirstConsumer важливий для хмарного сховища, як-от AWS EBS?
Відповідь
Томи EBS є специфічними для зони. З прив’язкою Immediate том може бути наданий в іншій зоні, ніж та, де заплановано Под, що спричинить помилки монтування. WaitForFirstConsumer відкладає надання до після планування Пода, забезпечуючи створення тому в тій самій зоні, що й Под.
Q4: Розширення тому
Розділ «Q4: Розширення тому»PVC використовує StorageClass з allowVolumeExpansion: false. Чи можна його розширити?
Відповідь
Ні. Розширення тому повинно бути увімкнене на StorageClass до того, як PVC можна буде розширити. Ви не можете змінити цей параметр після створення PVC (хіба що перестворите StorageClass і PVC).
Q5: Визначення за замовчуванням
Розділ «Q5: Визначення за замовчуванням»Як перевірити, який StorageClass є за замовчуванням?
Відповідь
k get scStorageClass за замовчуванням покаже (default) поруч зі своїм ім’ям. Або перевірте анотацію:
k get sc -o jsonpath='{.items[?(@.metadata.annotations.storageclass\.kubernetes\.io/is-default-class=="true")].metadata.name}'Q6: Різниця політик повернення
Розділ «Q6: Різниця політик повернення»Яка практична різниця між reclaimPolicy Delete та Retain у StorageClasses?
Відповідь
- Delete: При видаленні PVC динамічно наданий PV та базове сховище автоматично видаляються. Підходить для dev/test.
- Retain: При видаленні PVC PV стає “Released”, але сховище зберігається. Адміністратор повинен вручну очистити. Підходить для продакшен-даних.
Практична вправа: Динамічне надання
Розділ «Практична вправа: Динамічне надання»Сценарій
Розділ «Сценарій»Налаштуйте StorageClass та перевірте, що динамічне надання працює правильно.
Передумови
Розділ «Передумови»Вам потрібен кластер із працюючим storage provisioner. Kind та minikube мають вбудовані provisioners.
Завдання 1: Перевірити існуючі StorageClasses
Розділ «Завдання 1: Перевірити існуючі StorageClasses»# Подивитися, що доступноk get sc
# Перевірити, чи є за замовчуваннямk get sc -o custom-columns='NAME:.metadata.name,PROVISIONER:.provisioner,DEFAULT:.metadata.annotations.storageclass\.kubernetes\.io/is-default-class'Завдання 2: Створити StorageClass
Розділ «Завдання 2: Створити StorageClass»cat <<EOF | k apply -f -apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: fastprovisioner: rancher.io/local-path # Для kind; змініть для вашого кластераreclaimPolicy: DeletevolumeBindingMode: WaitForFirstConsumerallowVolumeExpansion: trueEOFЗавдання 3: Створити PVC з використанням StorageClass
Розділ «Завдання 3: Створити PVC з використанням StorageClass»cat <<EOF | k apply -f -apiVersion: v1kind: PersistentVolumeClaimmetadata: name: dynamic-pvcspec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: fastEOF
# Перевірте статус — має бути Pending (очікує споживача)k get pvc dynamic-pvcЗавдання 4: Створити Под для запуску надання
Розділ «Завдання 4: Створити Под для запуску надання»cat <<EOF | k apply -f -apiVersion: v1kind: Podmetadata: name: dynamic-podspec: containers: - name: app image: busybox:1.36 command: ['sh', '-c', 'echo "Dynamically provisioned!" > /data/message; sleep 3600'] volumeMounts: - name: storage mountPath: /data volumes: - name: storage persistentVolumeClaim: claimName: dynamic-pvcEOFЗавдання 5: Перевірити динамічне надання
Розділ «Завдання 5: Перевірити динамічне надання»# PVC тепер має бути Boundk get pvc dynamic-pvc# STATUS: Bound
# PV було створено автоматичноk get pv# Має показати динамічно названий PV, як-от pvc-xxxxx
# Перевірити деталі PVk get pv -o jsonpath='{.items[0].spec.storageClassName}'# Має показати: fast
# Перевірити, що Под працюєk exec dynamic-pod -- cat /data/messageЗавдання 6: Перевірити StorageClass за замовчуванням (опціонально)
Розділ «Завдання 6: Перевірити StorageClass за замовчуванням (опціонально)»# Зробити наш StorageClass за замовчуваннямk patch sc fast -p '{"metadata": {"annotations": {"storageclass.kubernetes.io/is-default-class": "true"}}}'
# Створити PVC без storageClassNamecat <<EOF | k apply -f -apiVersion: v1kind: PersistentVolumeClaimmetadata: name: default-pvcspec: accessModes: - ReadWriteOnce resources: requests: storage: 500Mi # storageClassName не вказано — використовується за замовчуванням!EOF
# Перевірити, що використовується клас за замовчуваннямk get pvc default-pvc -o jsonpath='{.spec.storageClassName}'# Має показати: fastКритерії успіху
Розділ «Критерії успіху»- StorageClass створено успішно
- PVC залишається Pending до створення Пода (WaitForFirstConsumer)
- PV автоматично створюється при плануванні Пода
- Под може записувати дані на динамічно надане сховище
- Розуміння зв’язку між SC → PVC → PV
Очищення
Розділ «Очищення»k delete pod dynamic-podk delete pvc dynamic-pvc default-pvck delete sc fastПрактичні вправи
Розділ «Практичні вправи»Вправа 1: Список StorageClasses (1 хв)
Розділ «Вправа 1: Список StorageClasses (1 хв)»# Завдання: Вивести всі StorageClasses та визначити за замовчуваннямk get scВправа 2: Створити базовий StorageClass (2 хв)
Розділ «Вправа 2: Створити базовий StorageClass (2 хв)»# Завдання: Створити StorageClass "slow" з provisioner rancher.io/local-path# reclaimPolicy: RetainВправа 3: Встановити StorageClass за замовчуванням (1 хв)
Розділ «Вправа 3: Встановити StorageClass за замовчуванням (1 хв)»# Завдання: Зробити StorageClass "standard" за замовчуванням# Використовуйте анотацію: storageclass.kubernetes.io/is-default-class: "true"Вправа 4: PVC з конкретним StorageClass (2 хв)
Розділ «Вправа 4: PVC з конкретним StorageClass (2 хв)»# Завдання: Створити PVC "data-pvc", що запитує 5Gi з StorageClass "fast"Вправа 5: PVC без динамічного надання (2 хв)
Розділ «Вправа 5: PVC без динамічного надання (2 хв)»# Завдання: Створити PVC, який не використовуватиме жоден StorageClass# Підказка: storageClassName: ""Вправа 6: Перевірити, чому PVC у стані Pending (2 хв)
Розділ «Вправа 6: Перевірити, чому PVC у стані Pending (2 хв)»# Завдання: Діагностувати, чому PVC застряг у стані Pendingk describe pvc <name># Перевірте секцію Events на наявність помилокВправа 7: Увімкнути розширення тому (2 хв)
Розділ «Вправа 7: Увімкнути розширення тому (2 хв)»# Завдання: Створити StorageClass з увімкненим розширенням тому# Ключове поле: allowVolumeExpansion: trueВправа 8: Перевірити режим прив’язки (1 хв)
Розділ «Вправа 8: Перевірити режим прив’язки (1 хв)»# Завдання: Перевірити volumeBindingMode StorageClass "standard"k get sc standard -o jsonpath='{.volumeBindingMode}'Наступний модуль
Розділ «Наступний модуль»Переходьте до Модуль 4.4: Знімки томів та клонування, щоб дізнатися про функції резервного копіювання та захисту даних.