Хостинг
VDS
Аренда серверов
Домены
Почта
SSL
Хранилище
Сайты
Обзоры
Регламенты
AI Studio
Kubernetes
Архив
Использование дополнительных дисков как Persistent Volume в Kubernetes

В Kubernetes для работы с постоянным хранилищем данных используются Persistent Volume (PV) и Persistent Volume Claim (PVC). Для узлов кластера, где есть дополнительные диски, можно создавать локальные тома, которые будут использоваться как PV.

В NetAngels к узлам кластера Kubernetes можно подключать дополнительные локальные диски, которые использовать для хранения данных приложений. Разберемcя как использовать блочные устройства на узлах в качестве Persistent Volumes.

Для начала работы

Перед началом работы вам понадобится:

  • Кластер Kubernetes в NetAngels с двумя узлами в группе

  • Подключенная к узлам группа дополнительных дисков минимального размера

  • Установленная утилита kubectl

1. Создание StorageClass

Сначала создадим StorageClass для локальных томов:

kubectl apply -f - <<EOF
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
EOF

Проверим созданный StorageClass:

kubectl get storageclass local-storage
NAME                      PROVISIONER                    RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-storage (default)   kubernetes.io/no-provisioner   Delete          WaitForFirstConsumer   false                  57s

2. Подготовка Persistent Volume

Создадим PV, используя диск /dev/vdb на узле worker-1:

kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv-worker-1
spec:
  volumeMode: Filesystem
  capacity:
    storage: 2Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /dev/vdb
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - worker-1
EOF

Проверим созданный PV:

kubectl get pv local-pv-worker-1
NAME                CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS    VOLUMEATTRIBUTESCLASS   REASON   AGE
local-pv-worker-1   2Gi        RWO            Delete           Available           local-storage   <unset>                          11s

3. Создание Persistent Volume Claim

Создадим PVC, который будет связан с созданным PV:

kubectl apply -f - <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: nginx-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 2Gi
EOF

Проверим созданный PVC:

kubectl get pvc nginx-pvc
NAME        STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS    VOLUMEATTRIBUTESCLASS   AGE
nginx-pvc   Pending                                      local-storage   <unset>                 12s

4. Использование PVC в Pod

Создадим Pod, который будет использовать PVC для монтирования тома:

kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-local
spec:
  containers:
  - name: nginx-local
    image: library/nginx:1.28-alpine
    ports:
    - containerPort: 80
    volumeMounts:
      - mountPath: "/var/www/html"
        name: data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: nginx-pvc
EOF

Проверим состояние PV

kubectl get pv local-pv-worker-1 
NAME                CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS    VOLUMEATTRIBUTESCLASS   REASON   AGE
local-pv-worker-1   2Gi        RWO            Delete           Bound    default/nginx-pvc   local-storage   <unset>                          3m52s

Проверим состояние PVC

kubectl get pvc nginx-pvc 
NAME        STATUS   VOLUME              CAPACITY   ACCESS MODES   STORAGECLASS    VOLUMEATTRIBUTESCLASS   AGE
nginx-pvc   Bound    local-pv-worker-1   2Gi        RWO            local-storage   <unset>                 2m56s

Проверим запущенный Pod:

kubectl get pod nginx-local 
NAME          READY   STATUS    RESTARTS   AGE
nginx-local   1/1     Running   0          43s

Проверим смонтированный каталог

kubectl exec -it pods/nginx-local -- df -h /var/www/html
kubectl exec -it pods/nginx-local -- grep /var/www/html /proc/mounts
Filesystem                Size      Used Available Use% Mounted on
/dev/vdb                 19.5G     24.0K     19.5G   0% /var/www/html

/dev/vdb /var/www/html ext4 rw,relatime 0 0

Блочное устойство было успешно подключено к поду. Как видно из вывода, фактический размер блочного устройства значительно выше, чем было запрошено в PVC. Это объясняется тем, что к узлу кластера подключен дополнительный диск размером 20ГБ, а к поду он, при таком способе подключения, подключается целиком.

5. Использование local-static-provisioner

Для автоматизации создания PV на основе локальных дисков используется Local Static Provisioner. Этот поставщик позволяет автоматически создавать PV на основе указанных шаблонов устройств.

Подготовка конфигурации

Создадим файл values-block.yaml с конфигурацией для провизионера:

# Mount the host's `/dev/` by default so that block device symlinks can be
# resolved by the containers
mountDevVolume: false
# Configuration for classes of static volumes.
classes:
- name: local-storage-vdb # Defines name of storage classes.
  # Path on the host where local volumes of this storage class are mounted
  # under.
  hostDir: /dev
  # File name pattern to discover. By default, discover all file names.
  namePattern: "vdb"
  # The volume mode of created PersistentVolume object. Default to Filesystem
  # if not specified.
  volumeMode: Filesystem
  # Access mode of the volume. default to ReadWriteOnce if not specified.
  accessMode: ReadWriteOnce
  # Filesystem type to mount.
  # It applies only when the source path is a block device,
  # and desire volume mode is Filesystem.
  # Must be a filesystem type supported by the host operating system.
  fsType: ext4
  # Restrict topology of provisioned volumes to specific labels
  allowedTopologies:
  - matchLabelExpressions:
    - key: kubernetes.io/hostname
      values:
      - worker-2
  blockCleanerCommand:
  - "/scripts/shred.sh"
  - "2"
  # Uncomment to create storage class object with default configuration.
  storageClass: true
  # Uncomment to create storage class object and configure it.
  storageClass:
    name: local-storage-vdb
    reclaimPolicy: Delete # Available reclaim policies: Delete/Retain, defaults: Delete.
    isDefaultClass: true # set as default class
    # If you are using cluster autoscaler to scale the workload using volume provisioned by this storage class,
    # set the provisioner of the storage class to another value other than the default.
    # Ref: https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner/issues/288
    provisioner: kubernetes.io/no-provisioner
# Обнаружение устройств только на узле с именем worker-2
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - worker-2

Установка local-static-provisioner

Сгенерируем манифест для установки провизионера с помощью Helm:

helm template sig-storage-local-static-provisioner/local-static-provisioner --version 2.8.0  --namespace sig-storage -f values-block.yaml > lsp-block.yaml

Применим полученный манифест:

kubectl create ns sig-storage
kubectl apply -f lsp-block.yaml
namespace/sig-storage created
serviceaccount/release-name-local-static-provisioner created
configmap/release-name-local-static-provisioner-config created
storageclass.storage.k8s.io/local-storage-vdb created
clusterrole.rbac.authorization.k8s.io/release-name-local-static-provisioner-node-clusterrole created
clusterrolebinding.rbac.authorization.k8s.io/release-name-local-static-provisioner-node-binding created
daemonset.apps/release-name-local-static-provisioner created

Проверка работы провизионера

После установки провизионера он автоматически отследит наличие /dev/vdb на узлах и создаст соответствующие PV. Проверим статус:

kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                         STORAGECLASS          VOLUMEATTRIBUTESCLASS   REASON   AGE
local-pv-dd2e6dbf                          20Gi       RWO            Delete           Available                                 local-storage-vdb     <unset>                          71s

Этот подход позволяет автоматически создавать PV при появлении нужных устройств, обеспечивая гибкость управления локальным хранилищем в Kubernetes кластере. В остальном работа с PVC происходит аналогично ручному выделению PV.

Далее можно создать PVC используя новый StorageClass и Pod

kubectl apply -f - <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: nginx-pvc-vdb
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 2Gi
  storageClassName: local-storage-vdb
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-local-vdb
spec:
  containers:
  - name: nginx-local
    image: library/nginx:1.28-alpine
    ports:
    - containerPort: 80
    volumeMounts:
      - mountPath: "/var/www/html"
        name: data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: nginx-pvc-vdb
EOF

Проверим созданные ресурсы

kubectl get pv/local-pv-dd2e6dbf pvc/nginx-pvc-vdb pod/nginx-local-vdb 
NAME                                 CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                   STORAGECLASS        VOLUMEATTRIBUTESCLASS   REASON   AGE
persistentvolume/local-pv-dd2e6dbf   20Gi       RWO            Delete           Bound    default/nginx-pvc-vdb   local-storage-vdb   <unset>                          7m32s

NAME                                  STATUS   VOLUME              CAPACITY   ACCESS MODES   STORAGECLASS        VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/nginx-pvc-vdb   Bound    local-pv-dd2e6dbf   20Gi       RWO            local-storage-vdb   <unset>                 39s

NAME                  READY   STATUS    RESTARTS   AGE
pod/nginx-local-vdb   1/1     Running   0          49s

Удаление ресурсов

kubectl delete pod nginx-local 
kubectl delete pvc nginx-pvc 
kubectl delete pv local-pv-worker-1

kubectl delete pod/nginx-local-vdb
kubectl delete pvc/nginx-pvc

Проверим состояние PV

kubectl describe pv local-pv-dd2e6dbf
Name:              local-pv-dd2e6dbf
Labels:            <none>
Annotations:       pv.kubernetes.io/bound-by-controller: yes
                   pv.kubernetes.io/provisioned-by: local-volume-provisioner-worker-2-f5468500-3f7b-41aa-8127-d39d6f6122c1
Finalizers:        [kubernetes.io/pv-protection]
StorageClass:      local-storage-vdb
Status:            Released
Claim:             default/nginx-pvc-vdb
Reclaim Policy:    Delete
Access Modes:      RWO
VolumeMode:        Filesystem
Capacity:          20Gi
Node Affinity:     
  Required Terms:  
    Term 0:        kubernetes.io/hostname in [worker-2]
Message:           
Source:
    Type:  LocalVolume (a persistent volume backed by local storage on a node)
    Path:  /dev/vdb
Events:
  Type    Reason        Age   From                                                                     Message
  ----    ------        ----  ----                                                                     -------
  Normal  VolumeDelete  90s   local-volume-provisioner-worker-2-f5468500-3f7b-41aa-8127-d39d6f6122c1  Starting cleanup of Block PV "local-pv-dd2e6dbf", this may take a while

Вывод говорит о том, что для PV запустилась процедура очистки. Ранее, в файле values.yaml опцией blockCleanerCommand был задан способ очистки PV перед выдачей другим подам. Сейчас она выполняется на узле worker-2, а после завершения PV станет доступен для повторного использования.

Отметим, что при ручном создании PV, без использования local-volume-provisioner данные PV остаются на диске и будут доступны в следующем поде, к которому будет подключен диск.

Нам доверяют тысячи компаний и разработчиков

22 года
Предоставляем услуги профессионального хостинга
35 000+
Клиентов доверяют нам размещение своих сайтов
99.99%
Подтвержденный uptime наших серверов хостинга
Callibri
Крылья
Tele-Club
Linline
Премьер зал
УГМК-Здоровье
Магнум
Алатырь
Туристер
Callibri
Крылья
Tele-Club
Linline
Премьер зал
УГМК-Здоровье
Магнум
Алатырь
Туристер
ВК49865