Практически пример за свързване на хранилище на база Ceph в кластер Kubernetes

Интерфейс хранилища контейнеров (CSI) — это унифицированный интерфейс для взаимодействия Kubernetes и систем хранения данных. Кратко о нём мы уже разказваха, а сегодня подробнее рассмотрим интеграцию CSI и Ceph: покажем, как подключить хранилище Ceph к кластеру Kubernetes.
В статье приведены реальные примеры, хотя и немного упрощенные для удобства восприятия. Установку и настройку кластеров Ceph и Kubernetes мы не рассматриваем.

Вам интересно, как это работает?

Практически пример за свързване на хранилище на база Ceph в кластер Kubernetes

Итак, у вас под рукой есть развернутый кластер Kubernetes, например, kubespray. Рядом работает кластер Ceph — его можно также развернуть, например, используя этот набор плейбуков. Надеюсь, не нужно упоминать, что для продакшена между ними должна быть сеть с пропускной способностью не менее 10 Гбит/с.

Если у вас всё это есть, поехали!

Сначала зайдем на одну из нод кластера Ceph и проверим, что всё в порядке:

ceph health
ceph -s

Далее создадим пул для RBD дисков:

ceph osd pool create kube 32
ceph osd pool application enable kube rbd

Теперь переходим в кластер Kubernetes. Первым делом устанавим драйвер Ceph CSI для RBD. Ставить будем, как и полагается, через Helm.
Добавим репозиторий с чартом и получим набор переменных чартов ceph-csi-rbd:

helm repo add ceph-csi https://ceph.github.io/csi-charts
helm inspect values ceph-csi/ceph-csi-rbd > cephrbd.yml

Теперь нужно заполнить файл cephrbd.yml. Для этого узнаем ID кластера и IP-адреса мониторов в Ceph:

ceph fsid  # так мы узнаем clusterID
ceph mon dump  # а так увидим IP-адреса мониторов

Полученные значения заносим в файл cephrbd.yml. Кроме того, включаем создание политик PSP (Политики безопасности подов). Опции в разделах nodeplugin и provisioner уже присутствуют в файле, их можно исправить следующим образом:

csiConfig:
  - clusterID: "bcd0d202-fba8-4352-b25d-75c89258d5ab"
    monitors:
      - "v2:172.18.8.5:3300/0,v1:172.18.8.5:6789/0"
      - "v2:172.18.8.6:3300/0,v1:172.18.8.6:6789/0"
      - "v2:172.18.8.7:3300/0,v1:172.18.8.7:6789/0"

nodeplugin:
  podSecurityPolicy:
    enabled: true

provisioner:
  podSecurityPolicy:
    enabled: true

Далее всё, что нам остается — установить чарт в кластер Kubernetes.

helm upgrade -i ceph-csi-rbd ceph-csi/ceph-csi-rbd -f cephrbd.yml -n ceph-csi-rbd --create-namespace

Отлично, драйвер RBD работает!
Создадим в Kubernetes новый StorageClass. Для этого снова потребуется немного поработать с Ceph.

Создаем нового пользователя в Ceph и выдаем ему права на запись в пул kube:

ceph auth get-or-create client.rbdkube mon 'profile rbd' osd 'profile rbd pool=kube'

А теперь посмотрим ключ доступа: всё там же:

ceph auth get-key client.rbdkube

Команда выдаст что-то вроде:

AQCO9NJbhYipKRAAMqZsnqqS/T8OYQX20xIa9A==

Занесём это значение в Secret в кластере Kubernetes — туда, где нужен userKey:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-rbd-secret
  namespace: ceph-csi-rbd
stringData:
  # Стойностите на ключовете съответстват на потребителското име и неговия ключ, как е посочено в
  # клъстера Ceph. ID на потребителя трябва да има достъп до пула,
  # указан в storage class
  userID: rbdkube
  userKey:

И създаваме нашия секрет:

kubectl apply -f secret.yaml

Следва ни e необходим такъв манифест StorageClass:

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
   name: csi-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
   clusterID: 
   pool: kube

   imageFeatures: layering

   # Тези секрети трябва да съдържат данни за авторизация
   # в пулa ви.
   csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
   csi.storage.k8s.io/provisioner-secret-namespace: ceph-csi-rbd
   csi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secret
   csi.storage.k8s.io/controller-expand-secret-namespace: ceph-csi-rbd
   csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
   csi.storage.k8s.io/node-stage-secret-namespace: ceph-csi-rbd

   csi.storage.k8s.io/fstype: ext4

reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
  - discard

Трябва да попълним clusterID, който вече узнахме с командата ceph fsid, и да приложим този манифест в кластера Kubernetes:

kubectl apply -f storageclass.yaml

За да проверим работата на кластерите в атака, създаваме следния PVC (Persistent Volume Claim):

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: rbd-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: csi-rbd-sc

Нека веднага да видим как Kubernetes е създал в Ceph запитания том:

kubectl get pvc
kubectl get pv

Всичко изглежда отлично! А как изглежда на страната на Ceph?
Получаваме списък с томове в пула и преглеждаме информацията за нашия том:

rbd ls -p kube
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653  # тук, разбира се, ще бъде друг ID на тома, който издаде предишната команда

Сега нека видим как работи промяната на размера на тома RBD.
Променяме размера на тома в манифеста pvc.yaml до 2Gi и го прилагаме:

kubectl apply -f pvc.yaml

Да изчакаме, докато промените влязат в сила, и отново да погледнем размера на тома.

rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653

kubectl get pv
kubectl get pvc

Виждаме, че размерът на PVC не е променен. За да разберем причината, можем да поискаме от Kubernetes описание на PVC в YAML формат:

kubectl get pvc rbd-pvc -o yaml

А ето и проблема:

message: Waiting for user to (re-)start a pod to finish file system resize of volume on node. type: FileSystemResizePending

Тоест, дискът е увеличен, но файловата система на него — не.
За да увеличим файловата система, трябва да монтираме тома. При нас създадения PVC/PV в момента не се използва по никакъв начин.

Можем да създадем тестов Pod, например така:

---
apiVersion: v1
kind: Pod
metadata:
  name: csi-rbd-demo-pod
spec:
  containers:
    - name: web-server
      image: nginx:1.17.6
      volumeMounts:
        - name: mypvc
          mountPath: /data
  volumes:
    - name: mypvc
      persistentVolumeClaim:
        claimName: rbd-pvc
        readOnly: false

И сега да разгледаме PVC:

kubectl get pvc

Размерът се промени, всичко е наред.

В първата част работихме с блочно устройство RBD (както е обозначено – Rados Block Device), но не е удачно да се прави, ако различни микросервизи трябва да работят паралелно с този диск. За работа с файлове, вместо с образ на диск, CephFS е много по-подходящ.
На основата на кластерите Ceph и Kubernetes, ще настроим CSI и другите необходими единици за работа с CephFS.

Нека извлечем стойностите от необходимия ни нов Helm-чарта:

helm inspect values ceph-csi/ceph-csi-cephfs > cephfs.yml

Отново е необходимо да попълним файла cephfs.yml. Както и преди, командите на Ceph ще ни помогнат:

ceph fsid
ceph mon dump

Попълваме файла със стойности по следния начин:

csiConfig:
  - clusterID: "bcd0d202-fba8-4352-b25d-75c89258d5ab"
    monitors:
      - "172.18.8.5:6789"
      - "172.18.8.6:6789"
      - "172.18.8.7:6789"

nodeplugin:
  httpMetrics:
    enabled: true
    containerPort: 8091
  podSecurityPolicy:
    enabled: true

provisioner:
  replicaCount: 1
  podSecurityPolicy:
    enabled: true

Обърнете внимание, че адресите на мониторите се посочват в простия формат address:port. За монтиране на cephfs на възела, тези адреси се предават на ядрения модул, който все още не умее да работи с протокола на мониторите v2.
Порта за httpMetrics (където Prometheus ще събира метрики за мониторинг) променяме, за да не влиза в конфликт с nginx-proxy, който се инсталира от Kubespray. Възможно е това да не е необходимо за вас.

Инсталираме Helm-чарта в кластера Kubernetes:

helm upgrade -i ceph-csi-cephfs ceph-csi/ceph-csi-cephfs -f cephfs.yml -n ceph-csi-cephfs --create-namespace

Преминаваме към хранилището на данни Ceph, за да създадем отделен потребител там. Документацията посочва, че на провизионера CephFS са необходими администраторски права в кластера. Но ще създадем отделен потребител fs с ограничени права:

ceph auth get-or-create client.fs mon 'allow r' mgr 'allow rw' mds 'allow rws' osd 'allow rw pool=cephfs_data, allow rw pool=cephfs_metadata'

И веднага ще видим неговия ключ за достъп, ще ни бъде полезен по-нататък:

ceph auth get-key client.fs

Създаваме отделни Secret и StorageClass.
Нищо ново, вече го видяхме на примера на RBD:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-cephfs-secret
  namespace: ceph-csi-cephfs
stringData:
  # Необходимо за динамично създаваните томове
  adminID: fs
  adminKey:

Прилагаме манифеста:

kubectl apply -f secret.yaml

А сега - отделен StorageClass:

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: csi-cephfs-sc
provisioner: cephfs.csi.ceph.com
parameters:
  clusterID: 

  # Името на CephFS файловата система, където ще бъде създаден том
  fsName: cephfs

  # (по желание) Ceph пул, в който ще се съхраняват данните на тома
  # pool: cephfs_data

  # (по желание) Опции за монтиране на Ceph-fuse, разделени с запетаи
  # например:
  # fuseMountOptions: debug

  # (по желание) Опции за монтиране на CephFS за ядрото, разделени с запетаи
  # Вижте man mount.ceph за списък с тези опции. Например:
  # kernelMountOptions: readdir_max_bytes=1048576,norbytes

  # Тайнствените данни трябва да съдържат достъпи за администратор и/или потребител на Ceph.
  csi.storage.k8s.io/provisioner-secret-name: csi-cephfs-secret
  csi.storage.k8s.io/provisioner-secret-namespace: ceph-csi-cephfs
  csi.storage.k8s.io/controller-expand-secret-name: csi-cephfs-secret
  csi.storage.k8s.io/controller-expand-secret-namespace: ceph-csi-cephfs
  csi.storage.k8s.io/node-stage-secret-name: csi-cephfs-secret
  csi.storage.k8s.io/node-stage-secret-namespace: ceph-csi-cephfs

  # (по желание) Драйверът може да използва или ceph-fuse (fuse),
  # или ceph kernelclient (kernel).
  # Ако не е указано, ще се използва обичайното монтиране на томовете,
  # което се определя с търсенето на ceph-fuse и mount.ceph
  # mounter: kernel
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
  - debug

Нека попълним тук clusterID и да приложим в Kubernetes:

kubectl apply -f storageclass.yaml

Проверка

За проверка, както в предишния пример, ще създадем PVC:

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: csi-cephfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
  storageClassName: csi-cephfs-sc

И ще проверим наличието на PVC/PV:

kubectl get pvc
kubectl get pv

Ако искате да видите файловете и директориите в CephFS, можете да монтирате тази файловата система някъде. Например, както е показано по-долу.

Да отидем на един от възлите на Ceph клъстера и да извършим следните действия:

# Точка монтирования
mkdir -p /mnt/cephfs

# Создаём файл с ключом администратора
ceph auth get-key client.admin >/etc/ceph/secret.key

# Добавляем запись в /etc/fstab
# !! Изменяем ip адрес на адрес нашего узла
echo "172.18.8.6:6789:/ /mnt/cephfs ceph name=admin,secretfile=/etc/ceph/secret.key,noatime,_netdev    0       2" >> /etc/fstab

mount /mnt/cephfs

Разбира се, това монтиране на FS на Ceph възел е подходящо единствено за учебни цели, по които работим на нашите курс по Slurm. Не мисля, че някой би го направил в продукция, рискува да изтрие важни файлове.

И накрая, нека проверим как стоят нещата с размера на тома при CephFS. Връщаме се в Kubernetes и редактираме нашия манифест за PVC - ще увеличим размера, например, до 7Gi.

Приложим редактирания файл:

kubectl apply -f pvc.yaml

Да видим на монтирания каталог как се е променила квотата:

getfattr -n ceph.quota.max_bytes

За работа с тази команда, вероятно ще трябва да инсталирате пакет в системата attr.

Очите се страхуват, но ръцете действат

На пръв поглед всички тези команди и дълги YAML манифести изглеждат сложни, но на практика студентите на Слёрм се справят с тях доста бързо.
В тази статия не навлизаме в подробности — за това има официалната документация. Ако се интересувате от детайлите за настройка на Ceph хранилище, интегрирано с Kubernetes клъстера, помощ могат да окажат тези връзки:

Общи принципи на работа на Kubernetes с томове
Документация за RBD
Интеграция на RBD и Kubernetes от гледна точка на Ceph
Интеграция на RBD и Kubernetes от гледна точка на CSI
Обща документация за CephFS
Интеграция на CephFS и Kubernetes от гледна точка на CSI

На курса Слёрм Kubernetes База можете да отидете още по-далеч и да развиете в Kubernetes реално приложение, което ще използва CephFS като хранилище за файлове. Чрез GET/POST заявки ще можете да прехвърляте файлове и да ги получавате от Ceph.

Ако ви интересува повече съхранението на данни, запишете се на новия курс по Ceph. Докато е в бета тест, курсът може да бъде получен с отстъпка и да повлияете на съдържанието му.

Автор на статията: Александър Швалов, практикуващ инженер Southbridge, Certified Kubernetes Administrator, автор и разработчик на курсове в Слёрм.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster