Практычны прыклад падключэння сховішча на базе Ceph у кластар Kubernetes

Container Storage Interface (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 (Pod Security Policies). Опцыі ў раздзелах nodeplugin и забеспячэнне ужо ёсць у файле, іх можна выправіць так, як паказана ніжэй:

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 і выдаём яму права на запіс у пул. кубе:

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: <user-key>

І ствараем наш сакрэт:

kubectl apply -f secret.yaml

Далей нам патрэбен прыкладна такі маніфест StorageClass:

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

   imageFeatures: layering

   # Эти секреты должны содержать данные для авторизации
   # в ваш пул.
   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

А вось і праблема:

электроннай пошце: Завяршыць карыстача, каб аднавіць файл (сістэма перасылка), каб завяршыць файл сістэме, якая павінна адпавядаць 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: <cluster-id>

  # Имя файловой системы 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 падыходзіць выключна для мэт навучання, чым мы і займаемся на нашых. курсах Слёрм. Не думаю, што хтосьці стане гэта рабіць у прадакшэне, вялікая рызыка выпадкова зацерці важныя файлы.

Ну і напрыканцы давайце праверым, як у выпадку з CephFS ідуць справы са зменай памераў тома. Вяртаемся ў Kubernetes і адрэдагуем наш маніфест для PVC – павялічым там памер, да прыкладу, да 7Gi.

Ужыем адрэдагаваны файл:

kubectl apply -f pvc.yaml

Паглядзім на прымантаваным каталогу, як змянілася квота:

getfattr -n ceph.quota.max_bytes <каталог-с-данными>

Для працы гэтай каманды, магчыма, вам спатрэбіцца ўсталяваць у сістэму пакет атр.

Вочы баяцца, а рукі робяць

З выгляду ўсе гэтыя загаворы і доўгія маніфесты YAML здаюцца складанымі, але на практыцы студэнты Слёрма разбіраюцца з імі даволі хутка.
У гэтым артыкуле мы не паглыбляліся ў нетры - для гэтага ёсць афіцыйная дакументацыя. Калі вас цікавяць дэталі наладкі сховішча Ceph сумесна з кластарам Kubernetes, дапамогуць вось гэтыя спасылкі:

Агульныя прынцыпы працы Kubernetes з тамамі
Дакументацыя па RBD
Інтэграцыя RBD і Kubernetes з пункту гледжання Ceph
Інтэграцыя RBD і Kubernetes з пункту гледжання CSI
Агульная дакументацыя па CephFS
Інтэграцыя CephFS і Kubernetes з пункта гледжання CSI

На курсе Слёрм Kubernetes База вы можаце пайсці яшчэ крыху далей і разгарнуць у Kubernetes рэальнае прыкладанне, якое будзе выкарыстоўваць CephFS ў якасці сховішчы для файлаў. Праз GET/POST запытаў вы зможаце перадаваць файлы і атрымліваць іх з Ceph.

А калі вам больш цікава захоўванне дадзеных, то запісвайцеся на новы курс па Ceph. Пакуль ідзе бэта-тэст, курс можна атрымаць са зніжкай і паўплываць на яго змест.

Аўтар артыкула: Аляксандр Швалаў, практыкуючы інжынер Саўджыдж, Certified Kubernetes Administrator, аўтар і распрацоўшчык курсаў Слёрм.

Крыніца: habr.com