1 - Томи

Томи Kubernetes дають контейнерам у Podʼі змогу отримувати доступ до даних і обмінюватися ними через файлову систему. Існують різні види томів, які можна використовувати для різних цілей, зокрема:

  • заповнення файлу конфігурації на основі ConfigMap або Secret
  • надання Podʼу тимчасового робочого простору
  • спільне використання файлової системи двома різними контейнерами в одному Podʼі
  • спільне використання файлової системи двома різними Podʼами (навіть якщо ці Podʼи працюють на різних вузлах)
  • надійне зберігання даних, щоб вони залишалися доступними, навіть якщо Pod перезапускається або замінюється
  • передавання конфігураційної інформації застосунку, що працює в контейнері, на основі відомостей про Pod, у якому перебуває контейнер (наприклад, повідомлення sidecar-контейнеру, у якому просторі імен працює Pod)
  • надання доступу лише для читання до даних в іншому образі контейнера

Обмін даними може відбуватися між різними локальними процесами всередині контейнера, або між різними контейнерами, або між Podʼами.

Чому томи важливі

  • Збереження даних: Файли на диску в контейнері є ефемерними, що створює певні проблеми для нетривіальних застосунків, які працюють у контейнерах. Одна з проблем виникає, коли контейнер аварійно завершує роботу або зупиняється: стан контейнера не зберігається, тому всі файли, створені або змінені протягом життя контейнера, втрачаються. Після аварійного завершення kubelet перезапускає контейнер із чистим станом.

  • Спільне сховище: Ще одна проблема виникає, коли в Pod працює кілька контейнерів, яким потрібно спільно використовувати файли. Налаштувати спільну файлову систему для всіх контейнерів і отримати до неї доступ може бути складно.

Абстракція тому в Kubernetes може допомогти розвʼязати обидві ці проблеми.

Перш ніж дізнатися про томи, PersistentVolumes та PersistentVolumeClaims, вам слід прочитати про Podʼи і переконатися, що ви розумієте, як Kubernetes використовує Podʼи для запуску контейнерів.

Як томи працюють

Kubernetes підтримує багато типів томів. Pod може використовувати будь-яку кількість типів томів одночасно. Типи ефемерних томів мають життєвий цикл, повʼязаний із конкретним Podʼом, а постійні томи існують довше за будь-який окремий Pod. Коли Pod припиняє існування, Kubernetes знищує ефемерні томи; однак Kubernetes не знищує постійні томи. Для будь-якого виду тому в певному Podʼі дані зберігаються під час перезапусків контейнерів.

По суті, том — це тека, можливо, з деякими даними, доступна контейнерам у Podʼі. Те, як ця тека зʼявляється, який носій її підтримує і який вона має вміст, визначається конкретним типом тому.

Щоб використати том, вкажіть томи, які потрібно надати Podʼу, у .spec.volumes і вкажіть, куди монтувати ці томи в контейнерах, у .spec.containers[*].volumeMounts.

Коли Pod запускається, процес у контейнері бачить файлову систему, складену з початкового вмісту образу контейнера і томів (якщо їх визначено), змонтованих усередині контейнера. Процес бачить кореневу файлову систему, яка спочатку відповідає вмісту образу контейнера. Будь-які записи в цій ієрархії файлової системи, якщо їх дозволено, впливають на те, що процес бачить під час наступного доступу до файлової системи. Томи монтуються за вказаними шляхами у файловій системі контейнера. Для кожного контейнера, визначеного в Podʼі, потрібно окремо вказати, куди монтувати кожен том, який він використовує.

Томи не можуть монтуватися всередині інших томів (але дивіться Використання subPath про споріднений механізм). Також том не може містити жорстке посилання на щось в іншому томі.

Типи томів

Kubernetes підтримує кілька типів томів.

configMap

ConfigMap надає спосіб вставляти конфігураційні дані в Podʼи. На дані, збережені в ConfigMap, можна посилатися в томі типу configMap, а потім їх використовуватимуть контейнеризовані застосунки, що працюють у Podʼі.

Посилаючись на ConfigMap, ви вказуєте в томі назву ConfigMap. Ви можете налаштувати шлях для конкретного запису в ConfigMap. Наведена нижче конфігурація показує, як змонтувати ConfigMap log-config у Pod з назвою configmap-pod:

apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
    - name: test
      image: busybox:1.28
      command: ['sh', '-c', 'echo "The app is running!" && tail -f /dev/null']
      volumeMounts:
        - name: config-vol
          mountPath: /etc/config
  volumes:
    - name: config-vol
      configMap:
        name: log-config
        items:
          - key: log_level
            path: log_level.conf

ConfigMap log-config монтується як том, і весь вміст, збережений у його записі log_level, монтується в Pod за шляхом /etc/config/log_level.conf. Зверніть увагу, що цей шлях утворюється з mountPath тому та path із ключем log_level.

Примітка:

  • Ви повинні створити ConfigMap, перш ніж ви зможете його використовувати.

  • ConfigMap завжди монтується як readOnly.

  • Контейнер, який використовує ConfigMap як монтування тому subPath, не отримуватиме оновлень, коли ConfigMap змінюється.

  • Текстові дані надаються у вигляді файлів у кодуванні UTF-8. Для інших кодувань символів використовуйте binaryData.

downwardAPI

Том downwardAPI робить дані downward API доступними для застосунків. У томі ви можете знайти надані дані у вигляді файлів лише для читання у форматі звичайного тексту.

Примітка:

Контейнер, який використовує downward API як монтування тому subPath, не отримує оновлень, коли значення полів змінюються.

Докладніше дивіться в Передавання інформації про Pod контейнерам через файли.

emptyDir

Для Podʼа, який визначає том emptyDir, том створюється, коли Pod призначається вузлу. Як випливає з назви, том emptyDir спочатку порожній. Усі контейнери в Podʼі можуть читати й записувати ті самі файли в томі emptyDir, хоча цей том може бути змонтований за однаковими або різними шляхами в кожному контейнері. Коли Pod вилучається з вузла з будь-якої причини, дані в emptyDir видаляються назавжди.

Примітка:

Аварійне завершення контейнера не вилучає Pod із вузла. Дані в томі emptyDir зберігаються під час аварійних завершень контейнера.

Деякі способи використання emptyDir:

  • робочий простір, наприклад, для сортування злиттям на диску
  • контрольні точки тривалих обчислень для відновлення після збоїв
  • зберігання файлів, які отримує контейнер менеджера вмісту, поки контейнер вебсервера обслуговує ці дані

Поле emptyDir.medium визначає, де зберігаються томи emptyDir. Стандартно томи emptyDir зберігаються на носії вузла, наприклад, на диску, SSD або в мережевому сховищі, залежно від вашого середовища. Якщо встановити поле emptyDir.medium у "Memory", Kubernetes натомість монтує tmpfs (файлову систему в оперативній памʼяті). Хоча tmpfs дуже швидкий, памʼятайте, що, на відміну від дисків, файли, які ви записуєте, враховуються в обмеженні памʼяті контейнера, який їх записав.

Для стандартного носія можна вказати обмеження розміру, яке обмежує місткість тому emptyDir. Простір виділяється з тимчасового сховища вузла. Якщо воно заповниться з іншого джерела (наприклад, файлами логів або накладеннями образів), місце в emptyDir може закінчитися раніше, ніж буде досягнуто цього обмеження. Якщо розмір не вказано, томи в памʼяті отримують розмір, що дорівнює памʼяті вузла, доступній для розподілу.

Увага:

Перегляньте тут моменти, які слід врахувати щодо керування ресурсами під час використання emptyDir у памʼяті.
СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the EmptyDirVolumeMode feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Поле emptyDir.mode дозволяє встановити біти дозволів Unix на теці emptyDir, вказавши значення від 0000 до 01777 (у вісімковій системі). Це відповідає тому самому шаблону, що й поле defaultMode у томах Secret і ConfigMap. Якщо mode не вказано, тека створюється зі стандартними дозволами 0777.

Встановлення власного режиму корисне, коли ви хочете обмежити доступ лише власником і групою (наприклад, 0750) або встановити sticky bit на спільній теці, щоб лише власники файлів могли видаляти свої файли (наприклад, 01777).

Примітка:

Якщо fsGroup встановлено в контексті безпеки Podʼа, групові дозволи, застосовані fsGroup, перевизначають mode, вказаний тут. Поле mode не впливає на Windows.

Приклад конфігурації emptyDir

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
      sizeLimit: 500Mi

Приклад конфігурації emptyDir у памʼяті

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
      sizeLimit: 500Mi
      medium: Memory

emptyDir і зміна розміру Podʼа на місці

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the InPlacePodVerticalScalingMemoryBackedVolumes feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Коли функціональну можливість InPlacePodVerticalScalingMemoryBackedVolumes ввімкнено, ви можете динамічно змінювати sizeLimit томів emptyDir у памʼяті (medium: Memory) без перезапуску Podʼа або його контейнерів.

Докладніше дивіться в Зміна розміру ресурсів CPU та памʼяті, призначених контейнерам.

Приклад конфігурації дозволів emptyDir

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
      mode: 01777

fc (fibre channel)

Тип тому fc дозволяє монтувати в Pod наявний блоковий том сховища Fibre Channel. Ви можете вказати одне чи кілька цільових всесвітніх імен (world wide names, WWN) за допомогою параметра targetWWNs у конфігурації тому. Якщо вказано кілька WWN, targetWWNs очікує, що ці WWN належать до багатошляхових зʼєднань.

Примітка:

Ви повинні заздалегідь налаштувати зонування FC SAN, щоб виділити та маскувати ці LUN (томи) для цільових WWN, щоб хости Kubernetes могли отримати до них доступ.

gcePersistentDisk (застаріло)

У Kubernetes 1.37 усі операції для вбудованого типу gcePersistentDisk перенаправляються на драйвер CSI pd.csi.storage.gke.io.

Вбудований драйвер сховища gcePersistentDisk визнано застарілим у випуску Kubernetes v1.17, а потім повністю вилучено у випуску v1.28.

Проєкт Kubernetes пропонує натомість використовувати сторонній драйвер сховища Google Compute Engine Persistent Disk CSI.

gitRepo (вимкнено)

Попередження:

Kubernetes 1.37 не містить драйвера томів gitRepo. Останньою версією, яка надавала можливість використовувати цей драйвер, була Kubernetes v1.35, а застарілим він став із мінорного випуску v1.11.

Щоб надати Pod зі змонтованим репозиторієм Git, ви можете змонтувати том emptyDir в init-контейнер, який клонує репозиторій за допомогою Git, а потім змонтувати EmptyDir у контейнер Podʼа.


Ви можете обмежити використання томів gitRepo у своєму кластері за допомогою політик, таких як ValidatingAdmissionPolicy. Ви можете використати наведений нижче вираз Common Expression Language (CEL) як частину політики, щоб відхиляти використання томів gitRepo:

!has(object.spec.volumes) || !object.spec.volumes.exists(v, has(v.gitRepo))

hostPath

Том hostPath монтує файл або теку з файлової системи вузла-хоста у ваш Pod. Більшості Podʼів це не потрібно, але це потужний запасний вихід для деяких застосунків.

Попередження:

Використання типу тому hostPath створює багато ризиків для безпеки. Якщо можете уникнути використання тому hostPath, зробіть це. Наприклад, натомість визначте й використовуйте local PersistentVolume.

Якщо ви обмежуєте доступ до певних тек на вузлі за допомогою перевірки під час допуску, це обмеження є ефективним лише тоді, коли ви додатково вимагаєте, щоб усі монтування цього тому hostPath були лише для читання. Якщо ви дозволяєте ненадійному Podʼу монтувати будь-який шлях хоста для читання й запису, контейнери цього Podʼа можуть зловжити цим монтуванням хоста для читання й запису.


Будьте обережні, використовуючи томи hostPath, незалежно від того, чи монтуються вони лише для читання, чи для читання й запису, оскільки:

  • Доступ до файлової системи хоста може розкрити привілейовані системні облікові дані (наприклад, для kubelet) або привілейовані API (наприклад, сокет середовища виконання контейнерів), які можна використати для виходу з контейнера або для атаки на інші частини кластера.
  • Podʼи з однаковою конфігурацією (наприклад, створені з PodTemplate) можуть поводитися по-різному на різних вузлах через різні файли на вузлах.
  • Використання тому hostPath не вважається використанням ефемерного сховища. Ви маєте самостійно стежити за використанням диска, оскільки надмірне використання диска томами hostPath призведе до тиску на диск вузла.

Деякі способи використання hostPath:

  • запуск контейнера, якому потрібен доступ до системних компонентів рівня вузла (наприклад, контейнера, який передає системні логи до центрального місця, отримуючи доступ до цих логів через монтування /var/log лише для читання)
  • надання конфігураційного файлу, що зберігається на хост-системі, у режимі лише для читання статичному Podʼу; на відміну від звичайних Podʼів, статичні Podʼи не можуть отримувати доступ до ConfigMaps

Типи томів hostPath

Крім обовʼязкової властивості path, ви можете за потреби вказати type для тому hostPath.

Доступні значення для type:

ЗначенняПоведінка
‌""Порожній рядок (стандартно) призначений для зворотної сумісності й означає, що перед монтуванням тому hostPath перевірки не виконуватимуться.
DirectoryOrCreateЯкщо за вказаним шляхом нічого немає, там за потреби буде створено порожню теку з дозволами 0755, з тією самою групою та власником, що й у kubelet.
DirectoryТека має існувати за вказаним шляхом.
FileOrCreateЯкщо за вказаним шляхом нічого немає, там за потреби буде створено порожній файл із дозволами 0644, з тією самою групою та власником, що й у kubelet.
FileПовинен існувати файл за вказаним шляхом.
SocketМає існувати UNIX-сокет за вказаним шляхом.
CharDevice(Лише вузли Linux) Має існувати символьний пристрій за вказаним шляхом.
BlockDevice(Лише вузли Linux) Має існувати блоковий пристрій за вказаним шляхом.

Увага:

Режим FileOrCreate не створює батьківську теку файлу. Якщо батьківської теки змонтованого файлу не існує, Podʼу не вдасться запуститися. Щоб забезпечити роботу цього режиму, можна спробувати монтувати теки та файли окремо, як показано в прикладі FileOrCreate для hostPath.

Деякі файли або теки, створені на базових хостах, можуть бути доступні лише користувачу root. Тоді вам потрібно або запускати процес як root у привілейованому контейнері, або змінити дозволи файлів на хості, щоб читати з тому hostPath або записувати в нього.

Приклад конфігурації hostPath


---
# Цей маніфест монтує /data/foo на вузлі як /foo всередині
# єдиного контейнера, який працює в межах Podʼа hostpath-example-linux
#
# Монтування в контейнер тільки для читання
apiVersion: v1
kind: Pod
metadata:
  name: hostpath-example-linux
spec:
  os: { name: linux }
  nodeSelector:
    kubernetes.io/os: linux
  containers:
  - name: example-container
    image: registry.k8s.io/test-webserver
    volumeMounts:
    - mountPath: /foo
      name: example-volume
      readOnly: true
  volumes:
  - name: example-volume
    # монтувати /data/foo, але тільки якщо ця тека вже існує
    hostPath:
      path: /data/foo # розташування теки на вузлі
      type: Directory # це поле є необовʼязковим

---
# Цей маніфест монтує C:\Data\foo на вузлі як C:\foo всередині
# єдиного контейнера, який працює в межах Podʼа hostpath-example-windows
#
# Монтування в контейнер тільки для читання
apiVersion: v1
kind: Pod
metadata:
  name: hostpath-example-windows
spec:
  os: { name: windows }
  nodeSelector:
    kubernetes.io/os: windows
  containers:
  - name: example-container
    image: microsoft/windowsservercore:1709
    volumeMounts:
    - name: example-volume
      mountPath: "C:\\foo"
      readOnly: true
  volumes:
    # монтувати C:\Data\foo з вузла, але тільки якщо ця тека вже існує
  - name: example-volume
      hostPath:
        path: "C:\\Data\\foo" # розташування теки на вузлі
        type: Directory       # це поле є необовʼязковим

Приклад конфігурації hostPath для FileOrCreate

У наведеному нижче маніфесті визначено Pod, який монтує /var/local/aaa всередині єдиного контейнера Podʼа. Якщо на вузлі ще немає шляху /var/local/aaa, kubelet створює його як теку, а потім монтує в Pod.

Якщо /var/local/aaa вже існує, але не є текою, Pod завершується збоєм. Крім того, kubelet намагається створити файл /var/local/aaa/1.txt усередині цієї теки (з погляду хоста); якщо за цим шляхом уже щось існує і це не звичайний файл, Pod завершується збоєм.

Ось приклад маніфесту:

apiVersion: v1
kind: Pod
metadata:
  name: test-webserver
spec:
  os: { name: linux }
  nodeSelector:
    kubernetes.io/os: linux
  containers:
  - name: test-webserver
    image: registry.k8s.io/test-webserver:latest
    volumeMounts:
    - mountPath: /var/local/aaa
      name: mydir
    - mountPath: /var/local/aaa/1.txt
      name: myfile
  volumes:
  - name: mydir
    hostPath:
      # Переконайтеся, що теку файлу створено.
      path: /var/local/aaa
      type: DirectoryOrCreate
  - name: myfile
    hostPath:
      path: /var/local/aaa/1.txt
      type: FileOrCreate

image

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.36; (стандартно увімкнено)
More information about this feature

This is a stable feature in Kubernetes, and has been since version 1.36. It was first available in the v1.31 release.

Джерело тому image представляє обʼєкт OCI (образ контейнера або артефакт), який доступний на хост-машині kubelet.

Ось приклад використання джерела тому image:

apiVersion: v1
kind: Pod
metadata:
  name: image-volume
spec:
  containers:
  - name: shell
    command: ["sleep", "infinity"]
    image: debian
    volumeMounts:
    - name: volume
      mountPath: /volume
  volumes:
  - name: volume
    image:
      reference: quay.io/crio/artifact:v2
      pullPolicy: IfNotPresent

Том розвʼязується під час запуску Podʼа залежно від значення pullPolicy:

Always
kubelet завжди намагається завантажити посилання. Якщо завантаження не вдається, kubelet переводить Pod у стан Failed.
Never
kubelet ніколи не завантажує посилання й використовує лише локальний образ або артефакт. Pod переходить у стан Failed, якщо будь-які шари образу ще не присутні локально або якщо маніфест цього образу ще не закешовано.
IfNotPresent
kubelet завантажує посилання, якщо його ще немає на диску. Pod переходить у стан Failed, якщо посилання немає й завантаження не вдається.

Том розвʼязується повторно, якщо Pod видаляють і створюють заново, тобто новий віддалений вміст стане доступним після повторного створення Podʼа. Збій розвʼязання або завантаження образу під час запуску Podʼа заблокує запуск контейнерів і може додати значну затримку. Спроби після збоїв повторюватимуться за звичайним механізмом backoff для томів, а про збої буде повідомлено в полях reason і message Podʼа.

Типи обʼєктів, які може монтувати цей том, визначаються реалізацією середовища виконання контейнерів на хост-машині. Вони мають включати щонайменше всі дійсні типи, які підтримує поле образу контейнера. Обʼєкт OCI монтується в одну теку (spec.containers[*].volumeMounts[*].mountPath) і лише для читання.

Крім того:

  • Монтування subPath або subPathExpr для контейнерів (spec.containers[*].volumeMounts[*].subPath, spec.containers[*].volumeMounts[*].subPathExpr) підтримуються лише починаючи з Kubernetes v1.33.
  • Поле spec.securityContext.fsGroupChangePolicy не має жодного ефекту для цього типу тому.
  • Контролер допуску AlwaysPullImages також працює для цього джерела тому, як і для образів контейнерів.

Для типу image доступні такі поля:

reference
Посилання на артефакт, який слід використовувати. Наприклад, ви можете вказати registry.k8s.io/conformance:v1.37.0, щоб завантажити файли з образу тестів на відповідність Kubernetes. Працює так само, як pod.spec.containers[*].image. Секрети завантаження образів збираються так само, як для образу контейнера: шляхом пошуку облікових даних вузла, секретів завантаження образів ServiceAccount і секретів завантаження образів зі специфікації Podʼа. Це поле є необовʼязковим, щоб керування конфігурацією вищого рівня могло задавати стандартні значення або перевизначати образи контейнерів у контролерах робочих навантажень, таких як Deployments і StatefulSets. Докладніше про образи контейнерів.
pullPolicy
Політика завантаження обʼєктів OCI. Можливі значення: Always, Never або IfNotPresent. Стандартно Always, якщо вказано теґ :latest, інакше IfNotPresent.

Докладніше про використання цього джерела тому дивіться в прикладі Використання тому image з Podʼом.

Статус Podʼа та томи image

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.35; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the ImageVolumeWithDigest feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Якщо у вашому кластері ввімкнено функціональну можливість ImageVolumeWithDigest, то щоразу, коли ви вказуєте том image для Podʼа, kubelet оновлює статус Podʼа, щоб записати digest образу контейнера, який використовується як джерело тому.

Ось спрощений приклад запущеного Podʼа у вигляді YAML, зокрема з оновленням статусу. Зверніть увагу на нове поле ImageRef у volumeMounts у статусі контейнера.

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  namespace: default
spec:
  containers:
  - name: shell
    command: ["sleep", "infinity"]
    image: docker.io/library/debian:12
    volumeMounts:
    - name: artifact
      mountPath: /data
  volumes:
  - name: artifact
    image:
      reference: quay.io/crio/artifact:v2
      pullPolicy: IfNotPresent
status:
  containerStatuses:
  - containerID: containerd://examplecontainerid1234567890abcdef
    image: docker.io/library/debian:12
    imageID: docker-pullable://docker.io/library/debian@sha256:3f1d6c17773a45c97bd8f158d665c9709d7b29ed7917ac934086ad96f92e4510
    volumeMounts:
    - name: artifact
      mountPath: /data
      readOnly: true
      imageRef: quay.io/crio/artifact@sha256:abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890

iscsi

Том iscsi дозволяє монтувати наявний том iSCSI (SCSI через IP) у ваш Pod. На відміну від emptyDir, який стирається, коли Pod вилучається, вміст тому iscsi зберігається, а том лише розмонтовується. Це означає, що том iSCSI можна попередньо заповнити даними, і ці дані можна спільно використовувати між Podʼами.

Примітка:

Вам потрібно мати власний сервер iSCSI, на якому створено том, перш ніж ви зможете його використовувати.

Особливість iSCSI полягає в тому, що його можуть одночасно монтувати кілька споживачів лише для читання. Це означає, що ви можете попередньо заповнити том своїм набором даних, а потім паралельно надавати його зі стількох Podʼів, скільки потрібно. На жаль, томи iSCSI може монтувати лише один споживач у режимі читання й запису. Одночасний запис не дозволений.

local

Том local представляє змонтований локальний пристрій зберігання, такий як диск, розділ або тека.

Локальні томи можна використовувати лише як статично створені PersistentVolume. Динамічне надання не підтримується.

Порівняно з томами hostPath, томи local використовуються довговічно й переносно, без ручного планування Podʼів на вузли. Система знає про обмеження вузла для тому, переглядаючи спорідненість вузла в PersistentVolume.

Однак томи local залежать від доступності базового вузла й підходять не для всіх застосунків. Якщо вузол стає несправним, том local стає недоступним для Podʼа. Pod, який використовує цей том, не може працювати. Застосунки, що використовують томи local, мають бути здатні витримувати таку знижену доступність, а також потенційну втрату даних, залежно від характеристик надійності базового диска.

У наведеному нижче прикладі показано PersistentVolume, що використовує том local і nodeAffinity:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 100Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /mnt/disks/ssd1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - example-node

Під час використання томів local потрібно встановити nodeAffinity у PersistentVolume. Планувальник Kubernetes використовує nodeAffinity PersistentVolume, щоб планувати ці Podʼи на правильний вузол.

volumeMode PersistentVolume можна встановити в "Block" (замість стандартного значення "Filesystem"), щоб надати локальний том як необроблений блоковий пристрій.

Під час використання локальних томів рекомендується створити StorageClass із volumeBindingMode, встановленим у WaitForFirstConsumer. Докладніше дивіться в прикладі StorageClass для локальних томів. Відкладена привʼязка томів гарантує, що рішення про привʼязку PersistentVolumeClaim також враховуватиме інші обмеження вузла, які може мати Pod, такі як вимоги до ресурсів вузла, селектори вузлів, спорідненість і антиспорідненість Podʼів.

Для кращого керування життєвим циклом локального тому можна окремо запустити зовнішній статичний provisioner. Зверніть увагу, що цей provisioner поки не підтримує динамічне надання. Приклад запуску зовнішнього локального provisioner дивіться в посібнику користувача local volume provisioner.

Примітка:

Локальний PersistentVolume потребує ручного очищення й видалення користувачем, якщо для керування життєвим циклом тому не використовується зовнішній статичний provisioner.

nfs

Том nfs дозволяє монтувати наявний спільний ресурс NFS (Network File System) у Pod. На відміну від emptyDir, який стирається, коли Pod вилучається, вміст тому nfs зберігається, а том лише розмонтовується. Це означає, що том NFS можна попередньо заповнити даними, і ці дані можна спільно використовувати між Podʼами. NFS можуть одночасно монтувати кілька записувачів.

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /my-nfs-data
      name: test-volume
  volumes:
  - name: test-volume
    nfs:
      server: my-nfs-server.example.com
      path: /my-nfs-volume
      readOnly: true

Примітка:

Щоб використовувати NFS, потрібно мати власний запущений сервер NFS з експортованим спільним ресурсом.

Також зверніть увагу, що ви не можете вказувати параметри монтування NFS у специфікації Podʼа. Ви можете встановити параметри монтування на боці сервера або використовувати /etc/nfsmount.conf. Ви також можете монтувати томи NFS через PersistentVolumes, які дозволяють встановлювати параметри монтування.

persistentVolumeClaim

Том persistentVolumeClaim використовується для монтування PersistentVolume у Pod. PersistentVolumeClaims — це спосіб для користувачів «запросити» надійне сховище (наприклад, том iSCSI), не знаючи деталей конкретного хмарного середовища.

Докладніше дивіться в інформації про PersistentVolumes.

portworxVolume (застаріло)

СТАН ФУНКЦІОНАЛУ: Deprecated since Kubernetes v1.25

portworxVolume — це еластичний рівень блокового сховища, який працює в гіперконвергентному режимі з Kubernetes. Portworx визначає відбитки сховища на сервері, розподіляє його за рівнями на основі можливостей і агрегує місткість на кількох серверах. Portworx працює в гостьовій системі віртуальних машин або на вузлах Linux без віртуалізації (bare metal).

portworxVolume можна створити динамічно через Kubernetes або попередньо надати й послатися на нього в Podʼі. Ось приклад Podʼа, який посилається на попередньо наданий том Portworx:

apiVersion: v1
kind: Pod
metadata:
  name: test-portworx-volume-pod
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /mnt
      name: pxvol
  volumes:
  - name: pxvol
    # Цей том Portworx повинен вже існувати.
    portworxVolume:
      volumeID: "pxvol"
      fsType: "<fs-type>"

Примітка:

Переконайтеся, що у вас є наявний PortworxVolume з назвою pxvol, перш ніж використовувати його в Podʼі.

Міграція на Portworx CSI

This is a stable feature in Kubernetes, and has been since the 1.33 release. You can no longer toggle this feature (the associated feature gate has been removed).

У Kubernetes 1.37 усі операції для вбудованих томів Portworx стандартно перенаправляються на драйвер Container Storage Interface (CSI) pxd.portworx.com. Portworx CSI Driver має бути встановлений у кластері.

projected

Проєкційний том зіставляє кілька наявних джерел томів з однією текою. Докладніше дивіться проєкційні томи.

secret

Том secret використовується для передавання конфіденційної інформації, такої як паролі, у Podʼи. Ви можете зберігати Secrets в API Kubernetes і монтувати їх як файли для використання Podʼами без прямої привʼязки до Kubernetes. Томи secret підтримуються tmpfs (файловою системою в оперативній памʼяті), тому вони ніколи не записуються на енергонезалежне сховище.

Примітка:

  • Ви повинні створити Secret в API Kubernetes, перш ніж ви зможете його використовувати.

  • Secret завжди монтується як readOnly.

  • Контейнер, який використовує Secret як монтування тому subPath, не отримуватиме оновлень Secret.

Докладніше дивіться Налаштування Secrets.

Використання subPath

Іноді корисно спільно використовувати один том для кількох цілей в одному Podʼі. Властивість volumeMounts[*].subPath задає підшлях усередині вказаного тому замість його кореня.

У наведеному нижче прикладі показано, як налаштувати Pod зі стеком LAMP (Linux, Apache, MySQL, PHP) за допомогою одного спільного тому. Цю конфігурацію subPath не рекомендується використовувати в промисловому середовищі.

Код і ресурси PHP-застосунку зіставляються з текою html тому, а база даних MySQL зберігається в теці mysql тому. Наприклад:

apiVersion: v1
kind: Pod
metadata:
  name: my-lamp-site
spec:
    containers:
    - name: mysql
      image: mysql
      env:
      - name: MYSQL_ROOT_PASSWORD
        value: "rootpasswd"
      volumeMounts:
      - mountPath: /var/lib/mysql
        name: site-data
        subPath: mysql
    - name: php
      image: php:7.0-apache
      volumeMounts:
      - mountPath: /var/www/html
        name: site-data
        subPath: html
    volumes:
    - name: site-data
      persistentVolumeClaim:
        claimName: my-lamp-site-data

Використання subPath із розширеними змінними середовища

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.17

Використовуйте поле subPathExpr, щоб будувати назви тек subPath зі змінних середовища downward API. Властивості subPath та subPathExpr є взаємовиключними.

У цьому прикладі Pod використовує subPathExpr, щоб створити теку pod1 усередині тому hostPath /var/log/pods. Том hostPath отримує назву Pod із downwardAPI. Тека хоста /var/log/pods/pod1 монтується в /logs у контейнері.

apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
  - name: container1
    env:
    - name: POD_NAME
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: metadata.name
    image: busybox:1.28
    command: [ "sh", "-c", "while [ true ]; do echo 'Hello'; sleep 10; done | tee -a /logs/hello.txt" ]
    volumeMounts:
    - name: workdir1
      mountPath: /logs
      # Для змінних використовуються круглі дужки (не фігурні).
      subPathExpr: $(POD_NAME)
  restartPolicy: Never
  volumes:
  - name: workdir1
    hostPath:
      path: /var/log/pods

Ресурси

Носій (наприклад, диск або SSD) тому emptyDir визначається носієм файлової системи, на якій розташована коренева тека kubelet (зазвичай /var/lib/kubelet). Немає обмежень на те, скільки місця може використовувати том emptyDir або hostPath, і немає ізоляції між контейнерами або Podʼами.

Щоб дізнатися про запит місця за допомогою специфікації ресурсів, дивіться як керувати ресурсами.

Зовнішні втулки томів

До зовнішніх втулків томів належать Container Storage Interface (CSI), а також FlexVolume (застарілий). Ці втулки дозволяють постачальникам сховищ створювати власні втулки сховища, не додаючи їхній вихідний код до репозиторію Kubernetes.

Раніше всі втулки томів були «вбудованими». «Вбудовані» втулки збиралися, компонувалися, компілювалися й постачалися разом з основними бінарними файлами Kubernetes. Це означало, що додавання нової системи зберігання до Kubernetes (втулка томів) вимагало внесення коду в основний репозиторій коду Kubernetes.

І CSI, і FlexVolume дозволяють розробляти втулки томів незалежно від кодової бази Kubernetes і розгортати (встановлювати) їх у кластерах Kubernetes як розширення.

Постачальникам сховищ, які хочуть створити зовнішній втулок томів, варто звернутися до FAQ про втулки томів.

csi

Container Storage Interface (CSI) визначає стандартний інтерфейс для систем оркестрування контейнерів (таких як Kubernetes), щоб надавати довільні системи зберігання своїм контейнерним робочим навантаженням.

Докладніше читайте в проєктній пропозиції CSI.

Примітка:

Підтримку версій специфікації CSI 0.2 та 0.3 визнано застарілою в Kubernetes v1.13, і її буде вилучено в майбутньому випуску.

Примітка:

Драйвери CSI можуть бути сумісними не з усіма випусками Kubernetes. Перевірте в документації конкретного драйвера CSI підтримувані кроки розгортання для кожного випуску Kubernetes і матрицю сумісності.

Після розгортання сумісного з CSI драйвера томів у кластері Kubernetes користувачі можуть використовувати тип тому csi, щоб підʼєднувати або монтувати томи, які надає драйвер CSI.

Том csi можна використовувати в Podʼі трьома різними способами:

Адміністратори сховища можуть використовувати такі поля для налаштування постійного тому CSI:

  • driver: Рядкове значення, яке задає назву драйвера томів. Це значення має відповідати значенню, яке драйвер CSI повертає в GetPluginInfoResponse, як визначено в специфікації CSI. Kubernetes використовує його, щоб визначити, який драйвер CSI викликати, а компоненти драйвера CSI — щоб визначити, які обʼєкти PV належать цьому драйверу CSI.
  • volumeHandle: Рядкове значення, яке унікально ідентифікує том. Це значення має відповідати значенню, яке драйвер CSI повертає в полі volume.id відповіді CreateVolumeResponse, як визначено в специфікації CSI. Значення передається як volume_id в усіх викликах драйвера томів CSI під час посилання на том.
  • readOnly: Необовʼязкове булеве значення, яке вказує, чи має том бути "ControllerPublished" (підʼєднаний) лише для читання. Стандартно false. Це значення передається драйверу CSI через поле readonly у ControllerPublishVolumeRequest.
  • fsType: Якщо VolumeMode PV має значення Filesystem, це поле можна використати для вказання файлової системи, яку слід використовувати для монтування тому. Якщо том не відформатовано й форматування підтримується, це значення буде використано для форматування тому. Це значення передається драйверу CSI через поле VolumeCapability у ControllerPublishVolumeRequest, NodeStageVolumeRequest та NodePublishVolumeRequest.
  • volumeAttributes: Мапа рядків на рядки, яка задає статичні властивості тому. Ця мапа має відповідати мапі, яку драйвер CSI повертає в полі volume.attributes відповіді CreateVolumeResponse, як визначено в специфікації CSI. Мапа передається драйверу CSI через поле volume_context у ControllerPublishVolumeRequest, NodeStageVolumeRequest та NodePublishVolumeRequest.
  • controllerPublishSecretRef: Посилання на обʼєкт Secret, що містить конфіденційну інформацію, яку слід передати драйверу CSI для завершення викликів CSI ControllerPublishVolume та ControllerUnpublishVolume. Це поле є необовʼязковим і може бути порожнім, якщо Secret не потрібен. Якщо Secret містить більше одного секрету, передаються всі секрети.
  • nodeExpandSecretRef: Посилання на Secret, що містить конфіденційну інформацію, яку слід передати драйверу CSI для завершення виклику CSI NodeExpandVolume. Це поле є необовʼязковим і може бути порожнім, якщо Secret не потрібен. Якщо обʼєкт містить більше одного секрету, передаються всі секрети. Коли ви налаштували секретні дані для розширення тому, ініційованого вузлом, kubelet передає ці дані драйверу CSI через виклик NodeExpandVolume(). Усі підтримувані версії Kubernetes пропонують поле nodeExpandSecretRef і стандартно роблять його доступним. Випуски Kubernetes до v1.25 не мали цієї підтримки.
  • Увімкніть функціональну можливість CSINodeExpandSecret для кожного kube-apiserver і для kubelet на кожному вузлі. Починаючи з Kubernetes 1.27, цю можливість стандартно ввімкнено, і явно вмикати функціональну можливість не потрібно. Ви також повинні використовувати драйвер CSI, який підтримує або потребує секретних даних під час операцій зміни розміру сховища, ініційованих вузлом.
  • nodePublishSecretRef: Посилання на обʼєкт Secret, що містить конфіденційну інформацію, яку слід передати драйверу CSI для завершення виклику CSI NodePublishVolume. Це поле є необовʼязковим і може бути порожнім, якщо Secret не потрібен. Якщо обʼєкт Secret містить більше одного секрету, передаються всі секрети.
  • nodeStageSecretRef: Посилання на обʼєкт Secret, що містить конфіденційну інформацію, яку слід передати драйверу CSI для завершення виклику CSI NodeStageVolume. Це поле є необовʼязковим і може бути порожнім, якщо Secret не потрібен. Якщо Secret містить більше одного секрету, передаються всі секрети.

Підтримка необроблених блокових томів CSI

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.18

Постачальники зовнішніх драйверів CSI можуть реалізувати підтримку необроблених блокових томів у робочих навантаженнях Kubernetes.

Ви можете налаштувати свій PersistentVolume/PersistentVolumeClaim із підтримкою необроблених блокових томів як зазвичай, без будь-яких змін, специфічних для CSI.

Ефемерні томи CSI

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.25

Ви можете безпосередньо налаштувати томи CSI у специфікації Podʼа. Томи, вказані таким способом, є ефемерними й не зберігаються після перезапуску Podʼа. Докладніше дивіться в Ефемерні томи.

Докладніше про розроблення драйвера CSI дивіться в документації kubernetes-csi

Проксі CSI для Windows

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.22

Втулки вузла CSI мають виконувати різні привілейовані операції, такі як сканування дискових пристроїв і монтування файлових систем. Ці операції відрізняються для кожної операційної системи хоста. На робочих вузлах Linux контейнеризовані втулки вузла CSI зазвичай розгортаються як привілейовані контейнери. На робочих вузлах Windows привілейовані операції для контейнеризованих втулків вузла CSI підтримуються за допомогою csi-proxy — автономного бінарного файлу, що підтримується спільнотою й має бути попередньо встановлений на кожному вузлі Windows.

Докладніше дивіться в посібнику з розгортання втулка CSI, який ви хочете розгорнути.

Міграція на драйвери CSI з вбудованих втулків

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.25

Можливість CSIMigration спрямовує операції щодо наявних вбудованих втулків до відповідних втулків CSI (які мають бути встановлені й налаштовані). Завдяки цьому операторам не потрібно змінювати конфігурацію наявних класів сховища, PersistentVolumes або PersistentVolumeClaims (які посилаються на вбудовані втулки) під час переходу на драйвер CSI, що замінює вбудований втулок.

Примітка:

Наявні PV, створені вбудованим втулком томів, можна й надалі використовувати без будь-яких змін конфігурації, навіть після завершення міграції на CSI для цього типу тому і навіть після оновлення до версії Kubernetes, у якій немає вкомпільованої підтримки цього типу сховища.

У межах цієї міграції ви або інший адміністратор кластера повинні встановити й налаштувати відповідний драйвер CSI для цього сховища. Ядро Kubernetes не встановлює це програмне забезпечення за вас.


Після цієї міграції ви також можете визначати нові PVC і PV, які посилаються на застарілі вбудовані інтеграції сховищ. Якщо відповідний драйвер CSI встановлено й налаштовано, створення PV і далі працює, навіть для зовсім нових томів. Фактичне керування сховищем тепер відбувається через драйвер CSI.

Підтримувані операції та можливості включають: надання/видалення, підʼєднання/відʼєднання, монтування/розмонтування та зміну розміру томів.

Вбудовані втулки, які підтримують CSIMigration і мають відповідний реалізований драйвер CSI, перелічено в розділі Типи томів.

flexVolume (застаріло)

СТАН ФУНКЦІОНАЛУ: Deprecated since Kubernetes v1.23

FlexVolume — це інтерфейс зовнішніх втулків, який використовує модель на основі exec для взаємодії з драйверами сховища. Бінарні файли драйверів FlexVolume мають бути встановлені в попередньо визначеному шляху втулків томів на кожному вузлі, а в деяких випадках і на вузлах панелі управління.

Podʼи взаємодіють із драйверами FlexVolume через вбудований втулок томів flexVolume.

Такі втулки FlexVolume, розгорнуті як сценарії PowerShell на хості, підтримують вузли Windows:

Примітка:

FlexVolume застарів. Рекомендований спосіб інтеграції зовнішнього сховища з Kubernetes — використовувати зовнішній драйвер CSI.

Супровідники драйвера FlexVolume мають реалізувати драйвер CSI й допомогти користувачам драйверів FlexVolume перейти на CSI. Користувачі FlexVolume мають перевести свої робочі навантаження на еквівалентний драйвер CSI.

Поширення монтування

Увага:

Поширення монтування — це низькорівнева можливість, яка не працює однаково на всіх типах томів. Проєкт Kubernetes рекомендує використовувати поширення монтування лише з томами hostPath або emptyDir у памʼяті. Докладніше дивіться в issue Kubernetes #95049.

Поширення монтування дозволяє надавати томи, змонтовані контейнером, іншим контейнерам у тому самому Podʼі або навіть іншим Podʼам на тому самому вузлі.

Поширення монтування тому контролюється полем mountPropagation у containers[*].volumeMounts. Його значення:

  • None — Це монтування тому не отримуватиме жодних подальших монтувань, які хост монтує в цей том або будь-яку його підтеку. Так само жодні монтування, створені контейнером, не будуть видимі на хості. Це стандартний режим.

    Цей режим еквівалентний поширенню монтування rprivate, як описано в mount(8)

    Однак середовище виконання CRI може вибрати поширення монтування rslave (тобто HostToContainer), коли поширення rprivate незастосовне. Відомо, що cri-dockerd (Docker) вибирає поширення монтування rslave, коли джерело монтування містить кореневу теку демона Docker (/var/lib/docker).

  • HostToContainer — Це монтування тому отримуватиме всі подальші монтування, які монтуються в цей том або будь-яку його підтеку.

    Іншими словами, якщо хост монтує щось усередині монтування тому, контейнер побачить, що це там змонтовано.

    Так само, якщо будь-який Pod із поширенням монтування Bidirectional на той самий том монтує туди щось, контейнер із поширенням монтування HostToContainer це побачить.

    Цей режим еквівалентний поширенню монтування rslave, як описано в mount(8)

  • Bidirectional — Це монтування тому поводиться так само, як монтування HostToContainer. Крім того, усі монтування томів, створені контейнером, поширюватимуться назад на хост і на всі контейнери всіх Podʼів, які використовують той самий том.

    Звичайний випадок використання цього режиму — Pod із драйвером FlexVolume або CSI чи Pod, якому потрібно щось змонтувати на хості за допомогою тому hostPath.

    Цей режим еквівалентний поширенню монтування rshared, як описано в mount(8)

    Попередження:

    Поширення монтування Bidirectional може бути небезпечним. Воно може пошкодити операційну систему хоста, тому дозволене лише в привілейованих контейнерах. Наполегливо рекомендується знати поведінку ядра Linux. Крім того, усі монтування томів, створені контейнерами в Podʼах, мають бути знищені (розмонтовані) контейнерами під час завершення роботи.

Монтування лише для читання

Монтування можна зробити лише для читання, встановивши поле .spec.containers[*].volumeMounts[*].readOnly у true. Це не робить сам том доступним лише для читання, але конкретний контейнер не зможе записувати в нього. Інші контейнери в Podʼі можуть монтувати той самий том для читання й запису.

У Linux монтування лише для читання стандартно не є рекурсивними. Наприклад, розгляньмо Pod, який монтує /mnt хоста як том hostPath. Якщо в /mnt/<SUBMOUNT> змонтовано для читання й запису іншу файлову систему (таку як tmpfs, NFS або USB-сховище), том, змонтований у контейнері(ах), також матиме /mnt/<SUBMOUNT> із можливістю запису, навіть якщо саме монтування вказано як лише для читання.

Рекурсивні монтування лише для читання

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.33
More information about this feature

This is a stable feature in Kubernetes, and has been since version v1.33. It was first available in the v1.30 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate RecursiveReadOnlyMounts, Kubernetes ignores it but does not report any error.

Рекурсивні монтування лише для читання можна ввімкнути, встановивши функціональну можливість RecursiveReadOnlyMounts для kubelet і kube-apiserver та встановивши поле .spec.containers[*].volumeMounts[*].recursiveReadOnly для Podʼа.

Допустимі значення:

  • Disabled (стандартно): без ефекту.

  • Enabled: робить монтування рекурсивно лише для читання. Потрібно виконати всі такі вимоги:

    • readOnly встановлено в true
    • mountPropagation не встановлено або встановлено в None
    • Хост працює з ядром Linux v5.12 або новіше
    • Середовище виконання контейнерів рівня CRI підтримує рекурсивні монтування лише для читання
    • Середовище виконання контейнерів рівня OCI підтримує рекурсивні монтування лише для читання.

    Якщо хоча б одна з цих умов не виконується, монтування завершиться збоєм.

  • IfPossible: намагається застосувати Enabled і повертається до Disabled, якщо можливість не підтримується ядром або класом середовища виконання.

Приклад:

apiVersion: v1
kind: Pod
metadata:
  name: rro
spec:
  volumes:
    - name: mnt
      hostPath:
        # tmpfs is mounted on /mnt/tmpfs
        path: /mnt
  containers:
    - name: busybox
      image: busybox
      args: ["sleep", "infinity"]
      volumeMounts:
        # /mnt-rro/tmpfs is not writable
        - name: mnt
          mountPath: /mnt-rro
          readOnly: true
          mountPropagation: None
          recursiveReadOnly: Enabled
        # /mnt-ro/tmpfs is writable
        - name: mnt
          mountPath: /mnt-ro
          readOnly: true
        # /mnt-rw/tmpfs is writable
        - name: mnt
          mountPath: /mnt-rw

Коли цю властивість розпізнають kubelet і kube-apiserver, поле .status.containerStatuses[*].volumeMounts[*].recursiveReadOnly встановлюється в Enabled або Disabled.

Власник файлу

Групова власність (GID)

Групова власність файлів тому (GID) контролюється полем spec.securityContext.fsGroup Podʼа.

Докладні кроки налаштування дивіться в Налаштування контексту безпеки для Podʼа або контейнера.

Власність користувача (UID)

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the AtomicWriteVolumeUserFields feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Встановлення функціональної можливості AtomicWriteVolumeUserFields вмикає поля власності користувача файлів (UID) томів configMap, secret, downwardAPI та projected.

Коли defaultUser вказано на рівні тому, він встановлює UID власника для всіх його файлів даних під час створення. На рівні елемента поле user контролює UID власника окремого файлу та має перевагу над defaultUser.

Приклад:

apiVersion: v1
kind: Pod
metadata:
  name: volume-user-fields-example
spec:
  containers:
  - name: test
    image: busybox:1.28
    command: ['sh', '-c', 'echo "The app is running!" && tail -f /dev/null']
    volumeMounts:
    - name: volA
      mountPath: /mnt/volA
    - name: volB
      mountPath: /mnt/volB
    - name: volC
      mountPath: /mnt/volC
  volumes:
  - name: volA
    configMap:
      defaultUser: 1000
      name: cm1
      items:
      - key: foo # Owner=defaultUser
        path: foo
      - key: bar # Owner=user
        path: bar
        user: 1001
  - name: volB
    secret: # Owner=defaultUser
      defaultUser: 1000
      secretName: secret1
  - name: volC
    projected:
      sources:
      - secret:
          name: secret2
          items:
          - key: moo # Owner=root
            path: moo
          - key: baa # Owner=user
            path: baa
            user: 1000

Реалізації

Примітка: Цей розділ містить посилання на проєкти сторонніх розробників, які надають функціонал, необхідний для Kubernetes. Автори проєкту Kubernetes не несуть відповідальності за ці проєкти. Проєкти вказано в алфавітному порядку. Щоб додати проєкт до цього списку, ознайомтеся з посібником з контенту перед надсиланням змін. Докладніше.

Відомо, що такі середовища виконання контейнерів підтримують рекурсивні монтування лише для читання.

Рівень CRI:

Рівень OCI:

  • runc, починаючи з v1.1
  • crun, починаючи з v1.8.6

Параметри bind mount

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.37; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the VolumeBindMountOptions feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Поле .spec.containers[*].volumeMounts[*].bindMountOptions дозволяє вам застосовувати повʼязані з безпекою прапорці bind mount Linux до будь-якого монтування тому. Допустимі значення:

  • noexec — запобігає виконанню бінарних файлів на змонтованому томі
  • nodev — ігнорує спеціальні файли пристроїв на змонтованому томі
  • nosuid — ігнорує біти set-user-identifier або set-group-identifier на змонтованому томі

Ці параметри застосовуються для кожного контейнера, тому різні контейнери в одному Podʼі можуть монтувати той самий том із різними параметрами bind mount. Поле не підтримується з томами образів.

Примітка:

Середовище виконання контейнерів (таке як containerd або CRI-O) повинно підтримувати поле mount_options у повідомленні CRI Mount. Якщо середовище виконання не повідомляє про підтримку, kubelet відхиляє Podʼи, які використовують bindMountOptions. Це поле не впливає на вузли Windows.

Що далі

Ознайомтеся з прикладом розгортання WordPress і MySQL із постійними томами.

2 - Постійні томи

У цьому документі описано постійні томи в Kubernetes. Рекомендується ознайомитися з томами, StorageClasses та VolumeAttributesClasses.

Вступ

Керування сховищем — це окреме завдання, відмінне від керування обчислювальними екземплярами. Підсистема PersistentVolume надає користувачам та адміністраторам API, який абстрагує деталі того, як сховище надається, від того, як воно споживається. Для цього ми запроваджуємо два нові ресурси API: PersistentVolume і PersistentVolumeClaim.

PersistentVolume (PV) — це частина сховища в кластері, надана адміністратором або динамічно за допомогою класів сховищ. Це ресурс у кластері, так само як вузол є ресурсом кластера. PV — це втулки томів, як і Volumes, але їхній життєвий цикл не залежить від будь-якого окремого Podʼа, який використовує PV. Цей обʼєкт API містить деталі реалізації сховища, чи то NFS, iSCSI, чи специфічна для хмарного провайдера система зберігання.

PersistentVolumeClaim (PVC) — це запит користувача на сховище. Він схожий на Pod. Podʼи споживають ресурси вузла, а PVC споживають ресурси PV. Podʼи можуть запитувати певні обсяги ресурсів (CPU та памʼять). PVC можуть запитувати певний розмір і режими доступу (наприклад, їх можна монтувати як ReadWriteOnce, ReadOnlyMany, ReadWriteMany або ReadWriteOncePod, дивіться AccessModes).

Хоча PersistentVolumeClaims дозволяють користувачам споживати абстрактні ресурси сховища, для різних завдань користувачам часто потрібні PersistentVolumes із різними властивостями, наприклад, продуктивністю. Адміністратори кластера мають бути здатні пропонувати різноманітні PersistentVolumes, які відрізняються не лише розміром і режимами доступу, не розкриваючи користувачам деталей реалізації цих томів. Для цих потреб існує ресурс StorageClass.

Дивіться докладний покроковий опис із робочими прикладами.

Життєвий цикл тому та PVC

PV — це ресурси в кластері. PVC — це запити на ці ресурси, які також діють як квитанції на ресурс. Взаємодія між PV та PVC відбувається за таким життєвим циклом:

Надання

Існує два способи надання PV: статично або динамічно.

Статичне

Адміністратор кластера створює певну кількість PV. Вони містять відомості про реальне сховище, доступне для використання користувачами кластера. Вони існують в API Kubernetes і доступні для споживання.

Динамічне

Коли жоден зі статичних PV, створених адміністратором, не відповідає PersistentVolumeClaim користувача, кластер може спробувати динамічно надати том спеціально для цього PVC. Це надання ґрунтується на StorageClasses: PVC має запитати клас сховища, а адміністратор має створити й налаштувати цей клас, щоб динамічне надання могло відбутися. PVC, які запитують клас "", фактично вимикають для себе динамічне надання.

Щоб увімкнути динамічне надання сховища на основі класу сховища, адміністратор кластера має ввімкнути DefaultStorageClass контролер допуску на API-сервері. Це можна зробити, наприклад, переконавшись, що DefaultStorageClass є серед значень упорядкованого списку, розділеного комами, у прапорці --enable-admission-plugins компонента API-сервера. Докладніше про прапорці командного рядка API-сервера дивіться в документації kube-apiserver.

Привʼязка

Користувач створює або, у разі динамічного надання, уже створив PersistentVolumeClaim із певним запитаним обсягом сховища та певними режимами доступу. Цикл управління в панелі управління стежить за новими PVC, знаходить відповідний PV (якщо це можливо) і привʼязує їх один до одного. Якщо PV було динамічно надано для нового PVC, цикл завжди привʼязуватиме цей PV до PVC. Інакше користувач завжди отримає принаймні те, що запитував, але том може перевищувати запитаний обсяг. Після привʼязки PersistentVolumeClaim є ексклюзивними, незалежно від того, як їх було привʼязано. Привʼязка PVC до PV — це зіставлення один до одного за допомогою ClaimRef, який є двоспрямованою привʼязкою між PersistentVolume і PersistentVolumeClaim.

PVC залишатимуться непривʼязаними необмежено довго, якщо відповідного тому не існує. PVC будуть привʼязані, коли відповідні томи стануть доступними. Наприклад, кластер, забезпечений багатьма PV розміром 50Gi, не відповідатиме PVC, який запитує 100Gi. PVC можна буде привʼязати, коли до кластера буде додано PV розміром 100Gi.

Використання

Podʼи використовують PVC як томи. Кластер перевіряє PVC, щоб знайти привʼязаний том, і монтує цей том для Podʼа. Для томів, які підтримують кілька режимів доступу, користувач вказує бажаний режим, коли використовує свій PVC як том у Podʼі.

Щойно користувач має PVC і цей PVC привʼязано, привʼязаний PV належить користувачеві стільки, скільки потрібно. Користувачі планують Podʼи та отримують доступ до своїх PV, додаючи розділ persistentVolumeClaim у блок volumes Podʼа. Докладніше дивіться в розділі PVC як томи.

Захист обʼєктів сховища, що використовуються

Мета можливості захисту обʼєктів сховища, що використовуються, — гарантувати, що PersistentVolumeClaims (PVC), які активно використовуються Podʼом, і PersistentVolume (PV), привʼязані до PVC, не вилучаються із системи, оскільки це може призвести до втрати даних.

Примітка:

PVC активно використовується Podʼом, коли існує обʼєкт Pod, який використовує PVC.

Якщо користувач видаляє PVC, який активно використовується Podʼом, PVC вилучається не одразу. Вилучення PVC відкладається, доки PVC більше не використовуватиметься активно жодним Podʼом. Так само, якщо адміністратор видаляє PV, привʼязаний до PVC, PV вилучається не одразу. Вилучення PV відкладається, доки PV більше не буде привʼязаний до PVC.

Ви можете побачити, що PVC захищено, коли статус PVC — Terminating, а список Finalizers містить kubernetes.io/pvc-protection:

kubectl describe pvc hostpath
Name:          hostpath
Namespace:     default
StorageClass:  example-hostpath
Status:        Terminating
Volume:
Labels:        <none>
Annotations:   volume.beta.kubernetes.io/storage-class=example-hostpath
               volume.beta.kubernetes.io/storage-provisioner=example.com/hostpath
Finalizers:    [kubernetes.io/pvc-protection]
...

Ви можете побачити, що PV захищено, коли статус PV — Terminating, а список Finalizers також містить kubernetes.io/pv-protection:

kubectl describe pv task-pv-volume
Name:            task-pv-volume
Labels:          type=local
Annotations:     <none>
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    standard
Status:          Terminating
Claim:
Reclaim Policy:  Delete
Access Modes:    RWO
Capacity:        1Gi
Message:
Source:
    Type:          HostPath (bare host directory volume)
    Path:          /tmp/data
    HostPathType:
Events:            <none>

Повторне використання

Коли користувач закінчує роботу зі своїм томом, він може видалити обʼєкти PVC з API, що дозволяє повторно використати ресурс. Політика повторного використання PersistentVolume вказує кластеру, що робити з томом після того, як його звільнено від PVC. Наразі томи можна зберегти (Retain), переробити (Recycle) або видалити (Delete).

Retain

Політика повторного використання Retain дозволяє повторно використати ресурс вручну. Коли PersistentVolumeClaim видаляють, PersistentVolume все ще існує, і том вважається «звільненим». Але він ще не доступний для іншого PVC, оскільки на томі залишаються дані попереднього власника PVC. Адміністратор може вручну повторно використати том, виконавши такі кроки.

  1. Видаліть PersistentVolume. Повʼязаний ресурс сховища в зовнішній інфраструктурі все ще існує після видалення PV.
  2. Вручну очистіть дані на повʼязаному ресурсі сховища.
  3. Вручну видаліть повʼязаний ресурс сховища.

Якщо ви хочете повторно використати той самий ресурс сховища, створіть новий PersistentVolume із таким самим визначенням ресурсу сховища.

Delete

Для втулків томів, які підтримують політику повторного використання Delete, видалення вилучає і обʼєкт PersistentVolume з Kubernetes, і повʼязаний ресурс сховища в зовнішній інфраструктурі. Томи, надані динамічно, успадковують політику повторного використання свого StorageClass, стандартним значенням якої є Delete. Адміністратор має налаштувати StorageClass відповідно до очікувань користувачів; інакше PV потрібно відредагувати або змінити за допомогою patch після створення. Дивіться Зміна політики повторного використання PersistentVolume.

Recycle

Попередження:

Політика повторного використання Recycle застаріла. Натомість рекомендовано використовувати динамічне надання.

Якщо це підтримує базовий втулок томів, політика повторного використання Recycle виконує базове очищення (rm -rf /thevolume/*) тому й знову робить його доступним для нового PVC.

Однак адміністратор може налаштувати власний шаблон Podʼа recycler за допомогою аргументів командного рядка менеджера контролерів Kubernetes, як описано в довіднику. Власний шаблон Podʼа recycler має містити специфікацію volumes, як показано в наведеному нижче прикладі:

apiVersion: v1
kind: Pod
metadata:
  name: pv-recycler
  namespace: default
spec:
  restartPolicy: Never
  volumes:
  - name: vol
    hostPath:
      path: /any/path/it/will/be/replaced
  containers:
  - name: pv-recycler
    image: "registry.k8s.io/busybox"
    command: ["/bin/sh", "-c", "test -e /scrub && rm -rf /scrub/..?* /scrub/.[!.]* /scrub/*  && test -z \"$(ls -A /scrub)\" || exit 1"]
    volumeMounts:
    - name: vol
      mountPath: /scrub

Однак конкретний шлях, вказаний у частині volumes власного шаблону Podʼа recycler, замінюється конкретним шляхом тому, що переробляється.

Завершувач захисту від видалення PersistentVolume

This is a stable feature in Kubernetes, and has been since the 1.33 release. You can no longer toggle this feature (the associated feature gate has been removed).

До PersistentVolume можна додавати завершувачі, щоб PersistentVolumes із політикою повторного використання Delete видалялися лише після видалення базового сховища.

Завершувач external-provisioner.volume.kubernetes.io/finalizer (запроваджений у v1.31) додається як до динамічно, так і до статично наданих томів CSI.

Завершувач kubernetes.io/pv-controller (запроваджений у v1.31) додається до динамічно наданих томів вбудованих втулків і пропускається для статично наданих томів вбудованих втулків.

Ось приклад динамічно наданого тому вбудованого втулка:

kubectl describe pv pvc-74a498d6-3929-47e8-8c02-078c1ece4d78
Name:            pvc-74a498d6-3929-47e8-8c02-078c1ece4d78
Labels:          <none>
Annotations:     kubernetes.io/createdby: vsphere-volume-dynamic-provisioner
                 pv.kubernetes.io/bound-by-controller: yes
                 pv.kubernetes.io/provisioned-by: kubernetes.io/vsphere-volume
Finalizers:      [kubernetes.io/pv-protection kubernetes.io/pv-controller]
StorageClass:    vcp-sc
Status:          Bound
Claim:           default/vcp-pvc-1
Reclaim Policy:  Delete
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        1Gi
Node Affinity:   <none>
Message:
Source:
    Type:               vSphereVolume (a Persistent Disk resource in vSphere)
    VolumePath:         [vsanDatastore] d49c4a62-166f-ce12-c464-020077ba5d46/kubernetes-dynamic-pvc-74a498d6-3929-47e8-8c02-078c1ece4d78.vmdk
    FSType:             ext4
    StoragePolicyName:  vSAN Default Storage Policy
Events:                 <none>

Завершувач external-provisioner.volume.kubernetes.io/finalizer додається для томів CSI. Ось приклад:

Name:            pvc-2f0bab97-85a8-4552-8044-eb8be45cf48d
Labels:          <none>
Annotations:     pv.kubernetes.io/provisioned-by: csi.vsphere.vmware.com
Finalizers:      [kubernetes.io/pv-protection external-provisioner.volume.kubernetes.io/finalizer]
StorageClass:    fast
Status:          Bound
Claim:           demo-app/nginx-logs
Reclaim Policy:  Delete
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        200Mi
Node Affinity:   <none>
Message:
Source:
    Type:              CSI (a Container Storage Interface (CSI) volume source)
    Driver:            csi.vsphere.vmware.com
    FSType:            ext4
    VolumeHandle:      44830fa8-79b4-406b-8b58-621ba25353fd
    ReadOnly:          false
    VolumeAttributes:      storage.kubernetes.io/csiProvisionerIdentity=1648442357185-8081-csi.vsphere.vmware.com
                           type=vSphere CNS Block Volume
Events:                <none>

Коли для конкретного вбудованого втулка томів увімкнено прапорець можливості CSIMigration{provider}, завершувач kubernetes.io/pv-controller замінюється завершувачем external-provisioner.volume.kubernetes.io/finalizer.

Завершувачі гарантують, що обʼєкт PV вилучається лише після видалення тому з бекенду сховища, якщо політика повторного використання PV — Delete. Це також гарантує, що том буде видалено з бекенду сховища незалежно від порядку видалення PV і PVC.

Резервування PersistentVolume

Панель управління може привʼязувати PersistentVolumeClaims до відповідних PersistentVolumes у кластері. Однак, якщо ви хочете, щоб PVC привʼязався до певного PV, потрібно попередньо їх привʼязати.

Вказавши PersistentVolume у PersistentVolumeClaim, ви оголошуєте привʼязку між цими конкретними PV та PVC. Якщо PersistentVolume існує і не зарезервував PersistentVolumeClaims через своє поле claimRef, PersistentVolume і PersistentVolumeClaim буде привʼязано.

Привʼязка відбувається незалежно від деяких критеріїв зіставлення томів, зокрема спорідненості вузла. Панель управління все ще перевіряє, що клас сховища, режими доступу та запитаний розмір сховища є дійсними.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: foo-pvc
  namespace: foo
spec:
  storageClassName: "" # Порожній рядок потрібно вказати явно, інакше буде встановлено стандартний StorageClass
  volumeName: foo-pv
  ...

Цей метод не гарантує жодних привілеїв привʼязки для PersistentVolume. Якщо інші PersistentVolumeClaims можуть використовувати вказаний вами PV, спочатку потрібно зарезервувати цей том сховища. Вкажіть відповідний PersistentVolumeClaim у полі claimRef PV, щоб інші PVC не могли до нього привʼязатися.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: foo-pv
spec:
  storageClassName: ""
  claimRef:
    name: foo-pvc
    namespace: foo
  ...

Це корисно, якщо ви хочете використовувати PersistentVolumes, у яких persistentVolumeReclaimPolicy має значення Retain, зокрема у випадках, коли ви повторно використовуєте наявний PV.

Розширення PersistentVolumeClaims

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.24

Підтримку розширення PersistentVolumeClaims (PVC) стандартно ввімкнено. Ви можете розширювати такі типи томів:

  • csi (зокрема деякі типи томів, перенесені на CSI)
  • flexVolume (застаріло)
  • portworxVolume (застаріло)

Ви можете розширити PVC, лише якщо поле allowVolumeExpansion його класу сховища має значення true.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: example-vol-default
provisioner: vendor-name.example/magicstorage
parameters:
  resturl: "http://192.168.10.100:8080"
  restuser: ""
  secretNamespace: ""
  secretName: ""
allowVolumeExpansion: true

Щоб запросити більший том для PVC, відредагуйте обʼєкт PVC і вкажіть більший розмір. Це запускає розширення тому, що стоїть за базовим PersistentVolume. Новий PersistentVolume для задоволення PVC ніколи не створюється. Натомість змінюється розмір наявного тому.

Попередження:

Пряме редагування розміру PersistentVolume може завадити автоматичній зміні розміру цього тому. Якщо ви редагуєте місткість PersistentVolume, а потім редагуєте .spec відповідного PersistentVolumeClaim, щоб розмір PersistentVolumeClaim збігався з PersistentVolume, зміна розміру сховища не відбудеться. Панель управління Kubernetes побачить, що бажаний стан обох ресурсів збігається, і зробить висновок, що розмір базового тому було збільшено вручну й зміна розміру не потрібна.

Розширення томів CSI

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.24

Підтримку розширення томів CSI стандартно ввімкнено, але вона також вимагає, щоб конкретний драйвер CSI підтримував розширення томів. Докладніше дивіться в документації конкретного драйвера CSI.

Зміна розміру тому, що містить файлову систему

Ви можете змінювати розмір томів, що містять файлову систему, лише якщо це XFS, Ext3 або Ext4.

Коли том містить файлову систему, її розмір змінюється лише тоді, коли новий Pod використовує PersistentVolumeClaim у режимі ReadWrite. Розширення файлової системи виконується або під час запуску Podʼа, або коли Pod працює і базова файлова система підтримує онлайн-розширення.

FlexVolumes (застаріли з Kubernetes v1.23) дозволяють змінювати розмір, якщо драйвер налаштовано з можливістю RequiresFSResize, встановленою в true. Розмір FlexVolume можна змінити під час перезапуску Podʼа.

Зміна розміру PersistentVolumeClaim, що використовується

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.24

У цьому випадку вам не потрібно видаляти й повторно створювати Pod або Deployment, який використовує наявний PVC. Будь-який PVC, що використовується, автоматично стає доступним для свого Podʼа, щойно його файлову систему буде розширено. Ця можливість не впливає на PVC, які не використовуються Podʼом або Deployment. Ви повинні створити Pod, який використовує PVC, щоб розширення могло завершитися.

Як і інші типи томів, томи FlexVolume також можна розширювати, коли їх використовує Pod.

Примітка:

Змінити розмір FlexVolume можна лише тоді, коли це підтримує базовий драйвер.

Відновлення після збою під час розширення томів

Якщо користувач вказує новий розмір, надто великий для базової системи зберігання, розширення PVC повторюватиметься постійно, доки користувач або адміністратор кластера не вживе заходів. Це може бути небажаним, тому Kubernetes надає такі методи відновлення після таких збоїв.

Якщо розширення базового сховища не вдається, адміністратор кластера може вручну відновити стан PersistentVolumeClaim (PVC) і скасувати запити на зміну розміру. Інакше контролер постійно повторюватиме запити на зміну розміру без втручання адміністратора.

  1. Позначте PersistentVolume (PV), привʼязаний до PersistentVolumeClaim (PVC), політикою повторного використання Retain.
  2. Видаліть PVC. Оскільки PV має політику повторного використання Retain, ми не втратимо жодних даних під час повторного створення PVC.
  3. Видаліть запис claimRef зі специфікації PV, щоб новий PVC міг до нього привʼязатися. Це має зробити PV Available.
  4. Створіть PVC заново з меншим розміром, ніж у PV, і встановіть у поле volumeName PVC назву PV. Це має привʼязати новий PVC до наявного PV.
  5. Не забудьте відновити політику повторного використання PV.

Якщо розширення PVC не вдалося, ви можете повторити його з меншим розміром, ніж запитане раніше значення. Щоб запросити нову спробу розширення з меншим запропонованим розміром, відредагуйте .spec.resources цього PVC і виберіть значення, менше за попереднє. Це корисно, якщо розширення до більшого значення не вдалося через обмеження місткості. Якщо це сталося або ви підозрюєте, що могло статися, ви можете повторити розширення, вказавши розмір у межах місткості базового провайдера сховища. Ви можете стежити за статусом операції зміни розміру через .status.allocatedResourceStatuses та Events на PVC.

Зверніть увагу, що, хоча ви можете вказати менший обсяг сховища, ніж запитували раніше, нове значення все одно має бути більшим за .status.capacity. Kubernetes не підтримує зменшення PVC до розміру, меншого за поточний.

Типи постійних томів

Типи PersistentVolume реалізовано як втулки. Наразі Kubernetes підтримує такі втулки:

  • csi — Container Storage Interface (CSI)
  • fc — Сховище Fibre Channel (FC)
  • hostPath — том HostPath (лише для тестування на одному вузлі; НЕ ПРАЦЮВАТИМЕ в кластері з кількома вузлами; натомість розгляньте використання тому local)
  • iscsi — Сховище iSCSI (SCSI через IP)
  • local — локальні пристрої зберігання, змонтовані на вузлах.
  • nfs — сховище Network File System (NFS)

Такі типи PersistentVolume застаріли, але все ще доступні. Якщо ви використовуєте ці типи томів, крім flexVolume, cephfs та rbd, встановіть відповідні драйвери CSI.

  • awsElasticBlockStore — AWS Elastic Block Store (EBS) (міграцію стандартно ввімкнено починаючи з v1.23)
  • azureDisk — Azure Disk (міграцію стандартно ввімкнено починаючи з v1.23)
  • azureFile — Azure File (міграцію стандартно ввімкнено починаючи з v1.24)
  • cinder — Cinder (блочне сховище OpenStack) (міграцію стандартно ввімкнено починаючи з v1.21)
  • flexVolume — FlexVolume (застаріло починаючи з версії v1.23, план міграції відсутній, планів припинення підтримки немає)
  • gcePersistentDisk — GCE Persistent Disk (міграцію стандартно ввімкнено починаючи з v1.23)
  • portworxVolume — Том Portworx (міграцію стандартно ввімкнено починаючи з v1.31)
  • vsphereVolume — том vSphere VMDK (міграцію стандартно ввімкнено починаючи з v1.25)

Старіші версії Kubernetes також підтримували такі типи вбудованих PersistentVolume:

  • cephfs (недоступно починаючи з версії v1.31)
  • flocker — Flocker storage. (недоступно починаючи з версії v1.25)
  • glusterfs — GlusterFS storage. (недоступно починаючи з версії v1.26)
  • photonPersistentDisk — Photon controller persistent disk. (недоступно починаючи з версії v1.15)
  • quobyte — Том Quobyte. (недоступно починаючи з версії v1.25)
  • rbd — Rados Block Device (RBD) volume (недоступно починаючи з версії v1.31)
  • scaleIO — Том ScaleIO. (недоступно починаючи з версії v1.21)
  • storageos — Том StorageOS. (недоступно починаючи з версії v1.25)

Постійні томи

Кожен PV містить spec і status, тобто специфікацію та статус тому. Назва обʼєкта PersistentVolume має бути дійсним іменем DNS-піддомену.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 172.17.0.2

Примітка:

Для використання PersistentVolume у кластері можуть знадобитися допоміжні програми, повʼязані з типом тому. У цьому прикладі PersistentVolume має тип NFS, і для підтримки монтування файлових систем NFS потрібна допоміжна програма /sbin/mount.nfs.

Місткість

Зазвичай PV має певну місткість сховища. Вона задається атрибутом capacity PV, який є значенням Quantity.

Наразі розмір сховища — єдиний ресурс, який можна встановити або запитати. Майбутні атрибути можуть включати IOPS, пропускну здатність тощо.

Режим тому

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.18

Kubernetes підтримує два значення volumeModes для PersistentVolumes: Filesystem та Block.

volumeMode є необовʼязковим параметром API. Filesystem — стандартний режим, який використовується, коли параметр volumeMode пропущено.

Том із volumeMode: Filesystem монтується в Podʼи в теку. Якщо том підкріплений блоковим пристроєм і пристрій порожній, Kubernetes створює на ньому файлову систему перед першим монтуванням.

Ви можете встановити volumeMode у Block, щоб використовувати том як необроблений блоковий пристрій. Такий том подається в Pod як блоковий пристрій без файлової системи. Цей режим корисний, щоб надати Podʼу найшвидший можливий доступ до тому без будь-якого шару файлової системи між Podʼом і томом. З іншого боку, застосунок, що працює в Podʼі, має знати, як працювати з необробленим блоковим пристроєм. Приклад використання тому з volumeMode: Block у Podʼі дивіться в розділі Підтримка необроблених блокових томів.

Режими доступу

PersistentVolume можна змонтувати на хості будь-яким способом, який підтримує провайдер ресурсу. Як показано в таблиці нижче, провайдери мають різні можливості, а режими доступу кожного PV встановлюються відповідно до режимів, які підтримує цей конкретний том. Наприклад, NFS може підтримувати кількох клієнтів для читання й запису, але конкретний PV NFS може бути експортований на сервері лише для читання. Кожен PV отримує власний набір режимів доступу, що описує можливості саме цього PV.

Режими доступу такі:

ReadWriteOnce
том можна змонтувати для читання й запису на одному вузлі. Режим доступу ReadWriteOnce все ще може дозволяти кільком Podʼам доступ до цього тому (читання з нього або запис у нього), якщо ці Podʼи працюють на одному вузлі. Про доступ для одного Podʼа дивіться ReadWriteOncePod.
ReadOnlyMany
том можна змонтувати лише для читання на багатьох вузлах.
ReadWriteMany
том можна змонтувати для читання й запису на багатьох вузлах.
ReadWriteOncePod
СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.29
том можна змонтувати для читання й запису одним Podʼом. Використовуйте режим доступу ReadWriteOncePod, якщо хочете гарантувати, що лише один Pod у всьому кластері може читати цей PVC або записувати в нього.

Примітка:

Режим доступу ReadWriteOncePod підтримується лише для томів CSI і Kubernetes версії 1.22+. Щоб використовувати цю можливість, вам потрібно оновити такі sidecar-контейнери CSI до цих або новіших версій:

У командному рядку режими доступу скорочуються так:

  • RWO — ReadWriteOnce
  • ROX — ReadOnlyMany
  • RWX — ReadWriteMany
  • RWOP — ReadWriteOncePod

Примітка:

Kubernetes використовує режими доступу до томів для зіставлення PersistentVolumeClaims і PersistentVolumes. У деяких випадках режими доступу до томів також обмежують, де можна змонтувати PersistentVolume. Режими доступу до томів не забезпечують захист від запису після монтування сховища. Навіть якщо вказано режими доступу ReadWriteOnce, ReadOnlyMany або ReadWriteMany, вони не встановлюють жодних обмежень на том. Наприклад, навіть якщо PersistentVolume створено як ReadOnlyMany, це не гарантує, що він буде доступний лише для читання. Якщо вказано режим доступу ReadWriteOncePod, том обмежений і може бути змонтований лише одним Podʼом.

Важливо! Том можна монтувати одночасно лише в одному режимі доступу, навіть якщо він підтримує кілька.

Втулок томівReadWriteOnceReadOnlyManyReadWriteManyReadWriteOncePod
AzureFile✓✓✓-
CephFS✓✓✓-
CSIзалежить від драйверазалежить від драйверазалежить від драйверазалежить від драйвера
FC✓✓--
FlexVolume✓✓залежить від драйвера-
HostPath✓---
iSCSI✓✓--
NFS✓✓✓-
RBD✓✓--
VsphereVolume✓-- (працює, коли Podʼи розташовані разом)-
PortworxVolume✓-✓-

Клас

PV може мати клас, який задається встановленням атрибута storageClassName на назву StorageClass. PV певного класу можна привʼязати лише до PVC, які запитують цей клас. PV без storageClassName не має класу, і його можна привʼязати лише до PVC, які не запитують жодного конкретного класу.

У минулому замість атрибута storageClassName використовувалася анотація volume.beta.kubernetes.io/storage-class. Ця анотація все ще працює; однак у майбутньому випуску Kubernetes вона стане повністю застарілою.

Політика повторного використання

Поточні політики повторного використання:

  • Retain — ручне повторне використання
  • Recycle — базове очищення (rm -rf /thevolume/*)
  • Delete — видалити том

У Kubernetes 1.37 переробку підтримують лише типи томів nfs та hostPath.

Параметри монтування

Адміністратор Kubernetes може вказати додаткові параметри монтування для випадку, коли постійний том монтується на вузлі.

Примітка:

Не всі типи постійних томів підтримують параметри монтування.

Такі типи томів підтримують параметри монтування:

  • csi (зокрема типи томів, перенесені на CSI)
  • iscsi
  • nfs

Параметри монтування не перевіряються. Якщо параметр монтування недійсний, монтування завершиться невдачею.

У минулому замість атрибута mountOptions використовувалася анотація volume.beta.kubernetes.io/mount-options. Ця анотація все ще працює; однак у майбутньому випуску Kubernetes вона стане повністю застарілою.

Спорідненість вузла

Примітка:

Для більшості типів томів вам не потрібно встановлювати це поле. Вам слід явно встановити його для томів local.

PV може вказувати спорідненість вузла, щоб визначити обмеження, з яких вузлів можна отримати доступ до цього тому. Podʼи, які використовують PV, плануватимуться лише на вузли, вибрані спорідненістю вузла. Щоб вказати спорідненість вузла, встановіть nodeAffinity у .spec PV. Докладніше про це поле дивіться в довіднику API PersistentVolume.

Оновлення спорідненості вузла

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.35; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the MutablePVNodeAffinity feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Якщо у вашому кластері ввімкнено функціональну можливість MutablePVNodeAffinity, поле .spec.nodeAffinity PersistentVolume можна змінювати. Це дозволяє адміністраторам кластера або зовнішньому контролеру сховища оновлювати спорідненість вузла PersistentVolume під час міграції даних, не перериваючи роботу запущених Podʼів.

Під час оновлення спорідненості вузла переконайтеся, що нова спорідненість вузла все ще відповідає вузлам, на яких том наразі використовується. Podʼи, що порушують нову спорідненість, якщо вони вже працюють, можуть продовжувати працювати. Але Kubernetes не підтримує таку конфігурацію. Слід якнайшвидше завершити Podʼи, що її порушують. Через кешування в памʼяті Podʼи, створені після оновлення, протягом короткого часу все ще можуть плануватися за старою спорідненістю вузла.

Щоб скористатися цією можливістю, увімкніть функціональну можливість MutablePVNodeAffinity у таких компонентах:

  • kube-apiserver
  • kubelet

Фаза

PersistentVolume перебуватиме в одній із таких фаз:

Available
вільний ресурс, ще не привʼязаний до PVC
Bound
том привʼязано до PVC
Released
PVC видалено, але кластер ще не повторно використав повʼязаний ресурс сховища
Failed
автоматичне повторне використання тому завершилося збоєм

Ви можете побачити назву PVC, привʼязаного до PV, за допомогою kubectl describe persistentvolume <name>.

Час переходу фази

This is a stable feature in Kubernetes, and has been since the 1.31 release. You can no longer toggle this feature (the associated feature gate has been removed).

Поле .status PersistentVolume може містити альфа-поле lastPhaseTransitionTime. Це поле фіксує час останнього переходу тому між фазами. Для новостворених томів фаза встановлюється в Pending, а lastPhaseTransitionTime — на поточний час.

PersistentVolumeClaims

Кожен PVC містить spec і status, тобто специфікацію та статус PVC. Назва обʼєкта PersistentVolumeClaim має бути дійсним іменем DNS-піддомену.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: slow
  selector:
    matchLabels:
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}

Режими доступу

PVC використовують ті самі домовленості, що й томи, запитуючи сховище з певними режимами доступу.

Режими томів

PVC використовують ту саму домовленість, що й томи, щоб вказати споживання тому як файлової системи або блокового пристрою.

Назва тому

PVC можуть використовувати поле volumeName, щоб явно привʼязатися до певного PersistentVolume. Ви також можете залишити volumeName невстановленим, вказавши, що хочете, щоб Kubernetes налаштував новий PersistentVolume, який відповідає PVC. Якщо вказаний PV уже привʼязаний до іншого PVC, привʼязка застрягне в стані очікування.

Ресурси

PVC, як і Podʼи, можуть запитувати певні кількості ресурсу. У цьому випадку запит стосується сховища. До томів і PVC застосовується та сама модель ресурсів.

Примітка:

Для томів Filesystem запит сховища стосується «зовнішнього» розміру тому (тобто розміру, виділеного бекендом сховища). Це означає, що розмір, доступний для запису, може бути дещо меншим у провайдерів, які будують файлову систему поверх блокового пристрою, через накладні витрати файлової системи. Це особливо помітно з XFS, де стандартно ввімкнено багато можливостей метаданих.

Селектор

PVC можуть вказати селектор міток, щоб додатково відфільтрувати набір томів. До PVC можна привʼязати лише томи, мітки яких відповідають селектору. Селектор може складатися з двох полів:

  • matchLabels — том повинен мати мітку з таким значенням
  • matchExpressions — список вимог, які визначаються за допомогою ключа, списку значень та оператора, який повʼязує ключ і значення. Допустимі оператори включають In, NotIn, Exists та DoesNotExist.

Усі вимоги з matchLabels і matchExpressions обʼєднуються логічним «І» — для збігу всі вони мають бути виконані.

Клас

PVC може запитати певний клас, вказавши назву StorageClass в атрибуті storageClassName. До PVC можна привʼязати лише PV запитаного класу, тобто ті, що мають такий самий storageClassName, як і PVC.

PVC не обовʼязково мають запитувати клас. PVC зі storageClassName, встановленим у "", завжди інтерпретується як такий, що запитує PV без класу, тому його можна привʼязати лише до PV без класу (без анотації або з анотацією, встановленою в ""). PVC без storageClassName — це не зовсім те саме, і кластер обробляє його по-різному залежно від того, чи ввімкнено втулок допуску DefaultStorageClass.

  • Якщо втулок допуску ввімкнено, адміністратор може вказати стандартний StorageClass. Усі PVC без storageClassName можна привʼязати лише до PV цього стандартного класу. Стандартний StorageClass задається встановленням анотації storageclass.kubernetes.io/is-default-class у true в обʼєкті StorageClass. Якщо адміністратор не вказав стандартний клас, кластер реагує на створення PVC так, ніби втулок допуску вимкнено. Якщо вказано кілька стандартних StorageClass, під час динамічного надання PVC використовується найновіший.
  • Якщо втулок допуску вимкнено, поняття стандартного StorageClass немає. Усі PVC зі storageClassName, встановленим у "", можна привʼязати лише до PV, у яких storageClassName також встановлено в "". Однак PVC без storageClassName можна оновити пізніше, коли стандартний StorageClass стане доступним. Якщо PVC оновлено, він більше не привʼязуватиметься до PV, у яких storageClassName також встановлено в "".

Докладніше дивіться в розділі ретроактивне призначення стандартного StorageClass.

Залежно від способу встановлення, менеджер надбудов може розгорнути стандартний StorageClass у кластері Kubernetes під час встановлення.

Коли PVC вказує selector на додаток до запиту StorageClass, вимоги обʼєднуються логічним «І»: до PVC можна привʼязати лише PV запитаного класу із запитаними мітками.

Примітка:

Наразі для PVC з непорожнім selector не можна динамічно надати PV.

У минулому замість атрибута storageClassName використовувалася анотація volume.beta.kubernetes.io/storage-class. Ця анотація все ще працює; однак у майбутньому випуску Kubernetes вона більше не підтримуватиметься.

Ретроактивне призначення стандартного StorageClass

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.28

Ви можете створити PersistentVolumeClaim, не вказуючи storageClassName для нового PVC, навіть якщо у вашому кластері немає стандартного StorageClass. У цьому випадку новий PVC створюється так, як ви його визначили, а storageClassName цього PVC залишається невстановленим, доки не стане доступним стандартний клас.

Коли стандартний StorageClass стає доступним, панель управління визначає всі наявні PVC без storageClassName. Для PVC, які мають порожнє значення storageClassName або не мають цього ключа, панель управління оновлює storageClassName відповідно до нового стандартного StorageClass. Якщо у вас є наявний PVC, де storageClassName має значення "", і ви налаштовуєте стандартний StorageClass, цей PVC не буде оновлено.

Щоб і надалі привʼязуватися до PV із storageClassName, встановленим у "" (за наявності стандартного StorageClass), вам потрібно встановити storageClassName повʼязаного PVC у "".

Така поведінка допомагає адміністраторам змінювати стандартний StorageClass: спочатку вилучити старий, а потім створити або встановити інший. Через це коротке вікно без стандартного класу PVC без storageClassName, створені в цей час, не матимуть стандартного класу, але завдяки ретроактивному призначенню стандартного StorageClass такий спосіб зміни стандартних значень безпечний.

Відстеження невикористаних PVC

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.37; (стандартно увімкнено)

Коли цю можливість увімкнено, контролер захисту PVC додає до кожного PersistentVolumeClaim стан Unused, щоб показати, чи посилається на нього зараз якийсь нетермінальний Pod.

Цей стан має два значення:

Unused зі статусом "True" (причина NoPodsUsingPVC)
Жоден нетермінальний Pod не посилається на цей PVC. lastTransitionTime фіксує час, коли PVC перестав використовуватися.
Unused зі статусом "False" (причина PodUsingPVC)
Принаймні один нетермінальний Pod наразі посилається на цей PVC. lastTransitionTime фіксує час, коли PVC почав використовуватися.

Pod вважається нетермінальним, якщо його фаза не Succeeded і не Failed. Це означає, що Pod в очікуванні (навіть ще не запланований) вважається таким, що використовує PVC.

lastTransitionTime стану Unused можуть використовувати адміністратори кластера, інструменти моніторингу та зовнішні контролери, щоб визначати PVC, які не використовуються тривалий час. Наприклад, щоб знайти всі PVC, які не використовуються понад 30 днів, можна вибрати PVC, у яких стан Unused має status: "True", а lastTransitionTime старший за 30 днів.

Примітка:

Тривалість невикористання, показана цим станом, може бути коротшою за фактичний час невикористання через затримки обробки в контролері або через те, що можливість було ввімкнено, коли PVC уже не використовувався. Стан не оновлюється, коли в PVC встановлено deletionTimestamp (тобто для PVC, що видаляються).

PVC як томи

Podʼи отримують доступ до сховища, використовуючи PVC як том. PVC має існувати в тому самому просторі імен, що й Pod, який його використовує. Кластер знаходить PVC у просторі імен Podʼа і використовує його, щоб отримати PersistentVolume, що стоїть за PVC. Потім том монтується на хост і в Pod.

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim

Примітка щодо просторів імен

Привʼязки PersistentVolumes є ексклюзивними, а оскільки PersistentVolumeClaims є обʼєктами в просторі імен, монтування PVC у режимах "Many" (ROX, RWX) можливе лише в межах одного простору імен.

PersistentVolumes типу hostPath

PersistentVolume типу hostPath використовує файл або теку на вузлі для емуляції мережевого сховища. Дивіться приклад тому типу hostPath.

Підтримка необроблених блокових томів

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.18

Такі втулки томів підтримують необроблені блокові томи, зокрема динамічне надання, де це застосовно:

  • CSI (зокрема деякі типи томів, перенесені на CSI)
  • FC (Fibre Channel)
  • iSCSI
  • Локальний том

PersistentVolume, що використовує необроблений блоковий том

apiVersion: v1
kind: PersistentVolume
metadata:
  name: block-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  volumeMode: Block
  persistentVolumeReclaimPolicy: Retain
  fc:
    targetWWNs: ["50060e801049cfd1"]
    lun: 0
    readOnly: false

PersistentVolumeClaim, який запитує необроблений блоковий том

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: block-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Block
  resources:
    requests:
      storage: 10Gi

Специфікація Podʼа з додаванням шляху необробленого блокового пристрою в контейнері

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-block-volume
spec:
  containers:
    - name: fc-container
      image: fedora:26
      command: ["/bin/sh", "-c"]
      args: [ "tail -f /dev/null" ]
      volumeDevices:
        - name: data
          devicePath: /dev/xvda
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: block-pvc

Примітка:

Під час додавання необробленого блокового пристрою для Podʼа ви вказуєте шлях до пристрою в контейнері замість шляху монтування.

Привʼязка блокових томів

Якщо користувач запитує необроблений блоковий том, вказавши це в полі volumeMode у специфікації PersistentVolumeClaim, правила привʼязки дещо відрізняються від попередніх випусків, які не враховували цей режим як частину специфікації. Нижче наведено таблицю можливих комбінацій, які користувач і адміністратор можуть вказати для запиту необробленого блокового пристрою. Таблиця показує, чи буде том привʼязано за цих комбінацій: Матриця привʼязки томів для статично наданих томів:

PV volumeModePVC volumeModeРезультат
не вказаноне вказаноПРИВʼЯЗАНИЙ
не вказаноBlockНЕ ПРИВʼЯЗАНИЙ
не вказаноFilesystemПРИВʼЯЗАНИЙ
Blockне вказаноНЕ ПРИВʼЯЗАНИЙ
BlockBlockПРИВʼЯЗАНИЙ
BlockFilesystemНЕ ПРИВʼЯЗАНИЙ
FilesystemFilesystemПРИВʼЯЗАНИЙ
FilesystemBlockНЕ ПРИВʼЯЗАНИЙ
Filesystemне вказаноПРИВʼЯЗАНИЙ

Примітка:

Для альфа-випуску підтримуються лише статично надані томи. Адміністратори мають враховувати ці значення під час роботи з необробленими блоковими пристроями.

Підтримка знімків томів та відновлення тому зі знімка

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.20

Знімки томів підтримують лише зовнішні втулки томів CSI. Докладніше дивіться в Знімки томів. Вбудовані втулки томів застаріли. Про застарілі втулки томів читайте в FAQ про втулки томів.

Створення PersistentVolumeClaim зі знімка тому

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: restore-pvc
spec:
  storageClassName: csi-hostpath-sc
  dataSource:
    name: new-snapshot-test
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

Клонування томів

Клонування томів доступне лише для втулків томів CSI.

Створення PersistentVolumeClaim з наявного PVC

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: cloned-pvc
spec:
  storageClassName: my-csi-plugin
  dataSource:
    name: existing-src-pvc-name
    kind: PersistentVolumeClaim
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

Наповнювачі томів та джерела даних

Клонування томів та відновлення зі знімка попередньо заповнюють новий том із вбудованого джерела даних. Наповнювачі томів розширюють цей механізм, щоб PersistentVolumeClaim можна було попередньо заповнити з інших видів джерел (власного ресурсу), на які він посилається через поле dataSourceRef:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: populated-pvc
spec:
  dataSourceRef:
    name: example-name
    kind: ExampleDataSource
    apiGroup: example.storage.k8s.io
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

Докладніше, зокрема про джерела даних між просторами імен, дивіться в Наповнювачі томів та джерела даних.

Створення переносної конфігурації

Якщо ви пишете шаблони конфігурації або приклади, які працюють на широкому спектрі кластерів і потребують постійного сховища, рекомендується використовувати такий підхід:

  • Додавайте обʼєкти PersistentVolumeClaim до свого набору конфігурації (поряд із Deployments, ConfigMaps тощо).
  • Не додавайте обʼєкти PersistentVolume до конфігурації, оскільки користувач, який застосовує конфігурацію, може не мати дозволу на створення PersistentVolumes.
  • Дайте користувачеві можливість вказати назву класу сховища під час застосування шаблону.
    • Якщо користувач вказує назву класу сховища, запишіть це значення в поле persistentVolumeClaim.storageClassName. Це приведе до зіставлення PVC з правильним класом сховища, якщо адміністратор увімкнув StorageClasses у кластері.
    • Якщо користувач не вказує назву класу сховища, залиште поле persistentVolumeClaim.storageClassName зі значенням nil. Це призведе до автоматичного надання PV для користувача зі стандартним StorageClass кластера. Багато кластерних середовищ мають встановлений стандартний StorageClass, або адміністратори можуть створити власний стандартний StorageClass.
  • У своїх інструментах стежте за PVC, які не привʼязуються протягом певного часу, і показуйте це користувачеві, оскільки це може означати, що кластер не має підтримки динамічного сховища (у цьому випадку користувач має створити відповідний PV) або не має системи зберігання (у цьому випадку користувач не може розгорнути конфігурацію, яка потребує PVC).

Що далі

Довідники API

Дізнайтеся більше про описані на цій сторінці API:

3 - Проєкційні томи

У цьому документі описано проєкційні томи в Kubernetes. Рекомендується ознайомитися з томами.

Вступ

Том projected зіставляє кілька наявних джерел томів з однією текою.

Наразі можна проєцювати такі типи джерел томів:

Усі джерела мають бути в тому самому просторі імен, що й Pod. Докладніше дивіться в проєктному документі all-in-one volume.

Приклад конфігурації із secret, downwardAPI та configMap

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: container-test
    image: busybox:1.28
    command: ["sleep", "3600"]
    volumeMounts:
    - name: all-in-one
      mountPath: "/projected-volume"
      readOnly: true
  volumes:
  - name: all-in-one
    projected:
      sources:
      - secret:
          name: mysecret
          items:
          - key: username
            path: my-group/my-username
      - downwardAPI:
          items:
          - path: "labels"
            fieldRef:
              fieldPath: metadata.labels
          - path: "cpu_limit"
            resourceFieldRef:
              containerName: container-test
              resource: limits.cpu
      - configMap:
          name: myconfigmap
          items:
          - key: config
            path: my-group/my-config

Приклад конфігурації: secrets із нестандартним режимом дозволів

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: container-test
    image: busybox:1.28
    command: ["sleep", "3600"]
    volumeMounts:
    - name: all-in-one
      mountPath: "/projected-volume"
      readOnly: true
  volumes:
  - name: all-in-one
    projected:
      sources:
      - secret:
          name: mysecret
          items:
          - key: username
            path: my-group/my-username
      - secret:
          name: mysecret2
          items:
          - key: password
            path: my-group/my-password
            mode: 0777

Кожне джерело проєкційного тому перелічено в специфікації в розділі sources. Параметри майже такі самі, за двома винятками:

  • Для secrets поле secretName змінено на name, щоб узгодити його з іменуванням ConfigMap.
  • defaultMode можна вказати лише на рівні projected, а не для кожного джерела тому. Однак, як показано вище, ви можете явно встановити mode для кожної окремої проєкції.

Проєкційні томи serviceAccountToken

Ви можете вставити токен поточного ServiceAccount у Pod за вказаним шляхом. Наприклад:

apiVersion: v1
kind: Pod
metadata:
  name: sa-token-test
spec:
  containers:
  - name: container-test
    image: busybox:1.28
    command: ["sleep", "3600"]
    volumeMounts:
    - name: token-vol
      mountPath: "/service-account"
      readOnly: true
  serviceAccountName: default
  volumes:
  - name: token-vol
    projected:
      sources:
      - serviceAccountToken:
          audience: api
          expirationSeconds: 3600
          path: token

Pod із прикладу має проєкційний том, що містить вставлений токен ServiceAccount. Контейнери в цьому Podʼі можуть використовувати цей токен для доступу до API-сервера Kubernetes, автентифікуючись від імені ServiceAccount цього Podʼа. Поле audience містить цільову аудиторію токена. Отримувач токена повинен ідентифікувати себе ідентифікатором, вказаним в аудиторії токена, інакше він має відхилити токен. Це поле є необовʼязковим, і його стандартним значенням є ідентифікатор API-сервера.

Поле expirationSeconds містить очікуваний термін дії токена ServiceAccount. Стандартно він становить 1 годину і має бути не меншим за 10 хвилин (600 секунд). Адміністратор також може обмежити його максимальне значення, вказавши параметр --service-account-max-token-expiration для API-сервера. Поле path задає шлях відносно точки монтування проєкційного тому.

Примітка:

Контейнер, що використовує джерело проєкційного тому як монтування тому subPath, не отримуватиме оновлень для цих джерел томів.

Проєкційні томи clusterTrustBundle

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.37; (стандартно увімкнено)
More information about this feature

This is a stable feature in Kubernetes, and has been since version 1.37. It was first available in the v1.29 release.

Джерело проєкційного тому clusterTrustBundle вставляє вміст одного або кількох обʼєктів ClusterTrustBundle як файл, що автоматично оновлюється, у файлову систему контейнера.

ClusterTrustBundles можна вибрати за назвою або за назвою підписувача.

Щоб вибрати за назвою, використовуйте поле name, щоб вказати один обʼєкт ClusterTrustBundle.

Щоб вибрати за назвою підписувача, використовуйте поле signerName (і, за потреби, поле labelSelector), щоб вказати набір обʼєктів ClusterTrustBundle, які використовують задану назву підписувача. Якщо labelSelector відсутній, вибираються всі ClusterTrustBundles цього підписувача.

kubelet вилучає дублікати сертифікатів у вибраних обʼєктах ClusterTrustBundle, нормалізує подання PEM (відкидаючи коментарі та заголовки), змінює порядок сертифікатів і записує їх у файл, вказаний у path. Коли змінюється набір вибраних ClusterTrustBundles або їхній вміст, kubelet підтримує файл в актуальному стані.

Стандартно kubelet не дає Podʼу запуститися, якщо вказаний ClusterTrustBundle не знайдено або якщо signerName / labelSelector не відповідають жодному ClusterTrustBundle. Якщо така поведінка вам не підходить, встановіть поле optional у true, і Pod запуститься з порожнім файлом за шляхом path.

apiVersion: v1
kind: Pod
metadata:
  name: sa-ctb-name-test
spec:
  containers:
  - name: container-test
    image: busybox
    command: ["sleep", "3600"]
    volumeMounts:
    - name: token-vol
      mountPath: "/root-certificates"
      readOnly: true
  serviceAccountName: default
  volumes:
  - name: token-vol
    projected:
      sources:
      - clusterTrustBundle:
          name: example
          path: example-roots.pem
      - clusterTrustBundle:
          signerName: "example.com/mysigner"
          labelSelector:
            matchLabels:
              version: live
          path: mysigner-roots.pem
          optional: true

Проєкційні томи podCertificate

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.37; (стандартно увімкнено)
More information about this feature

This is a stable feature in Kubernetes, and has been since version 1.37. It was first available in the v1.34 release.

Джерело проєкційного тому podCertificate безпечно надає приватний ключ і ланцюжок сертифікатів X.509, які Pod використовує як клієнтські або серверні облікові дані. Потім kubelet оновлює приватний ключ і ланцюжок сертифікатів, коли наближається завершення їхнього терміну дії. Застосунку потрібно лише своєчасно перезавантажувати файл, коли він змінюється, за допомогою механізму на кшталт inotify або опитування.

Кожна проєкція podCertificate підтримує такі конфігураційні поля:

  • signerName: підписувач, який має видати сертифікат. Зверніть увагу, що підписувачі можуть мати власні вимоги до доступу та можуть відмовитися видавати сертифікати вашому Podʼу.
  • keyType: Тип приватного ключа, який повинен бути згенерований. Дійсні значення: ED25519, ECDSAP256, ECDSAP384, ECDSAP521, RSA3072 і RSA4096.
  • maxExpirationSeconds: Максимальний термін дії сертифіката, виданого Podʼу, який ви приймете. Якщо не вказано, стандартно використовується 86400 (24 години). Має бути не менше 3600 (1 година) і не більше 7862400 (91 день). Вбудовані підписувачі Kubernetes обмежені максимальним терміном дії 86400 (1 день). Підписувач може видати сертифікат із терміном дії, коротшим за вказаний вами.
  • credentialBundlePath: Відносний шлях у межах проєкції, куди слід записати пакет облікових даних. Пакет облікових даних — це файл у форматі PEM, де перший блок — це блок "PRIVATE KEY", що містить приватний ключ, серіалізований у PKCS#8, а решта блоків — це блоки "CERTIFICATE", які утворюють ланцюжок сертифікатів (кінцевий сертифікат і всі проміжні).
  • keyPath і certificateChainPath: Окремі шляхи, куди kubelet має записати лише приватний ключ або ланцюжок сертифікатів.
  • userAnnotations: мапа, яка дозволяє передавати додаткову інформацію до реалізації підписувача. Вона дослівно копіюється в поле spec.unverifiedUserAnnotations обʼєктів PodCertificateRequest, які створює kubelet. Записи проходять ту саму перевірку, що й анотації метаданих обʼєкта, але додатково всі ключі повинні мати доменний префікс. На значення не накладаються жодні обмеження, крім загального обмеження розміру всього поля. Окрім цих базових перевірок, API-сервер не виконує жодних додаткових. Реалізації підписувача мають бути дуже обережними під час використання цих даних. Підписувачі не повинні довіряти цим даним без попереднього виконання відповідних кроків перевірки. Підписувачі мають документувати ключі та значення, які вони підтримують. Підписувачі мають відхиляти запити з ключами, які вони не розпізнають.

Примітка:

Більшість застосунків мають віддавати перевагу credentialBundlePath, якщо їм не потрібні ключ і сертифікати в окремих файлах з міркувань сумісності. kubelet використовує стратегію атомарного запису на основі символічних посилань, щоб під час відкриття файлів, які він проєцює, ви читали або старий, або новий вміст. Однак якщо ви читаєте ключ і ланцюжок сертифікатів з окремих файлів, kubelet може змінити облікові дані після першого читання й до другого, і ваш застосунок завантажить ключ і сертифікат, що не збігаються.
# Sample Pod spec that uses a podCertificate projection to request an ED25519
# private key, a certificate from the `coolcert.example.com/foo` signer, and
# write the results to `/var/run/my-x509-credentials/credentialbundle.pem`.
apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: podcertificate-pod
spec:
  serviceAccountName: default
  containers:
  - image: debian
    name: main
    command: ["sleep", "infinity"]
    volumeMounts:
    - name: my-x509-credentials
      mountPath: /var/run/my-x509-credentials
  volumes:
  - name: my-x509-credentials
    projected:
      defaultMode: 0644
      sources:
      - podCertificate:
          keyType: ED25519
          signerName: coolcert.example.com/foo
          credentialBundlePath: credentialbundle.pem
          userAnnotations:
            example.com/annotation1: "value1"
            example.com/annotation2: "value2"

Взаємодія із SecurityContext

Пропозиція щодо обробки дозволів файлів у вдосконаленні проєкційних томів ServiceAccount запровадила встановлення правильних дозволів власника для спроєцьованих файлів.

Linux

У Podʼах Linux, які мають проєкційний том і RunAsUser, встановлений у Pod SecurityContext, спроєцьовані файли мають правильно встановленого власника, зокрема власника-користувача контейнера.

Коли всі контейнери в Podʼі мають однакове значення runAsUser у своєму PodSecurityContext або SecurityContext контейнера, kubelet гарантує, що вміст тому serviceAccountToken належить цьому користувачеві, а файл токена має режим дозволів 0600.

Примітка:

Ефемерні контейнери, додані до Podʼа після його створення, не змінюють дозволи томів, встановлені під час створення Podʼа.

Якщо дозволи тому serviceAccountToken Podʼа було встановлено на 0600, оскільки всі інші контейнери в Podʼі мають однакове значення runAsUser, ефемерні контейнери повинні використовувати той самий runAsUser, щоб мати змогу прочитати токен.

Windows

У Podʼах Windows, які мають проєкційний том і RunAsUsername, встановлений у Pod SecurityContext, власність не застосовується через те, як у Windows керуються облікові записи користувачів. Windows зберігає локальні облікові записи користувачів і груп у файлі бази даних Security Account Manager (SAM) і керує ними. Кожен контейнер має власний екземпляр бази даних SAM, який хост не бачить під час роботи контейнера. Контейнери Windows призначені для запуску частини ОС у режимі користувача ізольовано від хоста, тому вони підтримують віртуальну базу даних SAM. Як наслідок, kubelet, що працює на хості, не може динамічно налаштовувати власність файлів хоста для віртуалізованих облікових записів контейнерів. Якщо файли на хост-машині потрібно спільно використовувати з контейнером, рекомендується розмістити їх у власному монтуванні тому поза C:\.

Стандартно спроєцьовані файли матимуть такого власника, як показано для прикладу файлу проєкційного тому:

PS C:\> Get-Acl C:\var\run\secrets\kubernetes.io\serviceaccount\..2021_08_31_22_22_18.318230061\ca.crt | Format-List

Path   : Microsoft.PowerShell.Core\FileSystem::C:\var\run\secrets\kubernetes.io\serviceaccount\..2021_08_31_22_22_18.318230061\ca.crt
Owner  : BUILTIN\Administrators
Group  : NT AUTHORITY\SYSTEM
Access : NT AUTHORITY\SYSTEM Allow  FullControl
         BUILTIN\Administrators Allow  FullControl
         BUILTIN\Users Allow  ReadAndExecute, Synchronize
Audit  :
Sddl   : O:BAG:SYD:AI(A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;0x1200a9;;;BU)

Це означає, що всі користувачі-адміністратори, такі як ContainerAdministrator, матимуть доступ на читання, запис і виконання, а користувачі, які не є адміністраторами, — на читання й виконання.

Примітка:

Загалом не рекомендується надавати контейнеру доступ до хоста, оскільки це може відкрити двері для потенційних експлойтів безпеки.

Створення Podʼа Windows із RunAsUser у його SecurityContext призведе до того, що Pod назавжди застрягне на ContainerCreating. Тому не рекомендується використовувати параметр RunAsUser, призначений лише для Linux, з Podʼами Windows.

4 - Ефемерні томи

У цьому документі описано ефемерні томи в Kubernetes. Рекомендується ознайомитися з томами, зокрема з PersistentVolumeClaim та PersistentVolume.

Деяким застосункам потрібне додаткове сховище, але їм не важливо, чи зберігаються ці дані постійно між перезапусками. Наприклад, сервіси кешування часто обмежені обсягом памʼяті й можуть переміщувати рідко використовувані дані в сховище, повільніше за памʼять, майже не впливаючи на загальну продуктивність.

Інші застосунки очікують, що у файлах будуть певні вхідні дані лише для читання, наприклад, конфігураційні дані або секретні ключі.

Ефемерні томи призначені для таких сценаріїв використання. Оскільки томи живуть стільки ж, скільки Pod, і створюються та видаляються разом із ним, Podʼи можна зупиняти й перезапускати, не обмежуючись місцем, де доступний певний постійний том.

Ефемерні томи вказуються inline у специфікації Podʼа, що спрощує розгортання застосунків і керування ними.

Типи ефемерних томів

Kubernetes підтримує кілька різновидів ефемерних томів для різних цілей:

  • emptyDir: порожній під час запуску Podʼа, сховище надається локально з базової теки kubelet (зазвичай кореневий диск) або з оперативної памʼяті
  • configMap, downwardAPI, secret: вставляють різні види даних Kubernetes у Pod
  • image: дозволяє монтувати файли образів контейнерів або артефакти безпосередньо в Pod.
  • ефемерні томи CSI: схожі на попередні види томів, але надаються спеціальними драйверами CSI, які спеціально підтримують цю можливість
  • загальні ефемерні томи, які можуть надавати всі драйвери сховища, що також підтримують постійні томи

emptyDir, configMap, downwardAPI, secret надаються як локальне тимчасове сховище. Ними керує kubelet на кожному вузлі.

Ефемерні томи CSI повинні надаватися сторонніми драйверами сховища CSI.

Загальні ефемерні томи можуть надаватися сторонніми драйверами сховища CSI, а також будь-яким іншим драйвером сховища, який підтримує динамічне надання. Деякі драйвери CSI написані спеціально для ефемерних томів CSI і не підтримують динамічне надання: їх не можна використовувати для загальних ефемерних томів.

Перевага сторонніх драйверів полягає в тому, що вони можуть пропонувати функціональність, яку сам Kubernetes не підтримує, наприклад, сховище з іншими характеристиками продуктивності, ніж диск, яким керує kubelet, або вставлення інших даних.

Ефемерні томи CSI

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.25

Примітка:

Ефемерні томи CSI підтримує лише частина драйверів CSI. Список драйверів Kubernetes CSI показує, які драйвери підтримують ефемерні томи.

Концептуально ефемерні томи CSI схожі на типи томів configMap, downwardAPI та secret: сховище керується локально на кожному вузлі й створюється разом з іншими локальними ресурсами після того, як Pod заплановано на вузол. На цьому етапі Kubernetes уже не має поняття про перепланування Podʼів. Створення тому має бути таким, щоб збій був малоймовірним, інакше запуск Podʼа застрягне. Зокрема, планування Podʼів з урахуванням місткості сховища для цих томів не підтримується. Наразі на них також не поширюються обмеження використання ресурсів сховища Podʼа, оскільки kubelet може застосовувати їх лише до сховища, яким керує сам.

Ось приклад маніфесту для Podʼа, який використовує ефемерне сховище CSI:

kind: Pod
apiVersion: v1
metadata:
  name: my-csi-app
spec:
  containers:
    - name: my-frontend
      image: busybox:1.28
      volumeMounts:
      - mountPath: "/data"
        name: my-csi-inline-vol
      command: [ "sleep", "1000000" ]
  volumes:
    - name: my-csi-inline-vol
      csi:
        driver: inline.storage.kubernetes.io
        volumeAttributes:
          foo: bar

volumeAttributes визначають, який том готує драйвер. Ці атрибути специфічні для кожного драйвера й не стандартизовані. Додаткові інструкції дивіться в документації кожного драйвера CSI.

Обмеження драйверів CSI

Ефемерні томи CSI дозволяють користувачам передавати volumeAttributes безпосередньо драйверу CSI як частину специфікації Podʼа. Драйвер CSI, який дозволяє volumeAttributes, що зазвичай доступні лише адміністраторам, НЕ підходить для використання в inline-ефемерному томі. Наприклад, параметри, які зазвичай визначаються в StorageClass, не слід відкривати користувачам через inline-ефемерні томи.

Адміністратори кластера, яким потрібно обмежити драйвери CSI, дозволені для використання як inline-томи у специфікації Podʼа, можуть зробити це так:

  • Вилучити Ephemeral із volumeLifecycleModes у специфікації CSIDriver, що не дасть використовувати драйвер як inline-ефемерний том.
  • Використати вебхук допуску, щоб обмежити використання цього драйвера.

Загальні ефемерні томи

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.23

Загальні ефемерні томи схожі на томи emptyDir у тому сенсі, що надають кожному Podʼу теку для робочих даних, яка зазвичай порожня після надання. Але вони також можуть мати додаткові можливості:

Приклад:

kind: Pod
apiVersion: v1
metadata:
  name: my-app
spec:
  containers:
    - name: my-frontend
      image: busybox:1.28
      volumeMounts:
      - mountPath: "/scratch"
        name: scratch-volume
      command: [ "sleep", "1000000" ]
  volumes:
    - name: scratch-volume
      ephemeral:
        volumeClaimTemplate:
          metadata:
            labels:
              type: my-frontend-volume
          spec:
            accessModes: [ "ReadWriteOnce" ]
            storageClassName: "scratch-storage-class"
            resources:
              requests:
                storage: 1Gi

Життєвий цикл та PersistentVolumeClaim

Ключова ідея дизайну полягає в тому, що параметри для PersistentVolumeClaim дозволені всередині джерела тому Podʼа. Підтримуються мітки, анотації та весь набір полів PersistentVolumeClaim. Коли такий Pod створюється, контролер ефемерних томів створює фактичний обʼєкт PersistentVolumeClaim у тому самому просторі імен, що й Pod, і забезпечує видалення PersistentVolumeClaim під час видалення Podʼа.

Це запускає привʼязку та/або надання тому: або негайно, якщо StorageClass використовує негайну привʼязку томів, або коли Pod попередньо заплановано на вузол (режим привʼязки томів WaitForFirstConsumer). Другий варіант рекомендовано для загальних ефемерних томів, оскільки тоді планувальник може вільно вибрати придатний вузол для Podʼа. За негайної привʼязки планувальник змушений вибрати вузол, який має доступ до тому, щойно том стає доступним.

З погляду власності на ресурси Pod, який має загальне ефемерне сховище, є власником PersistentVolumeClaim(ів), що надають це ефемерне сховище. Коли Pod видаляють, збирач сміття Kubernetes видаляє PVC, що зазвичай спричиняє видалення тому, оскільки стандартна політика повторного використання класів сховища — видаляти томи. Ви можете створити квазіефемерне локальне сховище за допомогою StorageClass із політикою повторного використання retain: сховище переживає Pod, і в цьому випадку потрібно подбати про окреме очищення тому.

Поки ці PVC існують, їх можна використовувати, як будь-який інший PVC. Зокрема, на них можна посилатися як на джерело даних під час клонування томів або створення знімків. Обʼєкт PVC також містить поточний статус тому.

Іменування PersistentVolumeClaim

Назви автоматично створених PVC є детермінованими: назва є комбінацією назви Podʼа та назви тому з дефісом (-) посередині. У наведеному вище прикладі назва PVC буде my-app-scratch-volume. Таке детерміноване іменування полегшує взаємодію з PVC, оскільки його не потрібно шукати, якщо відомі назва Podʼа та назва тому.

Детерміноване іменування також створює потенційний конфлікт між різними Podʼами (Pod "pod-a" з томом "scratch" та інший Pod з назвою "pod" і томом "a-scratch" отримають однакову назву PVC "pod-a-scratch"), а також між Podʼами та PVC, створеними вручну.

Такі конфлікти виявляються: PVC використовується для ефемерного тому, лише якщо його створено для цього Podʼа. Ця перевірка базується на відносинах власності. Наявний PVC не перезаписується і не змінюється. Але це не розвʼязує конфлікт, оскільки без правильного PVC Pod не може запуститися.

Увага:

Будьте обережні, називаючи Podʼи й томи в тому самому просторі імен, щоб таких конфліктів не виникало.

Безпека

Використання загальних ефемерних томів дозволяє користувачам створювати PVC опосередковано, якщо вони можуть створювати Podʼи, навіть якщо в них немає дозволу створювати PVC безпосередньо. Адміністратори кластера мають про це знати. Якщо це не відповідає їхній моделі безпеки, вони повинні використовувати вебхук допуску, який відхиляє обʼєкти, такі як Podʼи, що мають загальний ефемерний том.

Звичайна квота простору імен для PVC однаково застосовується, тому навіть якщо користувачам дозволено використовувати цей новий механізм, вони не можуть обходити з його допомогою інші політики.

Що далі

Ефемерні томи, керовані kubelet

Дивіться локальне тимчасове сховище.

Ефемерні томи CSI

Загальні ефемерні томи

5 - Класи атрибутів томів

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.36
More information about this feature

This is a stable feature in Kubernetes, and has been since version v1.36. It was first available in the v1.29 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate VolumeAttributesClass, Kubernetes ignores it but does not report any error.

На цій сторінці передбачається, що ви знайомі зі StorageClasses, томами та PersistentVolumes у Kubernetes.

VolumeAttributesClass надає адміністраторам можливість описати змінні «класи» сховища, які вони пропонують. Різні класи можуть відповідати різним рівням якості обслуговування. Сам Kubernetes не має власної думки щодо того, що представляють ці класи.

Ця можливість загальнодоступна (GA) з версії 1.34, і користувачі можуть вимкнути її.

Крім того, VolumeAttributesClasses можна використовувати лише зі сховищем на основі Container Storage Interface і лише там, де відповідний драйвер CSI реалізує API ModifyVolume.

API VolumeAttributesClass

Кожен VolumeAttributesClass містить driverName та parameters, які використовуються, коли PersistentVolume (PV), що належить до цього класу, потрібно динамічно надати або змінити.

Назва обʼєкта VolumeAttributesClass є важливою: саме за нею користувачі можуть запитати певний клас. Адміністратори встановлюють назву та інші параметри класу під час першого створення обʼєктів VolumeAttributesClass. Хоча назву обʼєкта VolumeAttributesClass у PersistentVolumeClaim можна змінювати, параметри наявного класу є незмінними.

apiVersion: storage.k8s.io/v1
kind: VolumeAttributesClass
metadata:
  name: silver
driverName: csi.storage.example.com
parameters:
  iops: "3000"
  throughput: "50Mi"

Provisioner

Кожен VolumeAttributesClass має provisioner, який визначає, який втулок томів використовується для надання PV. Поле driverName є обовʼязковим.

Підтримку цієї можливості для VolumeAttributesClass реалізовано в kubernetes-csi/external-provisioner.

Ви не обмежені вказанням kubernetes-csi/external-provisioner. Ви також можете запускати та вказувати зовнішні provisioners — незалежні програми, які відповідають специфікації, визначеній Kubernetes. Автори зовнішніх provisioners мають повну свободу щодо того, де розміщено їхній код, як постачається provisioner, як його потрібно запускати, який втулок томів він використовує тощо.

Щоб зрозуміти, як provisioner працює з VolumeAttributesClass, зверніться до документації CSI external-provisioner.

Resizer

Кожен VolumeAttributesClass має resizer, який визначає, який втулок томів використовується для зміни PV. Поле driverName є обовʼязковим.

Підтримку зміни томів для VolumeAttributesClass реалізовано в kubernetes-csi/external-resizer.

Наприклад, наявний PersistentVolumeClaim використовує VolumeAttributesClass з назвою silver:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pv-claim
spec:
  …
  volumeAttributesClassName: silver
  …

У кластері доступний новий VolumeAttributesClass gold:

apiVersion: storage.k8s.io/v1
kind: VolumeAttributesClass
metadata:
  name: gold
driverName: csi.storage.example.com
parameters:
  iops: "4000"
  throughput: "60Mi"

Кінцевий користувач може оновити PVC, вказавши новий VolumeAttributesClass gold, і застосувати зміни:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pv-claim
spec:
  …
  volumeAttributesClassName: gold
  …

Щоб зрозуміти, як resizer працює з VolumeAttributesClass, зверніться до документації CSI external-resizer.

Параметри

VolumeAttributeClasses мають параметри, які описують томи, що до них належать. Залежно від provisioner або resizer можуть прийматися різні параметри. Наприклад, значення 4000 для параметра iops і параметр throughput є специфічними для GCE PD. Якщо параметр пропущено, під час надання тому використовується стандартне значення. Якщо користувач застосовує PVC з іншим VolumeAttributesClass із пропущеними параметрами, стандартне значення параметрів може використовуватися залежно від реалізації драйвера CSI. Докладніше дивіться в документації відповідного драйвера CSI.

Для VolumeAttributesClass можна визначити не більше 512 параметрів. Загальна довжина обʼєкта параметрів, включно з ключами та значеннями, не може перевищувати 256 KiB.

6 - Класи сховищ

У цьому документі описано концепцію StorageClass у Kubernetes. Рекомендується ознайомитися з томами та постійними томами.

StorageClass надає адміністраторам можливість описати класи сховища, які вони пропонують. Різні класи можуть відповідати рівням якості обслуговування, політикам резервного копіювання або довільним політикам, визначеним адміністраторами кластера. Сам Kubernetes не має власної думки щодо того, що представляють класи.

Концепція класу сховища в Kubernetes схожа на «профілі» в дизайні деяких інших систем зберігання.

Обʼєкти StorageClass

Кожен StorageClass містить поля provisioner, parameters та reclaimPolicy, які використовуються, коли PersistentVolume, що належить до цього класу, потрібно надати динамічно, щоб задовольнити PersistentVolumeClaim (PVC).

Назва обʼєкта StorageClass є важливою: саме за нею користувачі можуть запитати певний клас. Адміністратори встановлюють назву та інші параметри класу під час першого створення обʼєктів StorageClass.

Як адміністратор, ви можете вказати стандартний StorageClass, який застосовується до будь-яких PVC, що не запитують конкретний клас. Докладніше дивіться концепцію PersistentVolumeClaim.

Ось приклад StorageClass:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: low-latency
  annotations:
    storageclass.kubernetes.io/is-default-class: "false"
provisioner: csi-driver.example-vendor.example
reclaimPolicy: Retain # default value is Delete
allowVolumeExpansion: true
mountOptions:
  - discard # this might enable UNMAP / TRIM at the block storage layer
volumeBindingMode: WaitForFirstConsumer
parameters:
  guaranteedReadWriteLatency: "true" # provider-specific

Стандартний StorageClass

Ви можете позначити StorageClass як стандартний для свого кластера. Інструкції щодо встановлення стандартного StorageClass дивіться в Зміна стандартного StorageClass.

Якщо PVC не вказує storageClassName, використовується стандартний StorageClass.

Якщо ви встановите анотацію storageclass.kubernetes.io/is-default-class у true для кількох StorageClass у своєму кластері, а потім створите PersistentVolumeClaim без встановленого storageClassName, Kubernetes використає найновіший стандартний StorageClass.

Примітка:

Намагайтеся мати у своєму кластері лише один StorageClass, позначений як стандартний. Kubernetes дозволяє мати кілька стандартних StorageClasses, щоб забезпечити безшовну міграцію.

Ви можете створити PersistentVolumeClaim, не вказуючи storageClassName для нового PVC, навіть якщо у вашому кластері немає стандартного StorageClass. У цьому випадку новий PVC створюється так, як ви його визначили, а storageClassName цього PVC залишається невстановленим, доки не стане доступним стандартний клас.

Ви можете мати кластер без стандартного StorageClass. Якщо ви не позначите жоден StorageClass як стандартний (і його не встановлено для вас, наприклад, хмарним провайдером), Kubernetes не зможе застосувати це стандартне значення до PersistentVolumeClaims, яким воно потрібне.

Якщо або коли стандартний StorageClass стає доступним, панель управління визначає всі наявні PVC без storageClassName. Для PVC, які мають порожнє значення storageClassName або не мають цього ключа, панель управління оновлює storageClassName відповідно до нового стандартного StorageClass. Якщо у вас є наявний PVC, де storageClassName має значення "", і ви налаштовуєте стандартний StorageClass, цей PVC не буде оновлено.

Щоб і надалі привʼязуватися до PV із storageClassName, встановленим у "" (за наявності стандартного StorageClass), вам потрібно встановити storageClassName повʼязаного PVC у "".

Provisioner

Кожен StorageClass має provisioner, який визначає, який втулок томів використовується для надання PV. Це поле є обовʼязковим.

Втулок томівВнутрішній provisionerПриклад конфігурації
AzureFile✓Azure File
CephFS--
FC--
FlexVolume--
iSCSI--
Local-Local
NFS-NFS
PortworxVolume✓Portworx Volume
RBD-Ceph RBD
VsphereVolume✓vSphere

Ви не обмежені вказанням перелічених тут «внутрішніх» provisioners (назви яких мають префікс "kubernetes.io" і які постачаються разом із Kubernetes). Ви також можете запускати та вказувати зовнішні provisioners — незалежні програми, які відповідають специфікації, визначеній Kubernetes. Автори зовнішніх provisioners мають повну свободу щодо того, де розміщено їхній код, як постачається provisioner, як його потрібно запускати, який втулок томів він використовує (зокрема Flex) тощо. У репозиторії kubernetes-sigs/sig-storage-lib-external-provisioner розміщено бібліотеку для написання зовнішніх provisioners, яка реалізує більшу частину специфікації. Деякі зовнішні provisioners перелічено в репозиторії kubernetes-sigs/sig-storage-lib-external-provisioner.

Наприклад, NFS не надає внутрішнього provisioner, але можна використовувати зовнішній. Також трапляється, що сторонні постачальники сховищ надають власний зовнішній provisioner.

Політика повторного використання

PersistentVolumes, які динамічно створюються за допомогою StorageClass, матимуть політику повторного використання, вказану в полі reclaimPolicy класу, яка може бути Delete або Retain. Якщо reclaimPolicy не вказано під час створення обʼєкта StorageClass, стандартним значенням буде Delete.

PersistentVolumes, створені вручну та керовані за допомогою StorageClass, матимуть ту політику повторного використання, яку їм було призначено під час створення.

Розширення томів

PersistentVolumes можна налаштувати як розширювані. Це дозволяє змінювати розмір тому, редагуючи відповідний обʼєкт PVC і запитуючи новий, більший обсяг сховища.

Такі типи томів підтримують розширення, коли базовий StorageClass має поле allowVolumeExpansion зі значенням true.

Таблиця типів томів і версій Kubernetes, яких вони потребують
Тип томуПотрібна версія Kubernetes для розширення тому
Azure File1.11
CSI1.24
FlexVolume1.13
Portworx1.11
rbd1.11

Примітка:

Можливість розширення томів можна використовувати лише для збільшення тому, але не для його зменшення.

Параметри монтування

PersistentVolumes, які динамічно створюються за допомогою StorageClass, матимуть параметри монтування, вказані в полі mountOptions класу.

Якщо втулок томів не підтримує параметри монтування, але їх вказано, надання завершиться невдачею. Параметри монтування не перевіряються ні на рівні класу, ні на рівні PV. Якщо параметр монтування недійсний, монтування PV завершиться невдачею.

Режим привʼязки тому

Поле volumeBindingMode визначає, коли мають відбуватися привʼязка томів і динамічне надання. Якщо його не встановлено, стандартно використовується режим Immediate.

Режим Immediate означає, що привʼязка томів і динамічне надання відбуваються одразу після створення PersistentVolumeClaim. Для бекендів сховища, які обмежені топологією й не доступні глобально з усіх вузлів кластера, PersistentVolumes будуть привʼязані або надані без урахування вимог планування Podʼа. Це може призвести до Podʼів, не придатних для планування.

Адміністратор кластера може розвʼязати цю проблему, вказавши режим WaitForFirstConsumer, який відкладає привʼязку та надання PersistentVolume до створення Podʼа, що використовує PersistentVolumeClaim. PersistentVolumes будуть вибрані або надані відповідно до топології, заданої обмеженнями планування Podʼа. Це, зокрема, вимоги до ресурсів, селектори вузлів, спорідненість та антиспорідненість Podʼів, а також taints і tolerations.

Такі втулки підтримують WaitForFirstConsumer із динамічним наданням:

  • Томи CSI, за умови, що конкретний драйвер CSI це підтримує

Такі втулки підтримують WaitForFirstConsumer із привʼязкою попередньо створених PersistentVolume:

  • Томи CSI, за умови, що конкретний драйвер CSI це підтримує
  • local

Примітка:

Якщо ви вирішили використовувати WaitForFirstConsumer, не використовуйте nodeName у специфікації Podʼа для задання спорідненості вузла. Якщо в цьому випадку використати nodeName, планувальник буде оминуто, а PVC залишиться в стані pending.

Натомість ви можете використати селектор вузла для kubernetes.io/hostname:

apiVersion: v1
kind: Pod
metadata:
  name: task-pv-pod
spec:
  nodeSelector:
    kubernetes.io/hostname: kube-01
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
        claimName: task-pv-claim
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage

Дозволені топології

Коли оператор кластера вказує режим привʼязки томів WaitForFirstConsumer, у більшості випадків більше не потрібно обмежувати надання конкретними топологіями. Однак, якщо це все ще потрібно, можна вказати allowedTopologies.

У цьому прикладі показано, як обмежити топологію наданих томів конкретними зонами; це слід використовувати як заміну параметрам zone та zones для підтримуваних втулків.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner:  example.com/example
parameters:
  type: pd-standard
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
  - key: topology.kubernetes.io/zone
    values:
    - us-central-1a
    - us-central-1b

Параметри

StorageClasses мають параметри, які описують томи, що належать до класу сховища. Залежно від provisioner можуть прийматися різні параметри. Якщо параметр пропущено, використовується певне стандартне значення.

Для StorageClass можна визначити не більше 512 параметрів. Загальна довжина обʼєкта параметрів, включно з ключами та значеннями, не може перевищувати 256 KiB.

AWS EBS

Kubernetes 1.37 не містить типу тому awsElasticBlockStore.

Вбудований драйвер сховища AWSElasticBlockStore визнано застарілим у випуску Kubernetes v1.19, а потім повністю вилучено у випуску v1.27.

Проєкт Kubernetes пропонує натомість використовувати зовнішній драйвер сховища AWS EBS.

Ось приклад StorageClass для драйвера CSI AWS EBS:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
  csi.storage.k8s.io/fstype: xfs
  type: io1
  iopsPerGB: "50"
  encrypted: "true"
  tagSpecification_1: "key1=value1"
  tagSpecification_2: "key2=value2"
allowedTopologies:
- matchLabelExpressions:
  - key: topology.ebs.csi.aws.com/zone
    values:
    - us-east-2c

tagSpecification: Теґи з цим префіксом застосовуються до динамічно наданих томів EBS.

AWS EFS

Щоб налаштувати сховище AWS EFS, можна використовувати зовнішній драйвер AWS_EFS_CSI_DRIVER.

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: efs-sc
provisioner: efs.csi.aws.com
parameters:
  provisioningMode: efs-ap
  fileSystemId: fs-92107410
  directoryPerms: "700"
  • provisioningMode: Тип тому, який надає Amazon EFS. Наразі підтримується лише надання на основі точки доступу (efs-ap).
  • fileSystemId: Файлова система, під якою створюється точка доступу.
  • directoryPerms: Дозволи кореневої теки, створеної точкою доступу.

Докладніше дивіться в документації AWS_EFS_CSI_Driver Dynamic Provisioning.

NFS

Щоб налаштувати сховище NFS, можна використовувати вбудований драйвер або драйвер CSI для NFS у Kubernetes (рекомендовано).

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: example-nfs
provisioner: example.com/external-nfs
parameters:
  server: nfs-server.example.com
  path: /share
  readOnly: "false"
  • server: Server — це імʼя хоста або IP-адреса сервера NFS.
  • path: Шлях, який експортується сервером NFS.
  • readOnly: Прапорець, який вказує, чи буде сховище змонтовано лише для читання (стандартно false).

Kubernetes не містить внутрішнього provisioner для NFS. Щоб створити StorageClass для NFS, потрібно використовувати зовнішній provisioner. Ось кілька прикладів:

vSphere

Існує два типи provisioners для класів сховища vSphere:

Вбудовані provisioners застаріли. Докладніше про provisioner CSI дивіться в Kubernetes vSphere CSI Driver та міграції vSphereVolume на CSI.

Provisioner CSI

Provisioner StorageClass для vSphere CSI працює з кластерами Tanzu Kubernetes. Приклад дивіться в репозиторії vSphere CSI.

Provisioner vCP

У наведених нижче прикладах використовується provisioner StorageClass VMware Cloud Provider (vCP).

  1. Створіть StorageClass із форматом диска, вказаним користувачем.

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: fast
    provisioner: kubernetes.io/vsphere-volume
    parameters:
      diskformat: zeroedthick
    

    diskformat: thin, zeroedthick та eagerzeroedthick. Стандартно: "thin".

  2. Створіть StorageClass із форматом диска на вказаному користувачем сховищі даних.

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: fast
    provisioner: kubernetes.io/vsphere-volume
    parameters:
      diskformat: zeroedthick
      datastore: VSANDatastore
    

    datastore: Користувач також може вказати datastore у StorageClass. Том буде створено в datastore, вказаному в StorageClass, у цьому випадку — VSANDatastore. Це поле є необовʼязковим. Якщо datastore не вказано, том буде створено в datastore, вказаному у файлі конфігурації vSphere, який використовується для ініціалізації хмарного провайдера vSphere.

  3. Керування політикою сховища в Kubernetes

    • Використання наявної політики SPBM vCenter

      Однією з найважливіших можливостей vSphere для керування сховищем є керування на основі політик. Керування сховищем на основі політик (Storage Policy Based Management, SPBM) — це фреймворк політик сховища, який надає єдину уніфіковану панель управління для широкого спектра сервісів даних і рішень зберігання. SPBM дозволяє адміністраторам vSphere долати початкові проблеми надання сховища, такі як планування місткості, диференційовані рівні обслуговування та керування запасом місткості.

      Політики SPBM можна вказати в StorageClass за допомогою параметра storagePolicyName.

    • Підтримка політики Virtual SAN всередині Kubernetes

      Адміністратори Vsphere Infrastructure (VI) матимуть змогу вказувати власні можливості сховища Virtual SAN під час динамічного надання томів. Тепер ви можете визначати вимоги до сховища, такі як продуктивність і доступність, у вигляді можливостей сховища під час динамічного надання томів. Вимоги до можливостей сховища перетворюються на політику Virtual SAN, яка потім передається на рівень Virtual SAN під час створення постійного тому (віртуального диска). Віртуальний диск розподіляється по сховищу даних Virtual SAN відповідно до вимог.

      Докладніше про використання політик сховища для керування постійними томами дивіться в Storage Policy Based Management for dynamic provisioning of volumes.

Ceph RBD (застаріло)

Примітка:

СТАН ФУНКЦІОНАЛУ: Deprecated since Kubernetes v1.28

Цей внутрішній provisioner Ceph RBD застарів. Використовуйте CephFS RBD CSI driver.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/rbd # This provisioner is deprecated
parameters:
  monitors: 198.19.254.105:6789
  adminId: kube
  adminSecretName: ceph-secret
  adminSecretNamespace: kube-system
  pool: kube
  userId: kube
  userSecretName: ceph-secret-user
  userSecretNamespace: default
  fsType: ext4
  imageFormat: "2"
  imageFeatures: "layering"
  • monitors: Монітори Ceph, розділені комою. Цей параметр є обовʼязковим.

  • adminId: Ідентифікатор клієнта Ceph, який може створювати образи в пулі. Стандартно "admin".

  • adminSecretName: Назва Secret для adminId. Цей параметр є обовʼязковим. Наданий Secret повинен мати тип "kubernetes.io/rbd".

  • adminSecretNamespace: Простір імен для adminSecretName. Стандартно "default".

  • pool: Пул Ceph RBD. Стандартно "rbd".

  • userId: Ідентифікатор клієнта Ceph, який використовується для зіставлення образу RBD. Стандартно такий самий, як adminId.

  • userSecretName: Назва Ceph Secret для userId для зіставлення образу RBD. Він має існувати в тому самому просторі імен, що й PVC. Цей параметр є обовʼязковим. Наданий Secret повинен мати тип "kubernetes.io/rbd", наприклад, створений таким чином:

    kubectl create secret generic ceph-secret --type="kubernetes.io/rbd" \
      --from-literal=key='QVFEQ1pMdFhPUnQrSmhBQUFYaERWNHJsZ3BsMmNjcDR6RFZST0E9PQ==' \
      --namespace=kube-system
    
  • userSecretNamespace: Простір імен для userSecretName.

  • fsType: fsType, який підтримує Kubernetes. Стандартно: "ext4".

  • imageFormat: Формат образу Ceph RBD, "1" або "2". Стандартно "2".

  • imageFeatures: Цей параметр є необовʼязковим, і його слід використовувати лише тоді, коли ви встановили imageFormat у "2". Наразі підтримується лише можливість layering. Стандартно "", і жодну можливість не ввімкнено.

Azure Disk

Kubernetes 1.37 не містить типу тому azureDisk.

Вбудований драйвер сховища azureDisk визнано застарілим у випуску Kubernetes v1.19, а потім повністю вилучено у випуску v1.27.

Проєкт Kubernetes пропонує натомість використовувати сторонній драйвер сховища Azure Disk.

Azure File (застаріло)

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: azurefile
provisioner: kubernetes.io/azure-file
parameters:
  skuName: Standard_LRS
  location: eastus
  storageAccount: azure_storage_account_name # example value
  • skuName: Рівень SKU облікового запису Azure Storage. Стандартно порожній.
  • location: Розташування облікового запису Azure Storage. Стандартно порожнє.
  • storageAccount: Назва облікового запису Azure Storage. Стандартно порожня. Якщо обліковий запис сховища не вказано, серед усіх облікових записів сховища, повʼязаних із групою ресурсів, шукається той, що відповідає skuName та location. Якщо обліковий запис сховища вказано, він має бути в тій самій групі ресурсів, що й кластер, а skuName та location ігноруються.
  • secretNamespace: Простір імен Secret, що містить назву та ключ облікового запису Azure Storage. Стандартно той самий, що й у Podʼа.
  • secretName: Назва Secret, що містить назву та ключ облікового запису Azure Storage. Стандартно azure-storage-account-<accountName>-secret.
  • readOnly: Прапорець, який вказує, чи буде сховище змонтовано лише для читання. Стандартно false, що означає монтування для читання й запису. Це налаштування також впливає на налаштування ReadOnly у VolumeMounts.

Під час надання сховища для облікових даних монтування створюється Secret із назвою secretName. Якщо в кластері ввімкнено і RBAC, і ролі контролерів, додайте дозвіл create на ресурс secret для clusterrole system:controller:persistent-volume-binder.

У контексті багатоорендності наполегливо рекомендується явно встановлювати значення secretNamespace, інакше облікові дані облікового запису сховища можуть прочитати інші користувачі.

Portworx volume (застаріло)

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: portworx-io-priority-high
provisioner: kubernetes.io/portworx-volume # This provisioner is deprecated
parameters:
  repl: "1"
  snap_interval: "70"
  priority_io: "high"
  • fs: файлова система для створення: none/xfs/ext4 (стандартно: ext4).
  • block_size: розмір блоку в кілобайтах (стандартно: 32).
  • repl: кількість синхронних реплік у формі коефіцієнта реплікації 1..3 (стандартно: 1). Тут очікується рядок, тобто "1", а не 1.
  • priority_io: визначає, чи буде том створено зі сховища вищої продуктивності чи нижчого пріоритету: high/medium/low (стандартно: low).
  • snap_interval: інтервал у хвилинах для запуску знімків. Знімки є інкрементними на основі різниці з попереднім знімком, 0 вимикає знімки (стандартно: 0). Тут очікується рядок, тобто "70", а не 70.
  • aggregation_level: вказує кількість частин, на які буде розподілено том, 0 означає неагрегований том (стандартно: 0). Тут очікується рядок, тобто "0", а не 0.
  • ephemeral: вказує, чи слід очищати том після відмонтування, чи він має бути постійним. Для випадку використання emptyDir це значення можна встановити в true, а для випадку persistent volumes, наприклад, для баз даних на кшталт Cassandra, слід установити false: true/false (стандартно false). Тут очікується рядок, тобто "true", а не true.

Локальне сховище

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner # indicates that this StorageClass does not support automatic provisioning
volumeBindingMode: WaitForFirstConsumer

Локальні томи не підтримують динамічне надання в Kubernetes 1.37; однак StorageClass однаково слід створити, щоб відкласти привʼязку тому до фактичного планування Podʼа на відповідний вузол. Це задається режимом привʼязки томів WaitForFirstConsumer.

Відкладення привʼязки тому дозволяє планувальнику враховувати всі обмеження планування Podʼа під час вибору відповідного PersistentVolume для PersistentVolumeClaim.

7 - Динамічне надання томів

Динамічне надання томів дозволяє створювати томи сховища на вимогу. Без динамічного надання адміністратори кластера змушені вручну звертатися до свого хмарного провайдера або постачальника сховища, щоб створити нові томи сховища, а потім створювати обʼєкти PersistentVolume, які представляють їх у Kubernetes. Можливість динамічного надання усуває потребу адміністраторів кластера заздалегідь надавати сховище. Натомість сховище надається автоматично, коли користувачі створюють обʼєкти PersistentVolumeClaim.

Загальні відомості

Реалізація динамічного надання томів базується на обʼєкті API StorageClass із групи API storage.k8s.io. Адміністратор кластера може визначити стільки обʼєктів StorageClass, скільки потрібно, і кожен із них вказує втулок томів (також відомий як provisioner), який надає том, і набір параметрів, які слід передати цьому provisioner під час надання. Адміністратор кластера може визначити та зробити доступними кілька різновидів сховища (з однієї або різних систем зберігання) у межах кластера, кожен із власним набором параметрів. Така архітектура також гарантує, що кінцевим користувачам не потрібно перейматися складністю та нюансами надання сховища, але вони все одно можуть вибирати з кількох варіантів сховища.

Докладніше дивіться в концепції Класи сховищ.

Увімкнення динамічного надання

Щоб увімкнути динамічне надання, адміністратор кластера має заздалегідь створити для користувачів один або кілька обʼєктів StorageClass. Обʼєкти StorageClass визначають, який provisioner слід використовувати та які параметри потрібно передати цьому provisioner під час виклику динамічного надання. Назва обʼєкта StorageClass має бути дійсним іменем DNS-піддомену.

Наведений нижче маніфест створює клас сховища "slow", який надає стандартні постійні диски, подібні до звичайних дисків.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard

Наведений нижче маніфест створює клас сховища "fast", який надає постійні диски, подібні до SSD.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd

Використання динамічного надання

Користувачі запитують динамічно надане сховище, вказуючи клас сховища у своєму PersistentVolumeClaim. До Kubernetes v1.6 це робилося за допомогою анотації volume.beta.kubernetes.io/storage-class. Однак ця анотація застаріла з версії v1.9. Тепер користувачі можуть і повинні використовувати натомість поле storageClassName обʼєкта PersistentVolumeClaim. Значення цього поля має збігатися з назвою StorageClass, налаштованого адміністратором (дивіться Увімкнення динамічного надання).

Наприклад, щоб вибрати клас сховища "fast", користувач створює такий PersistentVolumeClaim:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim1
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast
  resources:
    requests:
      storage: 30Gi

Цей PersistentVolumeClaim призводить до автоматичного надання постійного диска, подібного до SSD. Коли PersistentVolumeClaim видаляють, том знищується.

Стандартна поведінка

Динамічне надання можна ввімкнути в кластері так, щоб усі PersistentVolumeClaims надавалися динамічно, якщо клас сховища не вказано. Адміністратор кластера може ввімкнути таку поведінку таким чином:

Адміністратор може позначити певний StorageClass як стандартний, додавши до нього анотацію storageclass.kubernetes.io/is-default-class. Коли в кластері є стандартний StorageClass і користувач створює PersistentVolumeClaim без вказаного storageClassName, контролер допуску DefaultStorageClass автоматично додає поле storageClassName, що вказує на стандартний клас сховища.

Зверніть увагу, що якщо ви встановите анотацію storageclass.kubernetes.io/is-default-class у true для кількох StorageClass у своєму кластері, а потім створите PersistentVolumeClaim без встановленого storageClassName, Kubernetes використає найновіший стандартний StorageClass.

Урахування топології

У кластерах із кількома зонами Podʼи можуть бути розподілені між зонами регіону. Однозонні бекенди сховища слід надавати в тих зонах, де заплановано Podʼи. Цього можна досягти, встановивши режим привʼязки тому.

8 - Знімки томів

У Kubernetes VolumeSnapshot представляє знімок тому в системі зберігання. У цьому документі передбачається, що ви вже знайомі з постійними томами Kubernetes.

Вступ

Подібно до того, як ресурси API PersistentVolume та PersistentVolumeClaim використовуються для надання томів користувачам і адміністраторам, ресурси API VolumeSnapshotContent та VolumeSnapshot призначені для створення знімків томів для користувачів і адміністраторів.

VolumeSnapshotContent — це знімок, зроблений із тому в кластері, наданого адміністратором. Це ресурс у кластері, так само як PersistentVolume є ресурсом кластера.

VolumeSnapshot — це запит на знімок тому від користувача. Він схожий на PersistentVolumeClaim.

VolumeSnapshotClass дозволяє вказати різні атрибути, що належать до VolumeSnapshot. Ці атрибути можуть відрізнятися для знімків, зроблених з одного й того самого тому в системі зберігання, і тому їх не можна виразити за допомогою того самого StorageClass у PersistentVolumeClaim.

Знімки томів надають користувачам Kubernetes стандартизований спосіб копіювання вмісту тому на певний момент часу без створення цілком нового тому. Ця функціональність дозволяє, наприклад, адміністраторам баз даних створювати резервні копії баз даних перед внесенням змін або видаленням.

Під час використання цієї можливості користувачі повинні знати таке:

  • API-обʼєкти VolumeSnapshot, VolumeSnapshotContent та VolumeSnapshotClass є CRDs, а не частиною основного API.
  • Підтримка VolumeSnapshot доступна лише для драйверів CSI.
  • У межах процесу розгортання VolumeSnapshot команда Kubernetes надає контролер знімків, який розгортається в панелі управління, і допоміжний sidecar-контейнер csi-snapshotter, який розгортається разом із драйвером CSI. Контролер знімків стежить за обʼєктами VolumeSnapshot та VolumeSnapshotContent і відповідає за створення та видалення обʼєкта VolumeSnapshotContent. Sidecar-контейнер csi-snapshotter стежить за обʼєктами VolumeSnapshotContent і запускає операції CreateSnapshot та DeleteSnapshot для точки доступу CSI.
  • Також існує сервер валідаційного вебхука, який забезпечує посилену валідацію обʼєктів знімків. Його мають встановлювати дистрибутиви Kubernetes разом із контролером знімків і CRDs, а не драйвери CSI. Його слід встановити в усіх кластерах Kubernetes, де ввімкнено можливість знімків.
  • Драйвери CSI можуть реалізовувати функціональність знімків томів, а можуть і не реалізовувати. Драйвери CSI, які надають підтримку знімків томів, імовірно, використовуватимуть csi-snapshotter. Докладніше дивіться в документації драйверів CSI.
  • За встановлення CRDs та контролера знімків відповідає дистрибутив Kubernetes.

Для складніших випадків використання, таких як створення групових знімків кількох томів, дивіться зовнішню документацію CSI Volume Group Snapshot.

У кластерах, де знімок можна використовувати лише з частини кластера (наприклад, знімок тому в одній зоні багатозонового кластера без спільного сховища), топологію знімка можна записати та враховувати під час відновлення з нього. Докладніше дивіться у зовнішній документації CSI.

Життєвий цикл знімка тому та вмісту знімка тому

VolumeSnapshotContents — це ресурси в кластері. VolumeSnapshots — це запити на ці ресурси. Взаємодія між VolumeSnapshotContents та VolumeSnapshots відбувається за таким життєвим циклом:

Надання знімків томів

Знімки можна надавати двома способами: попередньо або динамічно.

Попереднє надання

Адміністратор кластера створює певну кількість VolumeSnapshotContents. Вони містять відомості про реальний знімок тому в системі зберігання, доступний для використання користувачами кластера. Вони існують в API Kubernetes і доступні для використання.

Динамічне надання

Замість використання наявного знімка ви можете запросити динамічне створення знімка з PersistentVolumeClaim. VolumeSnapshotClass вказує специфічні для постачальника сховища параметри, які слід використовувати під час створення знімка.

Привʼязка

Контролер знімків відповідає за привʼязку обʼєкта VolumeSnapshot до відповідного обʼєкта VolumeSnapshotContent як за попереднього, так і за динамічного надання. Привʼязка є зіставленням один до одного.

У випадку попереднього надання VolumeSnapshot залишається непривʼязаним, доки не буде створено запитаний обʼєкт VolumeSnapshotContent.

Захист PersistentVolumeClaim як джерела знімка

Мета цього захисту — гарантувати, що обʼєкти API PersistentVolumeClaim, які використовуються, не вилучаються із системи, поки з них робиться знімок (оскільки це може призвести до втрати даних).

Поки з PersistentVolumeClaim робиться знімок, цей PersistentVolumeClaim вважається таким, що використовується. Якщо ви видалите обʼєкт API PersistentVolumeClaim, який активно використовується як джерело знімка, обʼєкт PersistentVolumeClaim вилучається не одразу. Натомість його вилучення відкладається, доки знімок не стане readyToUse або не буде перерваний.

Видалення

Видалення запускається видаленням обʼєкта VolumeSnapshot, і далі діє DeletionPolicy. Якщо DeletionPolicy має значення Delete, базовий знімок сховища буде видалено разом з обʼєктом VolumeSnapshotContent. Якщо DeletionPolicy має значення Retain, то і базовий знімок, і VolumeSnapshotContent залишаються.

VolumeSnapshots

Кожен VolumeSnapshot містить spec і status.

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: new-snapshot-test
spec:
  volumeSnapshotClassName: csi-hostpath-snapclass
  source:
    persistentVolumeClaimName: pvc-test

persistentVolumeClaimName — це назва обʼєкта PersistentVolumeClaim, який є джерелом даних для знімка. Це поле є обовʼязковим для динамічного створення знімка.

Знімок тому може запитати певний клас, вказавши назву VolumeSnapshotClass в атрибуті volumeSnapshotClassName. Якщо нічого не вказано, використовується стандартний клас, якщо він доступний.

Для попередньо наданих знімків потрібно вказати volumeSnapshotContentName як джерело знімка, як показано в наведеному нижче прикладі. Поле джерела volumeSnapshotContentName є обовʼязковим для попередньо наданих знімків.

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: test-snapshot
spec:
  source:
    volumeSnapshotContentName: test-content

Вміст знімків томів

Кожен VolumeSnapshotContent містить spec і status. Під час динамічного надання загальний контролер знімків створює обʼєкти VolumeSnapshotContent. Ось приклад:

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotContent
metadata:
  name: snapcontent-72d9a349-aacd-42d2-a240-d775650d2455
spec:
  deletionPolicy: Delete
  driver: hostpath.csi.k8s.io
  source:
    volumeHandle: ee0cfb94-f8d4-11e9-b2d8-0242ac110002
  sourceVolumeMode: Filesystem
  volumeSnapshotClassName: csi-hostpath-snapclass
  volumeSnapshotRef:
    name: new-snapshot-test
    namespace: default
    uid: 72d9a349-aacd-42d2-a240-d775650d2455

volumeHandle — це унікальний ідентифікатор тому, створеного в бекенді сховища й повернутого драйвером CSI під час створення тому. Це поле є обовʼязковим для динамічного надання знімка. Воно вказує том-джерело знімка.

Для попередньо наданих знімків ви (як адміністратор кластера) відповідаєте за створення обʼєкта VolumeSnapshotContent, як показано нижче.

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotContent
metadata:
  name: new-snapshot-content-test
spec:
  deletionPolicy: Delete
  driver: hostpath.csi.k8s.io
  source:
    snapshotHandle: 7bdd0de3-aaeb-11e8-9aae-0242ac110002
  sourceVolumeMode: Filesystem
  volumeSnapshotRef:
    name: new-snapshot-test
    namespace: default

snapshotHandle — це унікальний ідентифікатор знімка тому, створеного в бекенді сховища. Це поле є обовʼязковим для попередньо наданих знімків. Воно вказує ідентифікатор знімка CSI в системі зберігання, який представляє цей VolumeSnapshotContent.

sourceVolumeMode — це режим тому, з якого зроблено знімок. Значенням поля sourceVolumeMode може бути Filesystem або Block. Якщо режим вихідного тому не вказано, Kubernetes вважає, що режим вихідного тому невідомий.

volumeSnapshotRef — це посилання на відповідний VolumeSnapshot. Зверніть увагу, що коли VolumeSnapshotContent створюється як попередньо наданий знімок, VolumeSnapshot, на який посилається volumeSnapshotRef, може ще не існувати.

Зміна режиму тому знімка

Якщо API VolumeSnapshots, встановлений у вашому кластері, підтримує поле sourceVolumeMode, то API може не давати неавторизованим користувачам змінювати режим тому.

Щоб перевірити, чи підтримує ваш кластер цю можливість, виконайте таку команду:

$ kubectl get crd volumesnapshotcontent -o yaml

Якщо ви хочете дозволити користувачам створювати PersistentVolumeClaim з наявного VolumeSnapshot, але з іншим режимом тому, ніж у джерела, слід додати анотацію snapshot.storage.kubernetes.io/allow-volume-mode-change: "true" до VolumeSnapshotContent, який відповідає VolumeSnapshot.

Для попередньо наданих знімків spec.sourceVolumeMode має заповнити адміністратор кластера.

Приклад ресурсу VolumeSnapshotContent із увімкненою цією можливістю виглядатиме так:

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotContent
metadata:
  name: new-snapshot-content-test
  annotations:
    - snapshot.storage.kubernetes.io/allow-volume-mode-change: "true"
spec:
  deletionPolicy: Delete
  driver: hostpath.csi.k8s.io
  source:
    snapshotHandle: 7bdd0de3-aaeb-11e8-9aae-0242ac110002
  sourceVolumeMode: Filesystem
  volumeSnapshotRef:
    name: new-snapshot-test
    namespace: default

Топологія знімків томів

У деяких кластерах знімок можна використовувати лише з частини кластера. Наприклад, у багатозоновому кластері, де сховище не є спільним між зонами, знімок тому в одній зоні можна використовувати лише з цієї зони: томи, відновлені зі знімка, можна створювати лише там, де розташовані дані знімка.

Коли ввімкнено можливість VolumeSnapshotTopology, ця топологія записується та враховується:

  • Адміністратор кластера може встановити allowedTopologies у VolumeSnapshotClass, щоб вказати, звідки мають бути доступні динамічно створені знімки.
  • Драйвер CSI повідомляє, звідки можна використовувати знімок, а sidecar-контейнер csi-snapshotter записує це в VolumeSnapshotContent.spec.nodeAffinity.
  • Коли ви надаєте том зі знімка, ця топологія використовується для розміщення відновленого тому там, де доступні дані знімка.

Це альфа-можливість sidecar-контейнерів CSI, яка вмикається функціональною можливістю VolumeSnapshotTopology у csi-snapshotter та external-provisioner. Докладніше дивіться у зовнішній документації CSI.

Надання томів зі знімків

Ви можете надати новий том, попередньо заповнений даними зі знімка, за допомогою поля dataSource в обʼєкті PersistentVolumeClaim.

Докладніше дивіться в Знімок тому та відновлення тому зі знімка.

9 - Класи знімків томів

У цьому документі описано концепцію VolumeSnapshotClass у Kubernetes. Рекомендується ознайомитися зі знімками томів та класами сховищ.

Вступ

Так само як StorageClass надає адміністраторам можливість описувати «класи» сховища, які вони пропонують під час надання тому, VolumeSnapshotClass надає можливість описувати «класи» сховища під час надання знімка тому.

Ресурс VolumeSnapshotClass

Кожен VolumeSnapshotClass містить поля driver, deletionPolicy та parameters, які використовуються, коли VolumeSnapshot, що належить до цього класу, потрібно надати динамічно.

Назва обʼєкта VolumeSnapshotClass є важливою: саме за нею користувачі можуть запитати певний клас. Адміністратори встановлюють назву та інші параметри класу під час першого створення обʼєктів VolumeSnapshotClass, і ці обʼєкти не можна оновлювати після створення.

Примітка:

За встановлення CRD відповідає дистрибутив Kubernetes. Якщо потрібних CRD немає, створення VolumeSnapshotClass завершиться невдачею.
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: csi-hostpath-snapclass
driver: hostpath.csi.k8s.io
deletionPolicy: Delete
parameters:

Адміністратори можуть вказати стандартний VolumeSnapshotClass для VolumeSnapshots, які не запитують привʼязки до певного класу, додавши анотацію snapshot.storage.kubernetes.io/is-default-class: "true":

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: csi-hostpath-snapclass
  annotations:
    snapshot.storage.kubernetes.io/is-default-class: "true"
driver: hostpath.csi.k8s.io
deletionPolicy: Delete
parameters:

Якщо існує кілька драйверів CSI, для кожного з них можна вказати стандартний VolumeSnapshotClass.

Залежності VolumeSnapshotClass

Коли ви створюєте VolumeSnapshot без зазначення VolumeSnapshotClass, Kubernetes автоматично вибирає стандартний VolumeSnapshotClass, драйвер CSI якого збігається з драйвером CSI StorageClass цього PVC.

Така поведінка дозволяє кільком стандартним обʼєктам VolumeSnapshotClass співіснувати в кластері, якщо кожен із них повʼязаний з унікальним драйвером CSI.

Завжди переконуйтеся, що для кожного драйвера CSI існує лише один стандартний VolumeSnapshotClass. Якщо з одним драйвером CSI створено кілька стандартних обʼєктів VolumeSnapshotClass, створення VolumeSnapshot завершиться невдачею, оскільки Kubernetes не зможе визначити, який із них використати.

Driver

Класи знімків томів мають драйвер, який визначає, який втулок томів CSI використовується для надання VolumeSnapshots. Це поле є обовʼязковим.

DeletionPolicy

Класи знімків томів мають deletionPolicy. Вона дозволяє налаштувати, що станеться з VolumeSnapshotContent, коли обʼєкт VolumeSnapshot, до якого він привʼязаний, буде видалено. Значення deletionPolicy класу знімків томів може бути Retain або Delete. Це поле є обовʼязковим.

Якщо deletionPolicy має значення Delete, базовий знімок сховища буде видалено разом з обʼєктом VolumeSnapshotContent. Якщо deletionPolicy має значення Retain, то і базовий знімок, і VolumeSnapshotContent залишаються.

Параметри

Класи знімків томів мають параметри, які описують знімки томів, що належать до цього класу. Залежно від driver можуть прийматися різні параметри.

10 - Клонування томів CSI

У цьому документі описано концепцію клонування наявних томів CSI у Kubernetes. Рекомендується ознайомитися з томами.

Вступ

Можливість клонування томів CSI додає підтримку вказання наявних PVC у полі dataSource, щоб позначити, що користувач хоче клонувати том.

Клон — це дублікат наявного тому Kubernetes, який можна використовувати так само, як будь-який стандартний том. Єдина відмінність полягає в тому, що під час надання, замість створення «нового» порожнього тому, бекенд-пристрій створює точний дублікат вказаного тому.

З погляду API Kubernetes реалізація клонування додає можливість вказати наявний PVC як dataSource під час створення нового PVC. Вихідний PVC має бути привʼязаним і доступним (не використовуватися).

Під час використання цієї можливості користувачі повинні знати таке:

  • Підтримка клонування (VolumePVCDataSource) доступна лише для драйверів CSI.
  • Підтримка клонування доступна лише для динамічних provisioners.
  • Драйвери CSI можуть реалізовувати функціональність клонування томів, а можуть і не реалізовувати.
  • Ви можете клонувати PVC лише тоді, коли він існує в тому самому просторі імен, що й цільовий PVC (джерело та призначення мають бути в одному просторі імен).
  • Клонування підтримується з іншим Storage Class.
    • Цільовий том може мати той самий або інший клас сховища, ніж джерело.
    • Можна використовувати стандартний клас сховища, пропустивши storageClassName у специфікації.
  • Клонування можна виконати лише між двома томами, які використовують однакове значення VolumeMode (якщо ви запитуєте том у блоковому режимі, джерело ТАКОЖ ПОВИННО бути в блоковому режимі)

Надання

Клони надаються так само, як і будь-який інший PVC, за винятком додавання dataSource, який посилається на наявний PVC у тому самому просторі імен.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: clone-of-pvc-1
    namespace: myns
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: cloning
  resources:
    requests:
      storage: 5Gi
  dataSource:
    kind: PersistentVolumeClaim
    name: pvc-1

Примітка:

Ви повинні вказати значення місткості для spec.resources.requests.storage, і воно має бути таким самим або більшим за місткість вихідного тому.

Результатом є новий PVC із назвою clone-of-pvc-1, який має точно такий самий вміст, як і вказане джерело pvc-1.

Використання

Коли новий PVC стає доступним, клонований PVC використовується так само, як і інші PVC. На цьому етапі також очікується, що новостворений PVC є незалежним обʼєктом. Його можна використовувати, клонувати, створювати його знімки чи видаляти незалежно й без огляду на вихідний PVC з dataSource. Це також означає, що джерело ніяк не повʼязане з новоствореним клоном і його також можна змінити чи видалити, не впливаючи на новостворений клон.

11 - Наповнювачі томів та джерела даних

У цьому документі описано наповнювачі томів (volume populators) та джерела даних (data sources) у Kubernetes. Рекомендується ознайомитися з постійними томами.

Коли ви створюєте PersistentVolumeClaim, том, який Kubernetes надає для нього, зазвичай спочатку порожній. Джерело даних дозволяє натомість запитати, щоб новий том було попередньо заповнено наявними даними. Наповнювачі томів — це контролери, які виконують це заповнення на основі джерела даних, на яке посилається PersistentVolumeClaim.

Kubernetes має вбудовану підтримку джерел даних, які клонують наявний том або відновлюють знімок тому. Власні наповнювачі томів розширюють цей механізм. Джерело даних — це власний ресурс, тобто обʼєкт, тип якого визначено за допомогою CustomResourceDefinition. Контролер-наповнювач стежить за PersistentVolumeClaims, які посилаються на такий ресурс, і заповнює з нього новий том.

Наповнювачі томів та джерела даних

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.24

Kubernetes підтримує власні наповнювачі томів. Щоб використовувати власні наповнювачі томів, ви повинні ввімкнути функціональну можливість AnyVolumeDataSource для kube-apiserver та kube-controller-manager.

Наповнювачі томів використовують поле специфікації PVC з назвою dataSourceRef. На відміну від поля dataSource, яке може містити лише посилання на інший PersistentVolumeClaim або на VolumeSnapshot, поле dataSourceRef може містити посилання на будь-який обʼєкт у тому самому просторі імен, за винятком основних обʼєктів, відмінних від PVC. Для кластерів, у яких увімкнено цю функціональну можливість, слід надавати перевагу dataSourceRef, а не dataSource.

Посилання на джерела даних

Поле dataSourceRef поводиться майже так само, як поле dataSource. Якщо вказано одне з них, а інше ні, API-сервер надасть обом полям однакове значення. Жодне з полів не можна змінити після створення, а спроба вказати різні значення для цих двох полів призведе до помилки валідації. Тому обидва поля завжди матимуть однаковий вміст.

Існують дві відмінності між полями dataSourceRef та dataSource, про які користувачі повинні знати:

  • Поле dataSource ігнорує недійсні значення (ніби поле було порожнім), тоді як dataSourceRef ніколи не ігнорує значення і спричинить помилку, якщо використано недійсне значення. Недійсними значеннями є будь-які основні обʼєкти (обʼєкти без apiGroup), крім PVC.
  • Поле dataSourceRef може містити різні типи обʼєктів, тоді як поле dataSource дозволяє лише PVC та VolumeSnapshots.

Коли ввімкнено можливість CrossNamespaceVolumeDataSource, зʼявляються додаткові відмінності:

  • Поле dataSource дозволяє лише локальні обʼєкти, тоді як поле dataSourceRef дозволяє обʼєкти в будь-яких просторах імен.
  • Коли вказано простір імен, dataSource та dataSourceRef не синхронізуються.

Користувачі завжди повинні використовувати dataSourceRef у кластерах, де ввімкнено цю функціональну можливість, і повертатися до dataSource у кластерах, де її не ввімкнено. За жодних обставин не потрібно переглядати обидва поля. Дубльовані значення з дещо різною семантикою існують лише для зворотної сумісності. Зокрема, суміш старіших і новіших контролерів може взаємодіяти, оскільки поля однакові.

Використання наповнювачів томів

Наповнювачі томів — це контролери, які можуть створювати непорожні томи, вміст яких визначається власним ресурсом. Користувачі створюють заповнений том, посилаючись на власний ресурс за допомогою поля dataSourceRef:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: populated-pvc
spec:
  dataSourceRef:
    name: example-name
    kind: ExampleDataSource
    apiGroup: example.storage.k8s.io
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

Оскільки наповнювачі томів є зовнішніми компонентами, спроби створити PVC, який використовує один із них, можуть завершитися невдачею, якщо встановлено не всі потрібні компоненти. Зовнішні контролери повинні генерувати Events на PVC, щоб надавати зворотний звʼязок про статус створення, зокрема попередження, якщо PVC неможливо створити через відсутність певного компонента.

Ви можете встановити у свій кластер alpha-контролер volume data source validator. Цей контролер генерує попереджувальні Events на PVC, якщо жоден наповнювач не зареєстровано для обробки такого виду джерела даних. Коли для PVC встановлено відповідний наповнювач, саме цей контролер-наповнювач відповідає за створення Events, повʼязаних зі створенням тому та проблемами під час цього процесу.

Джерела даних між просторами імен

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.26

Kubernetes підтримує джерела даних томів між просторами імен. Щоб використовувати їх, ви повинні ввімкнути функціональні можливості AnyVolumeDataSource та CrossNamespaceVolumeDataSource для kube-apiserver та kube-controller-manager. Крім того, ви повинні ввімкнути функціональну можливість CrossNamespaceVolumeDataSource для csi-provisioner.

Увімкнення функціональної можливості CrossNamespaceVolumeDataSource дозволяє вказати простір імен у полі dataSourceRef.

Примітка:

Коли ви вказуєте простір імен для джерела даних тому, Kubernetes перевіряє наявність ReferenceGrant в іншому просторі імен, перш ніж прийняти посилання. ReferenceGrant є частиною API розширення gateway.networking.k8s.io. Докладніше дивіться в розділі ReferenceGrant документації Gateway API. Це означає, що перед використанням цього механізму ви повинні розширити свій кластер Kubernetes принаймні ресурсом ReferenceGrant із Gateway API.

Використання джерела даних тому між просторами імен

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.26

Створіть ReferenceGrant, щоб дозволити власнику простору імен прийняти посилання. Ви визначаєте заповнений том, вказуючи джерело даних тому між просторами імен за допомогою поля dataSourceRef. У вихідному просторі імен уже повинен існувати дійсний ReferenceGrant:

apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-ns1-pvc
  namespace: default
spec:
  from:
  - group: ""
    kind: PersistentVolumeClaim
    namespace: ns1
  to:
  - group: snapshot.storage.k8s.io
    kind: VolumeSnapshot
    name: new-snapshot-demo
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: foo-pvc
  namespace: ns1
spec:
  storageClassName: example
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  dataSourceRef:
    apiGroup: snapshot.storage.k8s.io
    kind: VolumeSnapshot
    name: new-snapshot-demo
    namespace: default
  volumeMode: Filesystem

Що далі

12 - Місткість сховища

Місткість сховища обмежена і може відрізнятися залежно від вузла, на якому працює Pod: мережеве сховище може бути доступним не всім вузлам, а сховище може бути локальним для вузла від самого початку.

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.24

На цій сторінці описано, як Kubernetes відстежує місткість сховища та як планувальник використовує цю інформацію, щоб планувати Podʼи на вузли, які мають доступ до достатньої місткості сховища для томів, яких ще бракує. Без відстеження місткості сховища планувальник може вибрати вузол, який не має достатньо місткості для надання тому, і знадобиться кілька повторних спроб планування.

Перш ніж ви розпочнете

Kubernetes v1.37 містить підтримку API на рівні кластера для відстеження місткості сховища. Щоб скористатися нею, ви також повинні використовувати драйвер CSI, який підтримує відстеження місткості. Зверніться до документації драйверів CSI, які ви використовуєте, щоб дізнатися, чи доступна ця підтримка і, якщо так, як її використовувати. Якщо ви не використовуєте Kubernetes v1.37, перегляньте документацію для своєї версії Kubernetes.

API

Для цієї можливості існує два розширення API:

  • Обʼєкти CSIStorageCapacity: їх створює драйвер CSI у просторі імен, де його встановлено. Кожен обʼєкт містить інформацію про місткість для одного класу сховища і визначає, які вузли мають доступ до цього сховища.
  • Поле CSIDriverSpec.StorageCapacity: якщо встановлено значення true, планувальник Kubernetes враховуватиме місткість сховища для томів, які використовують драйвер CSI.

Планування

Планувальник Kubernetes використовує інформацію про місткість сховища, якщо:

  • Pod використовує том, який ще не створено,
  • цей том використовує StorageClass, який посилається на драйвер CSI та використовує режим привʼязки тому WaitForFirstConsumer, і
  • обʼєкт CSIDriver для цього драйвера має StorageCapacity зі значенням true.

У цьому випадку планувальник розглядає для Podʼа лише ті вузли, яким доступно достатньо сховища. Ця перевірка дуже спрощена і лише порівнює розмір тому з місткістю, вказаною в обʼєктах CSIStorageCapacity з топологією, що включає цей вузол.

Для томів із режимом привʼязки Immediate драйвер сховища вирішує, де створити том, незалежно від Podʼів, які використовуватимуть цей том. Потім планувальник планує Podʼи на вузли, де том доступний після його створення.

Для ефемерних томів CSI планування завжди відбувається без урахування місткості сховища. Це ґрунтується на припущенні, що цей тип тому використовують лише спеціальні драйвери CSI, які є локальними для вузла й не потребують там значних ресурсів.

Перепланування

Коли вузол вибрано для Podʼа з томами WaitForFirstConsumer, це рішення все ще є попереднім. Наступним кроком драйверу сховища CSI надсилається запит створити том із підказкою, що том має бути доступний на вибраному вузлі.

Оскільки Kubernetes міг вибрати вузол на підставі застарілої інформації про місткість, може статися, що том не вдасться створити. Тоді вибір вузла скидається, і планувальник Kubernetes знову намагається знайти вузол для Podʼа.

Обмеження

Відстеження місткості сховища збільшує ймовірність того, що планування спрацює з першої спроби, але не може цього гарантувати, оскільки планувальник має приймати рішення на підставі потенційно застарілої інформації. Зазвичай збої планування обробляє той самий механізм повторних спроб, що й для планування без інформації про місткість сховища.

Одна із ситуацій, коли планування може остаточно зазнати невдачі, — коли Pod використовує кілька томів: один том уже може бути створений у сегменті топології, де потім бракує місткості для іншого тому. Щоб це виправити, потрібне ручне втручання, наприклад, збільшення місткості або видалення вже створеного тому.

Що далі

13 - Обмеження томів на вузлі

На цій сторінці описано максимальну кількість томів, які можна підʼєднати до вузла, для різних хмарних провайдерів.

Хмарні провайдери, такі як Google, Amazon і Microsoft, зазвичай обмежують кількість томів, які можна підʼєднати до вузла. Важливо, щоб Kubernetes дотримувався цих обмежень. Інакше Podʼи, заплановані на вузол, можуть застрягти в очікуванні підʼєднання томів.

Стандартні обмеження Kubernetes

Планувальник Kubernetes має стандартні обмеження на кількість томів, які можна підʼєднати до вузла:

Хмарний сервісМаксимальна кількість томів на вузол
Amazon Elastic Block Store (EBS)39
Google Persistent Disk16
Microsoft Azure Disk Storage16

Обмеження динамічних томів

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.17

Обмеження динамічних томів підтримуються для таких типів томів.

  • Amazon EBS
  • Google Persistent Disk
  • Azure Disk
  • CSI

Для томів, керованих вбудованими втулками томів, Kubernetes автоматично визначає тип вузла і застосовує відповідну максимальну кількість томів для вузла. Наприклад:

  • У Google Compute Engine до вузла можна підʼєднати до 127 томів, залежно від типу вузла.

  • Для дисків Amazon EBS на типах екземплярів M5,C5,R5,T3 та Z1D Kubernetes дозволяє підʼєднувати до вузла лише 25 томів. Для інших типів екземплярів в Amazon Elastic Compute Cloud (EC2) Kubernetes дозволяє підʼєднувати до вузла 39 томів.

  • В Azure до вузла можна підʼєднати до 64 дисків, залежно від типу вузла. Докладніше дивіться Sizes for virtual machines in Azure.

  • Якщо драйвер сховища CSI оголошує максимальну кількість томів для вузла (за допомогою NodeGetInfo), kube-scheduler дотримується цього обмеження. Докладніше дивіться в специфікаціях CSI.

  • Для томів, керованих вбудованими втулками, які було перенесено на драйвер CSI, максимальною кількістю томів буде та, про яку повідомляє драйвер CSI.

Mutable CSI Node Allocatable Count

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.36; (стандартно увімкнено)
More information about this feature

This is a stable feature in Kubernetes, and has been since version 1.36. It was first available in the v1.33 release.

Драйвери CSI можуть динамічно змінювати максимальну кількість томів, які можна підʼєднати до вузла, під час роботи. Це підвищує точність планування та зменшує кількість збоїв планування Podʼів через зміни в доступності ресурсів.

Щоб скористатися цією можливістю, ви повинні ввімкнути функціональну можливість MutableCSINodeAllocatableCount у таких компонентах:

  • kube-apiserver
  • kubelet

Періодичні оновлення

Якщо цю можливість увімкнено, драйвери CSI можуть запитувати періодичні оновлення своїх обмежень томів, встановивши поле nodeAllocatableUpdatePeriodSeconds у специфікації CSIDriver. Наприклад:

apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
  name: hostpath.csi.k8s.io
spec:
  nodeAllocatableUpdatePeriodSeconds: 60

kubelet періодично викликатиме точку доступу NodeGetInfo відповідного драйвера CSI, щоб оновити максимальну кількість томів, які можна підʼєднати, використовуючи інтервал, вказаний у полі nodeAllocatableUpdatePeriodSeconds. Мінімально допустиме значення цього поля — 10 секунд.

Якщо операція підʼєднання тому завершується помилкою ResourceExhausted (код gRPC 8), Kubernetes негайно оновлює кількість доступних для розподілу томів цього вузла. Крім того, kubelet позначає уражені Podʼи як Failed, що дозволяє їхнім контролерам обробити повторне створення. Це запобігає безстроковому застряганню Podʼів у стані ContainerCreating.

Запобігання розміщенню Podʼа без драйвера CSI

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.37; (стандартно увімкнено)

Функціональна можливість VolumeLimitScaling стандартно ввімкнена в Kubernetes v1.37.

Однак запобігання розміщенню Podʼів на вузлах без драйвера CSI вимагає явної згоди через поле spec.preventPodSchedulingIfMissing обʼєкта CSIDriver.

Поле preventPodSchedulingIfMissing стандартно має значення false, і його потрібно встановити в true, якщо ви не хочете, щоб Podʼи планувалися на вузлах без драйвера CSI. Стандартне значення false вибрано з міркувань зворотної сумісності та сумісності з Cluster AutoScaler, який може не враховувати обмеження томів CSI під час автомасштабування (дивіться розділ нижче).

apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
  name: hostpath.csi.k8s.io
spec:
  preventPodSchedulingIfMissing: true

Обмеження підʼєднання томів CSI та cluster autoscaler

Cluster autoscaler може враховувати обмеження томів CSI, коли встановлено --enable-csi-node-aware-scheduling=true. Цей параметр не залежить від функціональної можливості VolumeLimitScaling.

Якщо ви використовуєте cluster autoscaler, встановлюйте spec.preventPodSchedulingIfMissing у true лише тоді, коли cluster autoscaler налаштовано з --enable-csi-node-aware-scheduling=true. Інакше його симуляції планування не включатимуть потрібну інформацію CSINode для нових вузлів, і cluster autoscaler може не масштабуватися вгору для Podʼів в очікуванні, які використовують томи CSI.

14 - Локальне тимчасове сховище

Вузли мають локальне тимчасове сховище, яке підтримується локально підключеними пристроями з можливістю запису або, інколи, оперативною памʼяттю. «Тимчасове» означає, що немає довгострокової гарантії щодо довговічності.

Podʼи використовують тимчасове локальне сховище як робочий простір, для кешування та для логів. kubelet може надавати Podʼам робочий простір, використовуючи локальне тимчасове сховище для монтування томів emptyDir у контейнери.

kubelet також використовує цей тип сховища для зберігання логів контейнерів на рівні вузла, образів контейнерів і шарів запущених контейнерів, доступних для запису.

Увага:

Якщо вузол виходить з ладу, дані в його тимчасовому сховищі можуть бути втрачені. Ваші застосунки не можуть очікувати жодних SLA щодо продуктивності (наприклад, дискових IOPS) від локального тимчасового сховища.

Примітка:

Щоб квота ресурсів працювала для ephemeral-storage, потрібно виконати дві дії:

  • Адміністратор встановлює квоту ресурсів для ephemeral-storage в просторі імен.
  • Користувач повинен вказати обмеження для ресурсу ephemeral-storage у специфікації Podʼа.

Якщо користувач не вказав обмеження ресурсу ephemeral-storage у специфікації Podʼа, квота ресурсів не застосовується до ephemeral-storage.

Kubernetes дозволяє відстежувати, резервувати та обмежувати обсяг тимчасового локального сховища, яке може використовувати Pod.

Конфігурації для локального тимчасового сховища

Kubernetes підтримує такі способи налаштування локального тимчасового сховища на вузлі:

У цій конфігурації ви розміщуєте всі різні типи тимчасових локальних даних (томи emptyDir, шари, доступні для запису, образи контейнерів, логи) в одній файловій системі.

kubelet також записує логи контейнерів на рівні вузла і обробляє їх аналогічно тимчасовому локальному сховищу.

kubelet записує логи у файли всередині налаштованої теки логів (стандартно /var/log) і має базову теку для інших локально збережених даних (стандартно /var/lib/kubelet).

Зазвичай і /var/lib/kubelet, і /var/log розташовані в кореневій файловій системі, і kubelet розроблено з урахуванням такого розташування.

Ваш вузол може мати скільки завгодно інших файлових систем, які не використовуються для Kubernetes.

Ви використовуєте на вузлі одну файлову систему для тимчасових даних запущених Podʼів, таких як логи та томи emptyDir. Цю файлову систему також можна використовувати для інших даних, наприклад, для системних логів, не повʼязаних із Kubernetes; вона може бути навіть кореневою файловою системою.

kubelet також записує логи контейнерів на рівні вузла у першу файлову систему і обробляє їх аналогічно тимчасовому локальному сховищу.

Ви також використовуєте окрему файлову систему на іншому логічному пристрої зберігання. У цій конфігурації середовище виконання контейнерів зберігає і шари образів контейнерів, і шари, доступні для запису, у цій другій файловій системі. Налаштуйте це місце зберігання в середовищі виконання контейнерів, а не в kubelet.

Перша файлова система не містить жодних шарів образів або шарів, доступних для запису.

Ваш вузол може мати скільки завгодно інших файлових систем, які не використовуються для Kubernetes.

У цій конфігурації шари образів контейнерів розташовані в окремій файловій системі, а шари контейнерів, доступні для запису, — у тій самій файловій системі, що й тимчасові дані kubelet, такі як логи та томи emptyDir.

Ця конфігурація вимагає підтримки сигналів виселення containerfs. Докладніше про функціональну можливість і середовища виконання контейнерів, які підтримують цю конфігурацію, дивіться у виселенні внаслідок тиску на вузол.

На сторінці Виселення внаслідок тиску на вузол ці файлові системи, за якими ведеться спостереження, позначаються як nodefs, imagefs та containerfs. Ці назви не завжди означають окремі точки монтування.

kubelet може вимірювати використання локального сховища, якщо ви налаштовуєте вузол за однією з підтримуваних конфігурацій локального тимчасового сховища.

Якщо у вас інша конфігурація, kubelet не застосовує обмеження ресурсів для тимчасового локального сховища.

Примітка:

kubelet відстежує томи emptyDir типу tmpfs як використання памʼяті контейнера, а не як локальне тимчасове сховище.

Примітка:

kubelet може відстежувати тимчасове сховище лише у файлових системах, які він спостерігає через підтримувані схеми розташування. Якщо ви монтуєте додаткові файлові системи за такими шляхами, як /var/lib/kubelet, /var/log або тека сховища середовища виконання контейнерів, поза цими схемами, kubelet може неправильно повідомляти про тимчасове сховище.

Встановлення запитів та обмежень для локального тимчасового сховища

Ви можете вказати ephemeral-storage для керування локальним тимчасовим сховищем. Кожен контейнер Podʼа може вказати одне або обидва з такого:

  • spec.containers[].resources.limits.ephemeral-storage
  • spec.containers[].resources.requests.ephemeral-storage

Обмеження та запити для ephemeral-storage вимірюються в байтах. Ви можете виразити обсяг сховища як просте ціле число або як число з фіксованою комою, використовуючи один із таких суфіксів: E, P, T, G, M, k. Ви також можете використовувати еквіваленти степеня двійки: Ei, Pi, Ti, Gi, Mi, Ki. Наприклад, усі наведені нижче величини мають приблизно однакове значення:

  • 128974848
  • 129e6
  • 129M
  • 123Mi

Зверніть увагу на регістр суфіксів. Якщо ви запитуєте 400m тимчасового сховища, це запит на 0,4 байта. Той, хто це ввів, мабуть, мав на увазі 400 мебібайтів (400Mi) або 400 мегабайтів (400M).

У наведеному нижче прикладі Pod має два контейнери. Кожен контейнер має запит на 2GiB локального тимчасового сховища. Кожен контейнер має обмеження в 4GiB локального тимчасового сховища. Отже, Pod має запит на 4GiB локального тимчасового сховища та обмеження у 8GiB локального тимчасового сховища. 500Mi цього обмеження може використати том emptyDir.

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests:
        ephemeral-storage: "2Gi"
      limits:
        ephemeral-storage: "4Gi"
    volumeMounts:
    - name: ephemeral
      mountPath: "/tmp"
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        ephemeral-storage: "2Gi"
      limits:
        ephemeral-storage: "4Gi"
    volumeMounts:
    - name: ephemeral
      mountPath: "/tmp"
  volumes:
    - name: ephemeral
      emptyDir:
        sizeLimit: 500Mi

Як плануються Podʼи із запитами ephemeral-storage

Коли ви створюєте Pod, планувальник Kubernetes вибирає вузол, на якому працюватиме Pod. Кожен вузол має максимальний обсяг локального тимчасового сховища, який він може надати для Podʼів. Докладнішу інформацію дивіться в розділі Node Allocatable.

Планувальник гарантує, що сума запитів на ресурси запланованих контейнерів буде меншою за місткість вузла.

Керування споживанням тимчасового сховища

Якщо kubelet керує локальним тимчасовим сховищем як ресурсом, то kubelet вимірює використання сховища в:

  • томах emptyDir, за винятком томів tmpfs emptyDir
  • теках, що містять логи на рівні вузла
  • шарах контейнерів, доступних для запису

Якщо Pod використовує більше тимчасового сховища, ніж ви дозволяєте, kubelet встановлює сигнал виселення, який запускає виселення Podʼа.

Для ізоляції на рівні контейнера, якщо використання шару контейнера, доступного для запису, та логів перевищує його обмеження сховища, kubelet позначає Pod для виселення.

Для ізоляції на рівні Podʼа kubelet обчислює загальне обмеження сховища Podʼа, підсумовуючи обмеження контейнерів цього Podʼа. У цьому випадку, якщо сума використання локального тимчасового сховища всіма контейнерами, а також томами emptyDir Podʼа перевищує загальне обмеження сховища Podʼа, kubelet також позначає Pod для виселення.

Увага:

Якщо kubelet не вимірює локальне тимчасове сховище, то Pod, який перевищує своє обмеження локального сховища, не буде виселений за порушення обмежень ресурсів локального сховища.

Однак, якщо місця у файловій системі для шарів контейнерів, доступних для запису, логів на рівні вузла або томів emptyDir стає мало, вузол позначає себе taint про нестачу локального сховища, і цей taint запускає виселення всіх Podʼів, які спеціально не толерують цей taint.

Дивіться підтримувані конфігурації для тимчасового локального сховища.

kubelet підтримує різні способи вимірювання використання сховища Podʼа:

kubelet виконує регулярні заплановані перевірки, які сканують кожен том emptyDir, теку логів контейнера та шар контейнера, доступний для запису.

Сканування вимірює, скільки місця використовується.

Примітка:

У цьому режимі kubelet не відстежує відкриті дескриптори видалених файлів.

Якщо ви (або контейнер) створюєте файл у томі emptyDir, щось потім відкриває цей файл, а ви видаляєте файл, поки він ще відкритий, то inode видаленого файлу залишається, доки ви не закриєте цей файл, але kubelet не вважає це місце використаним.

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.31; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the LocalStorageCapacityIsolationFSQuotaMonitoring feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Квоти проєктів — це можливість на рівні операційної системи для керування використанням сховища у файлових системах. У Kubernetes ви можете ввімкнути квоти проєктів для моніторингу використання сховища. Переконайтеся, що файлова система, на якій розміщено томи emptyDir на вузлі, підтримує квоти проєктів. Наприклад, XFS та ext4fs пропонують квоти проєктів.

Примітка:

Квоти проєктів дозволяють моніторити використання сховища; вони не застосовують обмеження.

Kubernetes використовує ідентифікатори проєктів, починаючи з 1048576. Використовувані ідентифікатори зареєстровані в /etc/projects та /etc/projid. Якщо ідентифікатори проєктів у цьому діапазоні використовуються в системі для інших цілей, їх необхідно зареєструвати в /etc/projects та /etc/projid, щоб Kubernetes не використовував їх.

Квоти є швидшими та точнішими, ніж сканування тек. Коли тека призначається проєкту, всі файли, створені в цій теці, створюються в цьому проєкті, і ядро має лише відстежувати, скільки блоків використовується файлами в цьому проєкті. Якщо файл створено та видалено, але він має відкритий дескриптор файлу, він продовжує споживати простір. Відстеження квот точно фіксує цей простір, тоді як сканування тек пропускає простір, який використовують видалені файли.

Щоб використовувати квоти для відстеження використання ресурсів Podʼом, Pod повинен бути в просторі імен користувача. У просторах імен користувачів ядро обмежує зміни projectID у файловій системі, забезпечуючи надійність метрик сховища, обчислених за допомогою квот.

Якщо ви хочете використовувати квоти проєктів, вам слід:

  • Увімкнути функціональну можливість LocalStorageCapacityIsolationFSQuotaMonitoring=true за допомогою поля featureGates у конфігурації kubelet.

  • Переконатися, що функціональну можливість UserNamespacesSupport увімкнено, а ядро, реалізація CRI та середовище виконання OCI підтримують простори імен користувачів.

  • Переконатися, що в кореневій файловій системі (або необовʼязковій файловій системі середовища виконання) увімкнено квоти проєктів. Усі файлові системи XFS підтримують квоти проєктів. Для файлових систем ext4 потрібно ввімкнути можливість відстеження квот проєктів, поки файлова система не змонтована.

    # For ext4, with /dev/block-device not mounted
    sudo tune2fs -O project -Q prjquota /dev/block-device
    
  • Переконатися, що коренева файлова система (або необовʼязкова файлова система середовища виконання) змонтована з увімкненими квотами проєктів. Для XFS і ext4fs параметр монтування називається prjquota.

Якщо ви не хочете використовувати квоти проєктів, вам слід:

Що далі

15 - Моніторинг справності томів

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.21; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the CSIVolumeHealth feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

Моніторинг справності томів CSI дозволяє драйверу CSI повідомляти Kubernetes про проблеми зі справністю тому або бекенду його сховища безпосередньо. Драйвер звітує через RPC CSI, а Kubernetes показує ці звіти у трьох полях статусу: PersistentVolumeClaim .status.healthStatus, Pod .status.volumeHealth та CSINode .status.storageHealth. Автоматизація може стежити за цими стійкими полями статусу, а не відтворювати справність томів з ефемерних Events чи зі специфічних для постачальника dashboards.

Примітка:

Функціональна можливість CSIVolumeHealth існує з Kubernetes v1.21, але механізм, описаний на цій сторінці, є переробкою, яка замінює початкову альфа-реалізацію. Що змінилося, дивіться в розділі Обмеження.

Як це працює

Специфікація CSI визначає чотири RPC для звітування про справність:

  • На втулку контролера CSI: ControllerListVolumeHealth та ControllerGetVolumeHealth, для справності кожного тому, яку спостерігає контролер.
  • На втулку вузла CSI: NodeGetVolumeHealth, для справності кожного тому, яку спостерігає вузол, та NodeGetStorageHealth, для справності бекенду сховища, як її видно з цього вузла.

Драйверу потрібно реалізувати лише ті RPC, які він хоче підтримувати, і оголосити їхню підтримку через можливості втулка CSI. Драйвер, який не реалізує жодного з цих RPC, ніколи не опитується, і звітування для нього залишається неактивним. Драйвер, який оголошує можливість контролера LIST_VOLUME_HEALTH, також повинен оголосити GET_VOLUME_HEALTH; цю вимогу забезпечує sidecar-контейнер csi-external-health-monitor-controller.

Кожен звіт про справність містить status із невеликого набору значень, придатних для машинного аналізу, разом із визначеним драйвером reason та необовʼязковим зрозумілим людині message:

  • Значення статусу на рівні тому (використовуються для PersistentVolumeClaim.status.healthStatus та Pod.status.volumeHealth): Inaccessible, DataLoss, Degraded.
  • Значення статусу бекенду сховища (використовуються для CSINode.status.storageHealth): StorageUnreachable, StorageDegraded.

Звіти зі сторони вузла та зі сторони контролера незалежні: том може бути Inaccessible з одного вузла, який втратив шлях до даних бекенду, тоді як втулок контролера все ще повідомляє, що том справний, і навпаки.

Справність, про яку повідомляється в Podʼах

Для томів, які використовують драйвер CSI з підтримкою RPC NodeGetVolumeHealth зі сторони вузла, kubelet періодично викликає цей RPC для кожного тому CSI, який він змонтував для Podʼа, і записує результат у pod.status.volumeHealth, використовуючи як ключ назву тому з pod.spec.volumes. Інтервал опитування — це налаштування kubelet volumeStatsAggPeriod (прапорець командного рядка --volume-stats-agg-period).

apiVersion: v1
kind: Pod
# ...
status:
  volumeHealth:
  - name: my-volume
    healthConditions:
    - status: Inaccessible
      reason: VolumeNotFound
      message: "volume not found on the storage backend"
    lastTransitionTime: "2026-07-20T12:00:00Z"

kubelet записує лише pods/status, субресурс, який він уже має право оновлювати для Podʼів, привʼязаних до його власного вузла, тому для цього поля не потрібна нова авторизація.

Справність, про яку повідомляється в CSINode

Для кожного зареєстрованого на вузлі драйвера CSI, який підтримує NodeGetStorageHealth, kubelet періодично викликає цей RPC і записує результат у csinode.status.storageHealth, використовуючи як ключ назву драйвера.

apiVersion: storage.k8s.io/v1
kind: CSINode
# ...
status:
  storageHealth:
  - name: csi.example.com
    healthConditions:
    - status: StorageUnreachable
      reason: NetworkPartition
      message: "data path to the storage backend is unreachable from this node"

Запис StorageHealthCondition може за потреби обмежувати свою дію конкретним accessMode або volumeMode для бекендів, які деградують асиметрично (наприклад, мережева проблема, яка впливає на доступ ReadWriteMany, але не на ReadWriteOnce).

Запис у csinodes/status — це нова можливість, додана цією функціональністю: режим авторизації Node та втулок допуску NodeRestriction дозволяють kubelet змінювати лише обʼєкт CSINode, який відповідає його власному вузлу, і лише поки ввімкнено функціональну можливість CSIVolumeHealth.

Справність, про яку повідомляється в PersistentVolumeClaims

Справність томів, яку спостерігає контролер, записує в persistentvolumeclaim.status.healthStatus sidecar-контейнер csi-external-health-monitor-controller, що працює поряд із втулком контролера драйвера CSI. Sidecar-контейнер викликає ControllerListVolumeHealth (або переходить на ControllerGetVolumeHealth для кожного тому) і записує результат:

apiVersion: v1
kind: PersistentVolumeClaim
# ...
status:
  healthStatus:
    healthConditions:
    - status: Inaccessible
      reason: VolumeNotFound
      message: "volume not found on the storage backend"
    lastTransitionTime: "2026-07-20T12:00:00Z"

Жоден вузол ніколи не записує це поле; це робить лише sidecar-контейнер, що працює в панелі управління. Це не дає скомпрометованому або несправному вузлу впливати на те, що інші користувачі кластера бачать у PVC.

Чи доступний цей шлях для конкретного драйвера, залежить від того, чи цей драйвер і його розгортання sidecar-контейнера csi-external-health-monitor-controller перейшли на нові RPC контролера.

Увімкнення моніторингу справності томів

Моніторингом справності томів керує одна функціональна можливість CSIVolumeHealth на kube-apiserver та kubelet:

  • На kube-apiserver увімкнення функціональної можливості дозволяє записувати та читати нові поля статусу; вимкнення вилучає ці поля під час наступного запису в обʼєкт, але зберігає вже збережені значення.
  • На kubelet увімкнення функціональної можливості запускає періодичне опитування зі сторони вузла, описане вище.

Моніторинг зі сторони контролера, який заповнює persistentvolumeclaim.status.healthStatus, не має власної функціональної можливості. Розгортання sidecar-контейнера csi-external-health-monitor-controller поряд із втулком контролера вашого драйвера CSI саме по собі є ввімкненням цього моніторингу.

Увімкнення функціональної можливості саме по собі не призводить до появи інформації про справність: драйвер CSI також повинен оголосити та реалізувати відповідні RPC. Перегляньте документацію свого драйвера CSI, щоб дізнатися, які з чотирьох RPC він підтримує, якщо підтримує.

Моніторинг

kubelet надає метрику типу gauge csi_node_storage_health_status з мітками driver_name, status та reason і значенням 1 для кожного стану бекенду сховища, про який наразі повідомляється для драйвера на цьому вузлі.

Обмеження

  • Kubernetes лише показує ці звіти про справність, але не діє на їх основі. Ніщо в Kubernetes не переплановує Podʼи, не перемикає томи на резерв і не реагує якось інакше на повідомлений стан самостійно. Створення контролера виправлення на основі цих полів статусу залишається за операторами кластерів і постачальниками.
  • Старіша альфа-реалізація тієї самої функціональної можливості CSIVolumeHealth (доступна з Kubernetes v1.21) повідомляла про ненормальні стани томів за допомогою Events Kubernetes та метрики kubelet_volume_stats_health_status_abnormal. Цей механізм замінено полями статусу та RPC, описаними на цій сторінці, і його більше не існує.

Що далі

  • Прочитайте KEP-1432, щоб ознайомитися з повним дизайном.
  • Дивіться документацію драйверів CSI, щоб дізнатися, які драйвери CSI реалізують моніторинг справності томів.

16 - Сховище у Windows

На цій сторінці наведено огляд сховища, специфічного для операційної системи Windows.

Постійне сховище

У Windows є багатошаровий драйвер файлової системи для монтування шарів контейнера та створення копії файлової системи на основі NTFS. Усі шляхи файлів у контейнері розвʼязуються лише в контексті цього контейнера.

  • У Docker монтування томів може бути спрямоване лише на теку в контейнері, а не на окремий файл. Це обмеження не стосується containerd.
  • Монтування томів не може проєктувати файли або теки назад на файлову систему хоста.
  • Файлові системи лише для читання не підтримуються, оскільки завжди потрібен доступ для запису до реєстру Windows та бази даних SAM. Однак томи лише для читання підтримуються.
  • Маски користувача та дозволи для томів недоступні. Оскільки SAM не є спільним для хоста й контейнера, між ними немає зіставлення. Усі дозволи розвʼязуються в контексті контейнера.

Як наслідок, на вузлах Windows не підтримуються такі можливості сховища:

  • Монтування підшляхів тому: у контейнері Windows можна змонтувати лише весь том
  • Монтування підшляхів тому для Secrets
  • Проєкція монтування хоста
  • Коренева файлова система лише для читання (зіставлені томи все ще підтримують readOnly)
  • Зіставлення блокових пристроїв
  • Памʼять як носій сховища (наприклад, emptyDir.medium зі значенням Memory)
  • Можливості файлової системи, такі як uid/gid; дозволи файлової системи Linux для кожного користувача
  • Встановлення дозволів Secret за допомогою DefaultMode (через залежність від UID/GID)
  • Підтримка сховища/томів на основі NFS
  • Розширення змонтованого тому (resizefs)

Томи Kubernetes дозволяють розгортати в Kubernetes складні застосунки, яким потрібне збереження даних і спільне використання томів Podʼами. Керування постійними томами, повʼязаними з конкретним бекендом сховища або протоколом, включає такі дії, як надання, скасування надання та зміна розміру томів, підʼєднання тому до вузла Kubernetes і відʼєднання від нього, а також монтування тому в окремих контейнерах Podʼа, якому потрібно зберігати дані, і його розмонтування.

Компоненти керування томами постачаються як втулки томів Kubernetes. У Windows підтримуються такі широкі класи втулків томів Kubernetes:

Вбудовані втулки томів

Наведені нижче вбудовані втулки підтримують постійне сховище на вузлах Windows: