Инструменты Csi#

CSI (Container Storage Interface) - это стандарт для работы с хранилищами данных в DropApp. CSI добавляет возможность управления и настройки доступа к хранилищам данных в DropApp через плагины.

Csi-external-provisioner#

Csi-external-provisioner - компонент, который управляет динамическим выделением томов CSI. Он обеспечивает создание, монтирование и удаление томов CSI по запросу. Предоставляет API для создания, удаления и монтирования томов и запускается в DropApp в виде pod.

Рекомендуемые флаги приведены в таблице.

Таблица. Рекомендуемые флаги Csi-external-provisioner.

Синтаксис флага

Значение

--csi-address <path to CSI socket>

Путь к сокету драйвера CSI внутри pod, который контейнер external-provisioner будет использовать для выполнения операций CSI (/run/csi/socket используется по умолчанию)

--leader-election

Включает выбор главного процесса. Флаг обязателен, если для одного драйвера CSI запущено несколько реплик одного и того же внешнего поставщика. Активным может быть только один из них. Новый главный процесс будет выбран когда текущий процесс завершит работу или перестанет отвечать на запросы в течение примерно 15 секунд

--leader-election-namespace

Namespace, в котором будет создан объект выбора главного процесса. Рекомендуется, чтобы этот параметр заполнялся в namespace, в котором работает external-provisioner

--leader-election-lease-duration <duration>

Продолжительность в секундах, в течение которой допускается простой процесса. По умолчанию 15 секунд

--leader-election-renew-deadline <duration>

Продолжительность в секундах, в течение которой главный процесс повторяет попытку обновления лидерства, прежде чем завершить работу. По умолчанию 10 секунд

--leader-election-retry-period <duration>

Продолжительность в секундах, в течение которой клиенты LeaderElector должны ждать между попытками действий. По умолчанию 5 секунд

--timeout <duration>

Тайм-аут всех обращений к драйверу CSI. Он должен быть установлен на значение, которое подходит для большинства вызовов ControllerCreateVolume и ControllerDeleteVolume. По умолчанию используется 15 секунд

--retry-interval-start <duration>

Начальный интервал повторных попыток при неудачной инициализации или удалении. Он удваивается с каждым сбоем, до --retry-interval-max, а затем перестает увеличиваться. Значение по умолчанию 1 секунда

--retry-interval-max <duration>

Максимальный интервал повторных попыток при неудачной инициализации или удалении. Значение по умолчанию 5 минут

--worker-threads <num>

Количество одновременно запущенных ControllerCreateVolume и ControllerDeleteVolume. Значение по умолчанию 100

--kube-api-qps <num>

Количество запросов в секунду, отправленных клиентом DropApp на сервер API DropApp. По умолчанию 5

--kube-api-burst <num>

Количество запросов к серверу API DropApp, превышающее число запросов в секунду, которые можно отправить в любой момент времени. По умолчанию 10

--cloning-protection-threads <num>

Количество одновременно запущенных потоков, обрабатывающих удаление финализатора клонирования. По умолчанию 1

--http-endpoint

Cетевой адрес TCP, который будет прослушивать HTTP-сервер (порт 8080 на локальном хосте). По умолчанию используется пустая строка, что означает, что сервер отключен

--metrics-path

HTTP-путь, по которому будут отображаться метрики Prometheus. Значение по умолчанию /metrics

--extra-create-metadata

Ввод дополнительных метаданных PVC и PV в качестве параметров при вызове CreateVolume драйвера (ключи csi.storage.k8s.io/pvc/name, csi.storage.k8s.io/pvc/namespace, csi .storage.k8s.io/pv/name)

--controller-publish-readonly

Этот параметр позволяет пометить PV как доступный только для чтения при вызове тома публикации контроллера, если режим доступа PVC. По умолчанию значение false

--enable-pprof

Включение профилирования pprof на сетевом TCP-адресе, указанном параметром --http-endpoint. Путь HTTP /debug/pprof/

Csi-external-provisioner может работать в одном pod с другими внешними контроллерами CSI, такими как Csi-external-attacher, Csi-external-snapshotter и Csi-external-resizer.

Csi-external-provisioner не масштабируется с большим количеством реплик. Только один экземпляр Csi-external-provisioner избирается в качестве главного процесса и работает. Новый главный процесс переизбирается через 15 секунд после завершения работы старого процесса.

Внешний поставщик можно использовать для создания объектов CSIStorageCapacity, которые содержат информацию о емкости хранилища, доступной через драйвер. Затем планировщик DropApp использует эту информацию при выборе nodes для модулей с несвязанными томами, ожидающими первого потребителя.

Все объекты CSIStorageCapacity, созданные экземпляром Csi-external-provisioner, имеют определенные метки:

  • csi.storage.k8s.io/drivername - имя драйвера CSI;

  • csi.storage.k8s.io/managed-by- Csi-external-provisioner для централизованного предоставления, Csi-external-provisioner для распределенного предоставления.

Они создаются в namespace, указанном в namespace переменной среды.

Каждый экземпляр Csi-external-provisioner управляет именно теми объектами с метками, которые соответствуют экземпляру.

При необходимости все объекты CSIStorageCapacity, созданные экземпляром Csi-external-provisioner, могут иметь владельца. Это гарантирует автоматическое удаление объектов при удалении драйвера CSI. Владелец определяется переменными среды POD_NAME/NAMESPACE и параметром --capacity-ownerref-level.

Если владение отключено, администратор хранилища отвечает за удаление потерянных объектов CSIStorageCapacity, и для очистки потерянных объектов драйвера можно использовать следующую команду:

kubectl delete csistoragecapacities -l csi.storage.k8s.io/drivername=my-csi.example.com

Настройка поддержки емкости#

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

  1. Установите переменные среды POD_NAME и NAMESPACE:

    env:
    - name: NAMESPACE
      valueFrom:
      fieldRef:
      fieldPath: metadata.namespace
    - name: POD_NAME
      valueFrom:
      fieldRef:
      fieldPath: metadata.name
    
  2. Примените манифест:

    Csi-external-provisioner.yaml
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: csi-provisioner
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: csi-provisioner
      template:
        metadata:
          labels:
            app: csi-provisioner
        spec:
          serviceAccount: csi-provisioner
          containers:
            - name: csi-provisioner
              image: dappregistry/1.2/csi-provisioner:v3.3.0
              args:
                - "--csi-address=$(ADDRESS)"
                - "--leader-election"
                - "--http-endpoint=:8080"
              env:
                - name: ADDRESS
                  value: /var/lib/csi/sockets/pluginproxy/mock.socket
              imagePullPolicy: "IfNotPresent"
              volumeMounts:
                - name: socket-dir
                  mountPath: /var/lib/csi/sockets/pluginproxy/
              ports:
                - containerPort: 8080
                  name: http-endpoint
                  protocol: TCP
              livenessProbe:
                failureThreshold: 1
                httpGet:
                  path: /healthz/leader-election
                  port: http-endpoint
                initialDelaySeconds: 10
                timeoutSeconds: 10
                periodSeconds: 20
            - name: mock-driver
              image: quay.io/k8scsi/mock-driver:canary
              env:
                - name: CSI_ENDPOINT
                  value: /var/lib/csi/sockets/pluginproxy/mock.socket
              volumeMounts:
                - name: socket-dir
                  mountPath: /var/lib/csi/sockets/pluginproxy/
          volumes:
            - name: socket-dir
              emptyDir:
    
  3. Добавьте в командную строку флаги --enable-capacity.

  4. Добавьте StorageCapacity: true в информационный объект CSIDriver.

  5. Если Csi-external-provisioner не развернут StatefulSet, настройте при помощи флага --capacity-ownerref-level какими объектами будет происходить управление CSIStorageCapacity.

  6. Настройте частоту опроса драйвера для обнаружения измененной емкости с помощью флага --capacity-poll-interval.

  7. Настройте количество рабочих потоков, используемых параллельно с помощью флага --capacity-threads.

  8. Включите создание информации также для классов хранения, которые используют немедленную привязку тома с файлом --capacity-for-immediate-binding.

Csi-external-attacher#

Csi-external-attacher - компонент, который управляет присоединением томов к pods. Он обеспечивает подключение томов к указанному pod. Компонент предоставляет API для присоединения томов и запускается в DropApp в виде pod.

Параметры командной строки Csi-external-attacher представлены в таблице.

Таблица. Параметры командной строки.

Синтаксис флага

Значение

csi-address <path to CSI socket>

Путь к сокету драйвера CSI внутри модуля, который контейнер внешнего подключения будет использовать для выполнения операций CSI. По умолчанию используется /run/csi/socket

--leader-election

Включает выборы главного процесса. Это полезно, когда для одного драйвера CSI работает несколько реплик одного и того же Csi-external-attacher. Активным может быть только один из них

--leader-election-namespace <namespace>

Namespace, в котором запускается Csi-external-attacher, и где будет создан объект выбора главного процесса. Рекомендуется, чтобы этот параметр заполнялся из DropApp DownwardAPI

--timeout <duration>

Тайм-аут всех обращений к драйверу CSI. Он должен быть установлен на значение, которое подходит для большинства вызовов ControllerPublish и ControllerUnpublish. По умолчанию используется 15 секунд

--worker-threads

Количество рабочих nodes для обработки VolumeAttachments. По умолчанию используется значение 10

--retry-interval-start

Время ожидания в случае неудачного старта. По умолчанию 1 секунда

--retry-interval-max

Максимальное время отсрочки действия. По умолчанию 5 минут

--http-endpoint

Сетевой адрес TCP, где будет прослушиваться HTTP-сервер для диагностики, включая метрики и проверку работоспособности при выборе главного процесса ( example:8080, что соответствует порту 8080 на локальном хосте). По умолчанию используется пустая строка, что означает, что сервер отключен

--metrics-path

HTTP-путь, по которому будут отображаться метрики prometheus. По умолчаию /metrics

--reconcile-sync

Частота повторной синхронизации подключенных томов с драйвером. По умолчанию 1 минута

--kube-api-qps

Количество запросов в секунду, отправленных клиентом DropApp на сервер API DropApp. По умолчанию 5.

--kube-api-burst

Количество запросов к серверу API DropApp, превышающее число запросов в секунду, которые можно отправить в любой момент времени. По умолчанию 10

--default-fstype <type>

Тип файловой системы тома для публикации по умолчанию. По умолчанию пустая строка

Развертывание Csi-external-attacher#

Для развертывания Csi-external-attacher выполните следующие шаги:

  1. Создайте новую учетную запись службы и предоставьте ей права для запуска Csi-external-attacher.

  2. Разверните Csi-external-attacher:

    kubectl create deploy/Csi-external-attacher.yaml
    

    Содержание манифеста будет следующим:

    Csi-external-attacher.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: csi-attacher
      namespace: default
    ---
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: external-attacher-runner
    rules:
      - apiGroups: [""]
        resources: ["persistentvolumes"]
        verbs: ["get", "list", "watch", "patch"]
      - apiGroups: ["storage.k8s.io"]
        resources: ["csinodes"]
         verbs: ["get", "list", "watch"]
      - apiGroups: ["storage.k8s.io"]
        resources: ["volumeattachments"]
        verbs: ["get", "list", "watch", "patch"]
      - apiGroups: ["storage.k8s.io"]
        resources: ["volumeattachments/status"]
        verbs: ["patch"]
    ---
    kind: ClusterRoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: csi-attacher-role
    subjects:
      - kind: ServiceAccount
        name: csi-attacher
        # replace with non-default namespace name
        namespace: default
    roleRef:
      kind: ClusterRole
      name: external-attacher-runner
      apiGroup: rbac.authorization.k8s.io
    ---
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      # replace with non-default namespace name
      namespace: default
      name: external-attacher-cfg
    rules:
    - apiGroups: ["coordination.k8s.io"]
      resources: ["leases"]
      verbs: ["get", "watch", "list", "delete", "update", "create"]
    ---
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: csi-attacher-role-cfg
      namespace: default
    subjects:
      - kind: ServiceAccount
        name: csi-attacher
        namespace: default
    roleRef:
      kind: Role
     name: external-attacher-cfg
      apiGroup: rbac.authorization.k8s.io
    

    Этот файл содержит все объекты RBAC, необходимые для запуска Csi-external-attacher.

Вышеприведенная команда - для создания развертывания в DropApp. В данном случае, команда создает deployment, который запускает контейнер с драйвером DropApp.

Csi-external-attacher может работать в одном pod с другими внешними контроллерами CSI, такими как Csi-external-provisioner, Csi-external-snapshotter и Csi-external-resizer.

Csi-external-resizer#

Csi-external-resizer - компонент, который управляет изменением размеров томов. Он обеспечивает операцию изменения размеров томов CSI. Компонент предоставляет API для изменения размеров томов и запускается в DropApp в виде pod.

Параметры командной строки Csi-external-resizer аналогичны приведенным в таблицах разделов Csi-external-attacher и Csi-external-provisioner.

Развертывание Csi-external-resizer#

Для развертывания Csi-external-resizer выполните следующие шаги:

  1. Создайте новую учетную запись службы и предоставьте ей права для запуска Csi-external-resizer.

  2. Разверните Csi-external-resizer:

    kubectl create deploy/Csi-external-resizert.yaml
    

    Содержание манифеста будет следующим:

    Csi-external-resizer.yaml
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: csi-resizer
    spec:
      replicas: 1
      selector:
        matchLabels:
          external-resizer: mock-driver
      template:
        metadata:
          labels:
            external-resizer: mock-driver
        spec:
          serviceAccount: csi-resizer
          containers:
            - name: csi-resizer
              image: dappregistry/1.2/csi-resizer:v1.6.0
              args:
                - "--v=5"
                - "--csi-address=$(ADDRESS)"
                - "--leader-election"
                - "--http-endpoint=:8080"
              env:
                - name: ADDRESS
                  value: /var/lib/csi/sockets/pluginproxy/mock.socket
              imagePullPolicy: "IfNotPresent"
              ports:
                - containerPort: 8080
                  name: http-endpoint
                  protocol: TCP
              livenessProbe:
                failureThreshold: 1
                httpGet:
                  path: /healthz/leader-election
                  port: http-endpoint
                initialDelaySeconds: 10
                timeoutSeconds: 10
                periodSeconds: 20
              volumeMounts:
                - name: socket-dir
                  mountPath: /var/lib/csi/sockets/pluginproxy/
    
            - name: mock-driver
             image: quay.io/k8scsi/mock-driver:canary
              imagePullPolicy: "IfNotPresent"
             env:
                - name: CSI_ENDPOINT
                  value: /var/lib/csi/sockets/pluginproxy/mock.socket
              volumeMounts:
                - name: socket-dir
                  mountPath: /var/lib/csi/sockets/pluginproxy/
    
          volumes:
            - name: socket-dir
              emptyDir:
    

Вышеприведенная команда - для создания deployment в DropApp. Deployment - это объект DropApp, который представляет собой развертывание приложения на нескольких nodes. В этом случае Deployment используется для развертывания драйвера DropApp на нескольких nodes кластера.

Csi-external-resizer может работать в одном pod с другими внешними контроллерами CSI, такими как Csi-external-attacher, **Csi-external-snapshotter и/или Csi-external-provisioner.

Csi-external-snapshotter#

Csi-external-snapshotter - компонент управляет созданием и восстановлением снимков томов. Он обеспечивает создание и восстановление снимков томов CSI. Компонент предоставляет API для создания и восстановления снимков томов и запускается в DropApp в виде pod.

Csi-external-snapshotter должен запускаться один раз для каждого драйвера CSI. Развертывание одного контроллера Csi-external-snapshotter работает для всех драйверов CSI в кластере.

Параметры командной строки Csi-external-snapshotter аналогичны приведенным в таблицах разделов Csi-external-attacher и Csi-external-provisioner.

Развертывание Csi-external-snapshotter#

Для развертывания Csi-external-snapshotter выполните следующие шаги:

  1. Создайте новую учетную запись службы и предоставьте ей права для запуска Csi-external-snapshotter.

  2. Разверните Csi-external-snapshotter:

    kubectl create deploy/Csi-external-snapshotter.yaml
    

    Содержание манифеста будет следующим:

    Csi-external-snapshotter.yaml
    kind: StatefulSet
    apiVersion: apps/v1
    metadata:
      name: csi-snapshotter
    spec:
      serviceName: "csi-snapshotter"
      replicas: 1
      selector:
        matchLabels:
          app: csi-snapshotter
      template:
        metadata:
          labels:
            app: csi-snapshotter
        spec:
          serviceAccount: csi-snapshotter
          containers:
            - name: csi-provisioner
              image: dappregistry/csi-provisioner:v3.3.0
              args:
                - "--v=5"
                - "--csi-address=$(ADDRESS)"
              env:
                - name: ADDRESS
                  value: /csi/csi.sock
              imagePullPolicy: IfNotPresent
              volumeMounts:
                - name: socket-dir
                  mountPath: /csi
            - name: csi-snapshotter
              image: dappregistry/csi-snapshotter:v3.0.3
              args:
                - "--v=5"
                - "--csi-address=$(ADDRESS)"
                - "--leader-election=false"
              env:
                - name: ADDRESS
                  value: /csi/csi.sock
              imagePullPolicy: IfNotPresent
              volumeMounts:
                - name: socket-dir
                  mountPath: /csi
            - name: hostpath
              image: k8s.gcr.io/sig-storage/hostpathplugin:v1.4.0
              args:
                - "--drivername=hostpath.csi.k8s.io"
                - "--v=5"
                - "--endpoint=$(CSI_ENDPOINT)"
                - "--nodeid=$(KUBE_NODE_NAME)"
              env:
                - name: CSI_ENDPOINT
                  value: unix:///csi/csi.sock
                - name: KUBE_NODE_NAME
                  valueFrom:
                    fieldRef:
                      apiVersion: v1
                      fieldPath: spec.nodeName
              imagePullPolicy: IfNotPresent
              securityContext:
                privileged: true
              volumeMounts:
                - name: socket-dir
                  mountPath: /csi
          volumes:
            - name: socket-dir
              emptyDir:
    

Вышеприведенная команда - для создания StatefulSet в DropApp.

Csi-node-driver-registrar#

Csi-node-driver-registrar - компонент управляет регистрацией драйверов для устройств хранения данных на nodes DropApp. Он обеспечивает регистрацию драйвера на каждом node, который будет использоваться для работы с хранилищами данных. Компонент предоставляет API для регистрации драйверов и запускается в DropApp в виде DaemonSet.

Примечание

Все приведенные компоненты csi-node-driver-registrar используются вместе для управления томами и хранилищами данных в DropApp с помощью CSI стандарта.

Csi-node-driver-registrar представляет собой дополнительный контейнер, который извлекает информацию о драйвере (используя NodeGetInfo) из конечной точки CSI и регистрирует ее в kubelet на этом node с помощью механизма регистрации подключаемого модуля kubelet.

Kubelet напрямую выполняет вызовы CSI NodeGetInfo, NodeStageVolume и NodePublishVolume для драйверов CSI. Он использует механизм регистрации подключаемого модуля kubelet для обнаружения сокета домена unix для взаимодействия с драйвером CSI. Следовательно, все драйверы CSI должны использовать этот sidecar-контейнер для регистрации в kubelet.

Таблица. Параметры командной строки.

Синтаксис флага

Значение

--csi-address

Путь к сокету драйвера внутри модуля, который контейнер Csi-node-driver-registrar будет использовать для выполнения операций CSI (например, /csi/csi.sock)

--kubelet-registration-path

Путь к сокету драйвера CSI на host-node, который kubelet будет использовать для выполнения операций CSI (например, /var/lib/kubelet/plugins/<drivername.example.com>/csi.sock)

Csi-node-driver-registrar не взаимодействует с API DropApp, поэтому правила RBAC не нужны.

Csi-node-driver-registrar должен иметь возможность монтировать тома hostPath и иметь права доступа к файлам.

Регистрация DropApp CSI Driver#

Для регистрации CSI Driver выполните следующие шаги:

  1. Получите доступ к сокету драйвера CSI (путь: /var/lib/kubelet/plugins/<drivername.example.com>/).

  2. Получите доступ к регистрационному сокету (путь: /var/lib/kubelet/plugins_registry/). Убедитесь, что плагин для регистрации доступен на хосте, на котором запущен DropApp. Обычно это можно проверить, выполнив команду kubectl get pods -n kube-system. Если виден pod с именем etcd-<host_name>, то плагин доступен.

  3. Проверьте работоспособность csi-node-driver-registrar:

      containers:
        - name: csi-driver-registrar
          image: dappregistry/sig-storage/csi-node-driver-registrar:v2.5.1
          args:
            - "--v=5"
            - "--csi-address=/csi/csi.sock"
            - "--kubelet-registration-path=/var/lib/kubelet/plugins/<drivername.example.com>/csi.sock"
          livenessProbe:
            exec:
              command:
              - /csi-node-driver-registrar
              - --kubelet-registration-path=/var/lib/kubelet/plugins/<drivername.example.com>/csi.sock
              - --mode=kubelet-registration-probe
            initialDelaySeconds: 30
            timeoutSeconds: 15
    

    Выше приведена конфигурация контейнера для DropApp, который используется для регистрации DropApp CSI Driver. В контейнере используется образ Docker, он содержит программу Сsi-node-driver-registrar, которая регистрирует DropApp CSI Driver в кластере.

    Контейнер используется для запуска программы для регистрации драйвера DropApp. Драйвер - это компонент, который позволяет nodes DropApp подключаться к блочным устройствам, таким как диски или сетевые хранилища. В данном случае, контейнер используется для регистрации драйвера DropApp в системе.

    Флаг --mode=kubelet-registration-probe модифицирует Сsi-node-driver-registrar в зонд, проверяющий, прошла ли регистрация подключаемого модуля kubelet успешно. Значение --kubelet-registration-path должно быть таким же, как задано в аргументах контейнера, --csi-address в этом режиме не требуется.

    Если --http-endpoint установлено, то Сsi-node-driver-registrar предоставляет конечную точку проверки работоспособности по указанному адресу и пути /healthz, указывая, существует ли сокет регистрации.

  4. Примените спецификацию:

          containers:
            - name: csi-driver-registrar
              image: /sig-storage/csi-node-driver-registrar:v2.5.1
              args:
                - "--csi-address=/csi/csi.sock"
                - "--kubelet-registration-path=/var/lib/kubelet/plugins/<drivername.example.com>/csi.sock"
                # Адрес не является существующим и приведен в качестве примера.
                - "--health-port=9809"
              volumeMounts:
                - name: plugin-dir
                  mountPath: /csi
                - name: registration-dir
                  mountPath: /registration
              ports:
                - containerPort: 9809
                  name: healthz
              livenessProbe:
                httpGet:
                  path: /healthz
                  port: healthz
                initialDelaySeconds: 5
                timeoutSeconds: 5
          volumes:
            - name: registration-dir
              hostPath:
                path: /var/lib/kubelet/plugins_registry/
                type: Directory
            - name: plugin-dir
              hostPath:
                path: /var/lib/kubelet/plugins/<drivername.example.com>/
                # Адрес не является существующим и приведен в качестве примера.
                type: DirectoryOrCreate
    

Выше представлен контейнер для DropApp, используемый для регистрации DropApp Controller Manager в кластере DropApp. В конфигурации контейнера используется образ Docker с программой csi-node-driver-registrar. Контейнер также содержит два тома - /csi и /registration, которые используются для хранения данных регистрации DropApp Controller. Порт 9809 используется для проверки работоспособности контейнера. Liveness Probe проверяет работоспособность контейнера каждые 5 секунд.