Использование дополнительных дисков как Persistent Volume в Kubernetes

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

В NetAngels к узлам кластера Kubernetes можно подключать дополнительные локальные диски, которые использовать для хранения данных приложений. Разберемя как использовать блочные устройства на узлах в качетсве 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 наших серверов хостинга
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
ВК49865