Exemplu practic de conectare a unui stocare bazată pe Ceph într-un cluster Kubernetes

Container Storage Interface (CSI) este o interfață unificată de interacțiune între Kubernetes și sistemele de stocare de date. Am discutat pe scurt despre ea anterior, despre, iar astăzi ne vom concentra mai în detaliu asupra legăturii dintre CSI și Ceph: vom arăta cum să conectăm stocarea Ceph la clusterul Kubernetes.
Articolul oferă exemple reale, deși puțin simplificate pentru a fi mai ușor de înțeles. Nu vom discuta despre instalarea și configurarea clusterelor Ceph și Kubernetes.

Ești interesat să afli cum funcționează?

Exemplu practic de conectare a unui stocare bazată pe Ceph într-un cluster Kubernetes

Deci, ai un cluster Kubernetes la dispoziție, de exemplu, kubespray. Alături, există un cluster Ceph — acesta poate fi de asemenea instalat, de exemplu, folosind acest set de playbook-uri. Sper că nu e nevoie să menționez că pentru producție ar trebui să existe o rețea între ele cu o lățime de bandă de cel puțin 10 Gbit/s.

Dacă toate acestea le ai, să începem!

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

ceph health
ceph -s

Apoi, vom crea un pool pentru discurile RBD:

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

Trecem la clusterul Kubernetes. Acolo, primul pas este să instalăm driverul Ceph CSI pentru RBD. Îl vom instala, așa cum trebuie, prin Helm.
Adăugăm repository-ul cu chart-ul, obținem setul de variabile pentru chart-ul 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ă completăm fișierul cephrbd.yml. Pentru aceasta, vom afla ID-ul clusterului și adresele IP ale monitorilor din Ceph:

ceph fsid  # astfel aflăm clusterID
ceph mon dump  # iar așa vom obține adresele IP ale monitorilor

Valorile obținute se vor introduce în fișierul cephrbd.yml. Între timp, activăm crearea politicilor PSP (Pod Security Policies). Opțiunile din secțiunile nodeplugin și provisioner sunt deja în fișier, le putem modifica așa cum este arătat 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

Apoi, tot ce ne rămâne de făcut este să instalăm chart-ul în clusterul Kubernetes.

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

Excelent, driverul RBD funcționează!
Să creăm un nou StorageClass în Kubernetes. Pentru aceasta, va fi necesar să lucrăm puțin cu Ceph.

Creăm un nou utilizator în Ceph și îi dăm permisiuni de scriere în pool-ul kube:

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

Și acum, să vedem cheia de acces acolo unde am lăsat-o:

ceph auth get-key client.rbdkube

Comanda va returna ceva de genul:

AQCO9NJbhYipKRAAMqZsnqqS/T8OYQX20xIa9A==

Vom transmitem această valoare în Secretul din clusterul Kubernetes — acolo unde este necesară userKey:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-rbd-secret
  namespace: ceph-csi-rbd
stringData:
  # Valorile cheilor corespund numelui de utilizator și cheii acestuia, așa cum este indicat în
  # clusterul Ceph. ID-ul utilizatorului trebuie să aibă acces la pool-ul,
  # specificat în clasa de stocare
  userID: rbdkube
  userKey:

Și creăm secretul nostru:

kubectl apply -f secret.yaml

Apoi avem nevoie de un manifest StorageClass de genul:

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

   imageFeatures: layering

   # Aceste secrete trebuie să conțină date pentru autorizare
   # în pool-ul dvs.
   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 aflat deja cu comanda ceph fsid, și aplicăm acest manifest în clusterul Kubernetes:

kubectl apply -f storageclass.yaml

Pentru a verifica funcționarea clusterelor împreună, voi crea un astfel de PVC (Persistent Volume Claim):

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

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

kubectl get pvc
kubectl get pv

Se pare că totul este în regulă! Cum arată din partea Ceph?
Obținem lista volumelor din pool și vizualizăm informațiile despre volumul nostru:

rbd ls -p kube
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653  # aici, evident, va fi un alt ID al volumului, generat de comanda anterioară

Acum să vedem cum funcționează modificarea dimensiunii volumului RBD.
Schimbăm dimensiunea volumului în manifestul pvc.yaml la 2Gi și îl aplicăm:

kubectl apply -f pvc.yaml

Să așteptăm să intre în vigoare modificările și să verificăm din nou 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 modificat. Pentru a afla motivul, putem solicita descrierea PVC-ului de la Kubernetes în format YAML:

kubectl get pvc rbd-pvc -o yaml

Iată și problema:

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

Așa că discul s-a mărit, dar sistemul de fișiere de pe acesta nu.
Pentru a extinde sistemul de fișiere, trebuie să montăm volumul. PVC-ul/PV-ul nostru creat nu este utilizat acum în niciun fel.

Putem crea un Pod de test, 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 modificat, totul este în regulă.

În prima parte am lucrat cu un dispozitiv de blocare RBD (care se referă la Rados Block Device), dar nu este bine să procedăm astfel dacă se dorește acces simultan la acest disc din partea diferitelor microservicii. Pentru a lucra cu fișiere, mai degrabă decât cu o imagine de disc, CephFS este mult mai potrivit.
Pe baza clusterelor Ceph și Kubernetes, vom configura CSI și celelalte entități necesare pentru a lucra cu CephFS.

Vom obține valorile din noul Helm chart de care avem nevoie:

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

Din nou, trebuie să completăm fișierul cephfs.yml. Așa cum am mai văzut, comenzile Ceph ne vor ajuta:

ceph fsid
ceph mon dump

Completăm fișierul cu valorile aproximativ astfel:

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

Rețineți că adresele monitorilor sunt specificate într-o formă simplă address:port. Pentru a monta cephfs pe nod, aceste adrese sunt transmise modulului kernel, care încă nu poate lucra cu protocolul monitorilor v2.
Portul pentru httpMetrics (unde Prometheus va obține metricile pentru monitorizare) este schimbat pentru a nu intra în conflict cu nginx-proxy, care este instalat de Kubespray. Aceasta, poate, nu va fi necesar pentru dvs.

Instalăm Helm chart-ul în clusterul Kubernetes:

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

Trecem la stocarea datelor Ceph pentru a crea un utilizator separat. În documentație se menționează că provisioner-ului CephFS îi sunt necesare privilegii de acces de administrator al clusterului. 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 imediat vom verifica cheia de acces, de care ne va fi nevoie mai departe:

ceph auth get-key client.fs

Vom crea un Secret și un StorageClass separate.
Nimic nou, am văzut deja acest lucru pe baza RBD:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-cephfs-secret
  namespace: ceph-csi-cephfs
stringData:
  # Necesitate pentru volumele create dinamic
  adminID: fs
  adminKey:

Aplicăm manifestul:

kubectl apply -f secret.yaml

Iar acum – un StorageClass separat:

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

  # Numele sistemului de fișiere CephFS în care va fi creat volum
  fsName: cephfs

  # (opțional) Pool-ul Ceph în care vor fi stocate datele volumului
  # pool: cephfs_data

  # (opțional) Opțiuni de montare separate prin virgulă pentru Ceph-fuse
  # de exemplu:
  # fuseMountOptions: debug

  # (opțional) Opțiuni de montare CephFS pentru kernel, separate prin virgulă
  # Consultați man mount.ceph pentru lista acestor opțiuni. De exemplu:
  # kernelMountOptions: readdir_max_bytes=1048576,norbytes

  # Secretele trebuie să conțină acces pentru administrator și/sau utilizatorul 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

  # (opțional) Driverul poate folosi fie ceph-fuse (fuse), 
  # fie ceph kernelclient (kernel).
  # Dacă nu este specificat, se va utiliza montarea volumelor implicit,
  # aceasta fiind definită prin căutarea ceph-fuse și mount.ceph
  # mounter: kernel
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
  - debug

Vom completa aici clusterID și vom aplica în Kubernetes:

kubectl apply -f storageclass.yaml

Verificare

Pentru a verifica, la fel ca în exemplul anterior, vom crea un PVC:

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

Și vom verifica prezența PVC/PV:

kubectl get pvc
kubectl get pv

Dacă doriți să vedeți fișierele și directoarele din CephFS, puteți monta acest sistem de fișiere undeva. De exemplu, așa cum este prezentat mai jos.

Să ne ducem pe unul dintre nodurile clusterului Ceph și să executăm aceste 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, o astfel de montare FS pe un nod Ceph este exclusiv pentru scopuri de învățare, ceea ce facem la cursurile noastre Slurm. Nu cred că cineva ar face asta în producție, riscul de a șterge accidental fișiere importante este mare.

Și, în cele din urmă, să verificăm cum stau lucrurile cu schimbarea dimensiunii volumului în cazul CephFS. Ne întoarcem în Kubernetes și edităm manifestul nostru pentru PVC — vom crește dimensiunea, de exemplu, la 7Gi.

Vom aplica fișierul editat:

kubectl apply -f pvc.yaml

Să vedem în directorul montat cum s-a schimbat limita:

getfattr -n ceph.quota.max_bytes

Pentru a rula această comandă, este posibil să trebuiască să instalați în sistem pachetul attr.

Ochiul se teme, dar mâinile fac

La prima vedere, toate aceste incantații și lungi manifeste YAML par complicate, dar în practică, studenții de la Slyrm se descurcă destul de repede cu ele.
În acest articol nu ne-am aprofundat în detalii — pentru asta există documentația oficială. Dacă sunteți interesat de detaliile configurării stocării Ceph împreună cu clusterul Kubernetes, aceste linkuri vă vor ajuta:

Principiile generale de funcționare ale Kubernetes cu volume
Documentația RBD
Integrarea RBD și Kubernetes din perspectiva Ceph
Integrarea RBD și Kubernetes din perspectiva CSI
Documentația generală pentru CephFS
Integrarea CephFS și Kubernetes din perspectiva CSI

În cursul Slyrm Kubernetes Baza puteți merge puțin mai departe și desfășura o aplicație reală în Kubernetes care va folosi CephFS ca stocare pentru fișiere. Prin intermediul cererilor GET/POST, veți putea trimite și primi fișiere din Ceph.

Și dacă sunteți mai interesat de stocarea datelor, atunci înscrieți-vă la cursul nou despre Ceph. În timp ce cursul este în testare beta, acesta poate fi obținut cu o reducere și aveți ocazia să influențați conținutul său.

Autorul articolului: Alexander Shvalov, inginer practician Southbridge, Administrator Kubernetes Certificat, autor și dezvoltator de cursuri Slyrm.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster