Un exemplu practic de conectare a stocării bazate pe Ceph la un cluster Kubernetes

Container Storage Interface (CSI) este o interfață unificată între Kubernetes și sistemele de stocare. Am vorbit deja pe scurt despre asta a declarat, iar astăzi vom arunca o privire mai atentă asupra combinației dintre CSI și Ceph: vom arăta cum conectați stocarea Ceph către clusterul Kubernetes.
Articolul oferă exemple reale, deși ușor simplificate, pentru ușurința percepției. Nu luăm în considerare instalarea și configurarea clusterelor Ceph și Kubernetes.

Te întrebi cum funcționează?

Un exemplu practic de conectare a stocării bazate pe Ceph la un cluster Kubernetes

Deci, aveți un cluster Kubernetes la îndemână, implementat, de exemplu, kubespray. Există un cluster Ceph care funcționează în apropiere - îl puteți instala și, de exemplu, cu aceasta un set de cărți de joc. Sper sa nu fie nevoie sa mentionez ca pentru productie intre ele trebuie sa existe o retea cu o latime de banda de minim 10 Gbit/s.

Dacă ai toate astea, să mergem!

Mai întâi, să mergem la unul dintre nodurile clusterului Ceph și să verificăm dacă totul este în ordine:

ceph health
ceph -s

În continuare, vom crea imediat un pool pentru discurile RBD:

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

Să trecem la clusterul Kubernetes. Acolo, în primul rând, vom instala driverul Ceph CSI pentru RBD. Vom instala, așa cum era de așteptat, prin Helm.
Adăugăm un depozit cu o diagramă, obținem un set de variabile pentru diagrama ceph-csi-rbd:

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

Acum trebuie să completați fișierul cephrbd.yml. Pentru a face acest lucru, aflați ID-ul clusterului și adresele IP ale monitoarelor din Ceph:

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

Introducem valorile obținute în fișierul cephrbd.yml. În același timp, permitem crearea de politici PSP (Pod Security Policies). Opțiuni în secțiuni nodeplugin и asigurator deja în fișier, acestea pot fi corectate după cum se arată mai jos:

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

În continuare, tot ce ne rămâne este să instalăm diagrama în clusterul Kubernetes.

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

Grozav, driverul RBD funcționează!
Să creăm o nouă StorageClass în Kubernetes. Acest lucru necesită din nou un pic de reparații cu Ceph.

Creăm un utilizator nou în Ceph și îi dăm drepturi de a scrie în pool cub:

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

Acum să vedem că cheia de acces este încă acolo:

ceph auth get-key client.rbdkube

Comanda va scoate ceva de genul acesta:

AQCO9NJbhYipKRAAMqZsnqqS/T8OYQX20xIa9A==

Să adăugăm această valoare la Secret în clusterul Kubernetes - acolo unde avem nevoie cheie utilizator:

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

Și creăm secretul nostru:

kubectl apply -f secret.yaml

În continuare, avem nevoie de un manifest StorageClass ceva de genul acesta:

---
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

Trebuie completat clusterID, pe care l-am învățat deja de echipă ceph fsidși aplicați acest manifest pentru clusterul Kubernetes:

kubectl apply -f storageclass.yaml

Pentru a verifica cum funcționează grupurile împreună, să creăm următorul PVC (Revendicare de volum persistentă):

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

Să vedem imediat cum Kubernetes a creat volumul solicitat în Ceph:

kubectl get pvc
kubectl get pv

Totul pare a fi grozav! Cum arată asta pe partea Ceph?
Primim o listă de volume din pool și vedem informații despre volumul nostru:

rbd ls -p kube
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653  # тут, конечно же, будет другой ID тома, который выдала предыдущая команда

Acum să vedem cum funcționează redimensionarea unui volum RBD.
Schimbați dimensiunea volumului în manifestul pvc.yaml la 2Gi și aplicați-l:

kubectl apply -f pvc.yaml

Să așteptăm ca modificările să intre în vigoare și să ne uităm din nou la dimensiunea volumului.

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

kubectl get pv
kubectl get pvc

Vedem că dimensiunea PVC-ului nu s-a schimbat. Pentru a afla de ce, puteți interoga Kubernetes pentru o descriere YAML a PVC-ului:

kubectl get pvc rbd-pvc -o yaml

Iată problema:

mesaj: Se așteaptă ca utilizatorul să (re)pornească un pod pentru a finaliza redimensionarea sistemului de fișiere a volumului pe nod. tip: FileSystemResizePending

Adică, discul a crescut, dar sistemul de fișiere de pe el nu a crescut.
Pentru a crește sistemul de fișiere, trebuie să montați volumul. La noi, PVC/PV creat nu este în prezent folosit în niciun fel.

Putem crea un pod de testare, de exemplu astfel:

---
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

Și acum să ne uităm la PVC:

kubectl get pvc

Dimensiunea s-a schimbat, totul este bine.

În prima parte, am lucrat cu dispozitivul bloc RBD (acesta înseamnă Rados Block Device), dar acest lucru nu se poate face dacă diferite microservicii trebuie să funcționeze simultan cu acest disc. CephFS este mult mai potrivit pentru lucrul cu fișiere, mai degrabă decât cu imagini de disc.
Folosind exemplul clusterelor Ceph și Kubernetes, vom configura CSI și alte entități necesare pentru a lucra cu CephFS.

Să obținem valorile din noua diagramă Helm de care avem nevoie:

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

Din nou trebuie să completați fișierul cephfs.yml. Ca și înainte, comenzile Ceph vă vor ajuta:

ceph fsid
ceph mon dump

Completați fișierul cu valori ca aceasta:

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

Vă rugăm să rețineți că adresele monitorului sunt specificate în formularul simplu adresa:port. Pentru a monta cephf-uri pe un nod, aceste adrese sunt transferate către modulul kernel, care încă nu știe cum să lucreze cu protocolul de monitorizare v2.
Schimbăm portul pentru httpMetrics (Prometheus va merge acolo pentru monitorizarea valorilor), astfel încât să nu intre în conflict cu nginx-proxy, care este instalat de Kubespray. Este posibil să nu aveți nevoie de asta.

Instalați diagrama Helm în cluster-ul Kubernetes:

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

Să mergem la magazinul de date Ceph pentru a crea un utilizator separat acolo. Documentația afirmă că furnizorul CephFS necesită drepturi de acces de administrator de cluster. Dar vom crea un utilizator separat fs cu drepturi limitate:

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'

Și să ne uităm imediat la cheia lui de acces, vom avea nevoie de ea mai târziu:

ceph auth get-key client.fs

Să creăm Secret și StorageClass separate.
Nimic nou, am văzut deja acest lucru în exemplul RBD:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-cephfs-secret
  namespace: ceph-csi-cephfs
stringData:
  # Необходимо для динамически создаваемых томов
  adminID: fs
  adminKey: <вывод предыдущей команды>

Aplicarea manifestului:

kubectl apply -f secret.yaml

Și acum - o clasă de stocare separată:

---
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

Să-l completăm aici clusterID și aplicabil în Kubernetes:

kubectl apply -f storageclass.yaml

Проверка

Pentru a verifica, ca în exemplul anterior, să creăm un PVC:

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

Și verificați prezența PVC/PV:

kubectl get pvc
kubectl get pv

Dacă doriți să vă uitați la fișiere și directoare în CephFS, puteți monta acest sistem de fișiere undeva. De exemplu, așa cum se arată mai jos.

Să mergem la unul dintre nodurile clusterului Ceph și să efectuăm următoarele acțiuni:

# Точка монтирования
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

Desigur, montarea FS pe un nod Ceph ca acesta este potrivită numai în scopuri de antrenament, ceea ce facem pe noi. Cursuri de slurm. Nu cred că cineva ar face asta în producție; există un risc mare de a șterge accidental fișierele importante.

Și, în sfârșit, să verificăm cum funcționează lucrurile cu redimensionarea volumelor în cazul CephFS. Să revenim la Kubernetes și să ne edităm manifestul pentru PVC - creștem dimensiunea acolo, de exemplu, la 7Gi.

Să aplicăm fișierul editat:

kubectl apply -f pvc.yaml

Să ne uităm la directorul montat pentru a vedea cum s-a schimbat cota:

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

Pentru ca această comandă să funcționeze, poate fi necesar să instalați pachetul pe sistemul dumneavoastră attr.

Ochilor le este frică, dar mâinile fac

Toate aceste vrăji și manifeste lungi YAML par complicate la suprafață, dar, în practică, studenții Slurm le înțeleg destul de repede.
În acest articol nu am intrat adânc în junglă - există documentație oficială pentru asta. Dacă sunteți interesat de detaliile privind configurarea stocării Ceph cu un cluster Kubernetes, aceste link-uri vă vor ajuta:

Principii generale ale lucrului Kubernetes cu volume
Documentația RBD
Integrarea RBD și Kubernetes din perspectiva Ceph
Integrarea RBD și Kubernetes dintr-o perspectivă CSI
Documentație generală CephFS
Integrarea CephFS și Kubernetes dintr-o perspectivă CSI

Pe cursul Slurm Baza Kubernetes puteți merge puțin mai departe și puteți implementa o aplicație reală în Kubernetes care va folosi CephFS ca stocare de fișiere. Prin solicitările GET/POST veți putea transfera fișiere și le veți primi de la Ceph.

Și dacă sunteți mai interesat de stocarea datelor, atunci înscrieți-vă curs nou despre Ceph. În timp ce testul beta este în desfășurare, cursul poate fi obținut cu reducere și puteți influența conținutul acestuia.

Autorul articolului: Alexander Shvalov, inginer practicant Southbridge, Administrator certificat Kubernetes, autor și dezvoltator de cursuri Slurm.

Sursa: www.habr.com