Esempio pratico per connettere uno storage basato su Ceph a un cluster Kubernetes

Container Storage Interface (CSI) è un'interfaccia unificata per l'interazione tra Kubernetes e i sistemi di storage. Ne abbiamo già parlato brevemente parlavano, e oggi esamineremo più in dettaglio l'integrazione di CSI e Ceph: mostreremo come collegare lo storage Ceph al cluster Kubernetes.
L'articolo presenta esempi reali, sebbene un po' semplificati per una migliore comprensione. Non tratteremo l'installazione e la configurazione dei cluster Ceph e Kubernetes.

Ti interessa sapere come funziona?

Esempio pratico per connettere uno storage basato su Ceph a un cluster Kubernetes

Quindi, hai a disposizione un cluster Kubernetes già distribuito, per esempio, kubespray. Accanto a esso opera un cluster Ceph, che può essere anche installato, ad esempio, con questo set di playbook. Spero che non sia necessario menzionare che per l'ambiente di produzione deve esserci una rete con una larghezza di banda di almeno 10 Gbit/s.

Se hai tutto questo, andiamo!

Innanzitutto, accediamo a uno dei nodi del cluster Ceph e verifichiamo che tutto sia a posto:

ceph health
ceph -s

Successivamente creiamo un pool per i dischi RBD:

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

Passiamo al cluster Kubernetes. Lì installeremo prima il driver Ceph CSI per RBD. Lo installeremo come da prassi, tramite Helm.
Aggiungiamo il repository con il chart, otteniamo un insieme di variabili del chart ceph-csi-rbd:

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

Ora dobbiamo compilare il file cephrbd.yml. Per fare ciò, scopriamo l'ID del cluster e gli indirizzi IP dei monitor in Ceph:

ceph fsid  # così scopriamo il clusterID
ceph mon dump  # e così vediamo gli indirizzi IP dei monitor

Annotiamo i valori ottenuti nel file cephrbd.yml. Durante questo, abilitiamo la creazione delle politiche PSP (Pod Security Policies). Le opzioni nelle sezioni nodeplugin e provisioner sono già nel file, possono essere modificate come mostrato di seguito:

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

Poi tutto ciò che ci resta è installare il chart nel cluster Kubernetes.

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

Ottimo, il driver RBD funziona!
Creiamo un nuovo StorageClass in Kubernetes. Per questo avremo di nuovo bisogno di lavorare un po' con Ceph.

Creiamo un nuovo utente in Ceph e gli concediamo i diritti di scrittura nel pool kube:

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

E ora vediamo la chiave di accesso tutto lì:

ceph auth get-key client.rbdkube

Il comando restituirà qualcosa di simile:

AQCO9NJbhYipKRAAMqZsnqqS/T8OYQX20xIa9A==

Registriamo questo valore nel Secret nel cluster Kubernetes — dove necessario userKey:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-rbd-secret
  namespace: ceph-csi-rbd
stringData:
  # I valori delle chiavi corrispondono al nome utente e alla sua chiave, come specificato in
  # nel cluster Ceph. L'ID utente deve avere accesso al pool,
  # specificato nella classe di storage
  userID: rbdkube
  userKey:

E creiamo il nostro segreto:

kubectl apply -f secret.yaml

Ora abbiamo bisogno di un manifesto StorageClass simile a questo:

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

   imageFeatures: layering

   # Questi segreti devono contenere dati per l'autenticazione
   # nel tuo pool.
   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

Deve essere compilato clusterID, che abbiamo già appreso con il comando ceph fsid, e applicare questo manifesto nel cluster Kubernetes:

kubectl apply -f storageclass.yaml

Per verificare il funzionamento dei cluster insieme, creiamo un PVC (Persistent Volume Claim) di questo tipo:

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

Vediamo subito come Kubernetes ha creato il volume richiesto in Ceph:

kubectl get pvc
kubectl get pv

Sembra tutto a posto! E come si presenta dal lato di Ceph?
Otteniamo l'elenco dei volumi nel pool e controlliamo le informazioni sul nostro volume:

rbd ls -p kube
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653  # qui, ovviamente, ci sarà un altro ID volume fornito dal comando precedente

Ora vediamo come funziona il ridimensionamento del volume RBD.
Modifichiamo la dimensione del volume nel manifesto pvc.yaml a 2Gi e lo applichiamo:

kubectl apply -f pvc.yaml

Aspettiamo che le modifiche abbiano effetto e rivediamo la dimensione del volume.

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

kubectl get pv
kubectl get pvc

Vediamo che la dimensione del PVC non è cambiata. Per scoprire il motivo, possiamo richiedere a Kubernetes la descrizione del PVC in formato YAML:

kubectl get pvc rbd-pvc -o yaml

Ecco il problema:

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

Quindi, il disco è stato aumentato, ma il file system su di esso no.
Per aumentare il file system, è necessario montare il volume. Attualmente, il nostro PVC/PV creato non è utilizzato in alcun modo.

Possiamo creare un Pod di prova, ad esempio in questo modo:

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

E ora diamo un'occhiata al PVC:

kubectl get pvc

La dimensione è cambiata, tutto va bene.

Nella prima parte abbiamo lavorato con il dispositivo di blocco RBD (che sta per Rados Block Device), ma non è possibile farlo se diversi microservizi devono accedere a questo disco contemporaneamente. Per lavorare con file, e non con un'immagine del disco, CephFS è molto più adatto.
Utilizzando i cluster Ceph e Kubernetes, configureremo CSI e tutte le altre entità necessarie per lavorare con CephFS.

Ottenendo i valori dal nuovo Helm chart che ci interessa:

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

Dobbiamo nuovamente completare il file cephfs.yml. Come prima, ci aiuteranno i comandi Ceph:

ceph fsid
ceph mon dump

Compiliamo il file con i valori in questo modo:

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

Si prega di notare che gli indirizzi dei monitor sono forniti nella forma semplice address:port. Per montare cephfs sul nodo, questi indirizzi vengono passati al modulo del kernel, che non è ancora in grado di lavorare con il protocollo dei monitor v2.
Cambiamo la porta per httpMetrics (da cui Prometheus raccoglierà le metriche per il monitoraggio) affinché non confligga con il nginx-proxy, che viene installato da Kubespray. Potreste non averne bisogno.

Installiamo il chart Helm nel cluster Kubernetes:

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

Passiamo allo storage di dati Ceph per creare un utente separato. La documentazione indica che il provisioning di CephFS richiede diritti di accesso da amministratore del cluster. Ma creeremo un utente separato fs con diritti limitati:

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'

E subito vediamo la sua chiave di accesso, ci servirà in seguito:

ceph auth get-key client.fs

Creiamo un Secret e uno StorageClass separati.
Niente di nuovo, lo abbiamo già visto con l'esempio RBD:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-cephfs-secret
  namespace: ceph-csi-cephfs
stringData:
  # Necessario per i volumi creati dinamicamente
  adminID: fs
  adminKey:

Applichiamo il manifesto:

kubectl apply -f secret.yaml

E ora – una StorageClass separata:

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

  # Nome del file system CephFS in cui verrà creato il volume
  fsName: cephfs

  # (opzionale) Pool Ceph in cui saranno memorizzati i dati del volume
  # pool: cephfs_data

  # (opzionale) Opzioni di montaggio separate da virgole per Ceph-fuse
  # per esempio:
  # fuseMountOptions: debug

  # (opzionale) Opzioni di montaggio CephFS per il kernel, separate da virgole
  # Vedi man mount.ceph per l'elenco di queste opzioni. Per esempio:
  # kernelMountOptions: readdir_max_bytes=1048576,norbytes

  # I segreti devono contenere accessi per l’amministratore e/o l'utente 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

  # (opzionale) Il driver può utilizzare o ceph-fuse (fuse), 
  # o il ceph kernelclient (kernel).
  # Se non specificato, verrà utilizzato il montaggio dei volumi predefiniti,
  # determinato dalla ricerca di ceph-fuse e mount.ceph
  # mounter: kernel
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
  - debug

Compiliamo qui clusterID e applichiamo in Kubernetes:

kubectl apply -f storageclass.yaml

Verifica

Per verificare, come nell'esempio precedente, creiamo un PVC:

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

E controlliamo l'esistenza di PVC/PV:

kubectl get pvc
kubectl get pv

Se si desidera visualizzare file e directory in CephFS, è possibile montare questo file system da qualche parte. Ad esempio, come mostrato di seguito.

Andiamo su uno dei nodi del cluster Ceph e eseguiamo le seguenti azioni:

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

Naturalmente, questo tipo di montaggio FS su un nodo Ceph è adatto esclusivamente per scopi didattici, che è ciò che stiamo facendo nei nostri corsi Slurm. Non credo che qualcuno lo farebbe in produzione, poiché c'è un alto rischio di cancellare accidentalmente file importanti.

Infine, verifichiamo come vanno le cose con la modifica delle dimensioni del volume in CephFS. Torniamo su Kubernetes e modifichiamo il nostro manifesto per PVC — aumentiamo la dimensione, ad esempio, a 7Gi.

Applichiamo il file modificato:

kubectl apply -f pvc.yaml

Controlliamo nella directory montata come è cambiata la quota:

getfattr -n ceph.quota.max_bytes

Per eseguire questo comando, potrebbe essere necessario installare il pacchetto attr.

Gli occhi temono, ma le mani agiscono

A prima vista, tutte queste configurazioni e lunghe manifestazioni YAML possono sembrare complesse, ma nella pratica gli studenti di Slurm le comprendono piuttosto rapidamente.
In questo articolo non ci siamo addentrati nei dettagli — per quello c'è la documentazione ufficiale. Se sei interessato ai dettagli per configurare lo storage Ceph in combinazione con un cluster Kubernetes, queste sono le fonti utili:

Principi generali di funzionamento di Kubernetes con i volumi
Documentazione su RBD
Integrazione RBD e Kubernetes dal punto di vista di Ceph
Integrazione RBD e Kubernetes dal punto di vista di CSI
Documentazione generale su CephFS
Integrazione di CephFS e Kubernetes dal punto di vista di CSI

Nel corso di Slurm Base di Kubernetes puoi andare un po' oltre e implementare un'applicazione reale in Kubernetes che utilizza CephFS come storage per i file. Attraverso richieste GET/POST puoi inviare e ricevere file da Ceph.

E se sei più interessato allo storage dei dati, iscriviti al nuovo corso su Ceph. Durante la fase beta, il corso è disponibile a un prezzo scontato e puoi influenzare il suo contenuto.

Autore dell'articolo: Alexander Shvalov, ingegnere pratico Southbridge, Certified Kubernetes Administrator, autore e sviluppatore dei corsi Slurm.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster