Praktisch voorbeeld van het aansluiten van opslag op basis van Ceph in een Kubernetes-cluster

Container Storage Interface (CSI) is een gestandaardiseerde interface voor de interactie tussen Kubernetes en opslagsystemen. Kort gezegd hebben we het er al over gehad, twee jaar geleden verteld, en in november 2018 gebeurde er een zeer interessante (wat betreft beveiliging) gebeurtenis. Kort samengevat, het team van CyberArk Software Ltd. slaagde erin het te hacken: ze kregen de mogelijkheid om commando's buiten de containers uit te voeren, d.w.z. op het host-systeem. Een prachtige illustratie van het beveiligingsprobleem in Docker, nietwaar? Over alle details van wat er gebeurde, lees je, en vandaag bekijken we in detail de combinatie van CSI en Ceph: we laten zien hoe je Ceph-opslag aan een Kubernetes-cluster kunt koppelen.
De artikelen bevatten echte, zij het iets vereenvoudigde voorbeelden voor een betere begrijpelijkheid. We bespreken de installatie en configuratie van Ceph- en Kubernetes-clusters niet.

Ben je benieuwd hoe het werkt?

Praktisch voorbeeld van het aansluiten van opslag op basis van Ceph in een Kubernetes-cluster

Dus, je hebt een Kubernetes-cluster bij de hand, bijvoorbeeld, kubespray. Daarnaast draait er een Ceph-cluster - dat kan ook worden geïnstalleerd, bijvoorbeeld met dit set van playbooks. Hopelijk is het niet nodig om te vermelden dat er voor productie tussen hen een netwerk moet zijn met een bandbreedte van minimaal 10 Gb/s.

Als je dat allemaal hebt, laten we beginnen!

Laten we eerst een van de knooppunten van het Ceph-cluster bezoeken en controleren of alles in orde is:

ceph health
ceph -s

Vervolgens maken we hier een pool voor de RBD-schijven aan:

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

We gaan naar het Kubernetes-cluster. Daar installeren we eerst de Ceph CSI-driver voor RBD. We zullen dit op de juiste manier via Helm doen.
Laten we de repository met de chart toevoegen en pakken het pakket met variabelen voor de 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

Nu moeten we het bestand cephrbd.yml invullen. Hiervoor achterhalen we de cluster-ID en de IP-adressen van de monitoren in Ceph:

ceph fsid  # zo vinden we clusterID
ceph mon dump  # en zo zien we de IP-adressen van de monitoren

De verkregen waarden plaatsen we in het bestand cephrbd.yml. Tussendoor activeren we de creatie van PSP (Pod Security Policies). De opties in de secties nodeplugin en provisioner zijn al in het bestand aanwezig; ze kunnen worden aangepast zoals hieronder wordt weergegeven:

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

Het enige wat we nog hoeven te doen, is de chart in het Kubernetes-cluster installeren.

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

Geweldig, de RBD-driver werkt!
Laten we een nieuwe StorageClass aanmaken in Kubernetes. Hiervoor moeten we opnieuw wat werk verrichten met Ceph.

We creëren een nieuwe gebruiker in Ceph en geven deze schrijfrechten op de pool kube:

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

Laten we nu de toegangssleutel daar bekijken:

ceph auth get-key client.rbdkube

De opdracht zal iets dergelijks opleveren:

AQCO9NJbhYipKRAAMqZsnqqS/T8OYQX20xIa9A==

We plaatsen deze waarde in een Secret in het Kubernetes-cluster — daar waar nodig userKey:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-rbd-secret
  namespace: ceph-csi-rbd
stringData:
  # De sleutelwaarden komen overeen met de gebruikersnaam en de bijbehorende sleutel, zoals opgegeven in
  # de Ceph-cluster. De gebruikers-ID moet toegang hebben tot de pool,
  # zoals opgegeven in de opslagklasse
  userID: rbdkube
  userKey:

En we maken onze secret aan:

kubectl apply -f secret.yaml

Vervolgens hebben we ongeveer zo'n manifest voor de StorageClass nodig:

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

   imageFeatures: layering

   # Deze secrets moeten gegevens voor authenticatie bevatten
   # naar uw 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

Moet worden ingevuld clusterID, dat we al hebben ontdekt met het commando ceph fsid, en pas dit manifest toe in het Kubernetes-cluster:

kubectl apply -f storageclass.yaml

Om te controleren of de clusters goed samenwerken, maken we de volgende PVC (Persistent Volume Claim):

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

Laten we meteen kijken hoe Kubernetes de aangevraagde volume in Ceph heeft aangemaakt:

kubectl get pvc
kubectl get pv

Alles ziet er goed uit! En hoe ziet het eruit aan de Ceph-kant?
Laten we een lijst van volumes in de pool ophalen en de informatie over ons volume bekijken:

rbd ls -p kube
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653  # hier zal natuurlijk een andere volume-ID worden getoond, die door het vorige commando werd gegeven

Laten we nu eens kijken hoe de grootte van het RBD-volume kan worden aangepast.
Pas de grootte van het volume in het manifest pvc.yaml aan naar 2Gi en pas het toe:

kubectl apply -f pvc.yaml

Laten we wachten totdat de wijzigingen zijn doorgevoerd en laten we nog eens naar de grootte van het volume kijken.

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

kubectl get pv
kubectl get pvc

We zien dat de grootte van de PVC niet is gewijzigd. Om de reden te achterhalen, kunnen we Kubernetes vragen om de beschrijving van de PVC in YAML-indeling op te vragen:

kubectl get pvc rbd-pvc -o yaml

En hier is het probleem:

message: Wachten tot de gebruiker een pod (her)start om de schijfgrootte op de knoop af te ronden. type: FileSystemResizePending

Dat wil zeggen, de schijf is vergroot, maar het bestandssysteem erop is dat niet.
Om het bestandssysteem te vergroten, moet het volume worden aangekoppeld. Onze gemaakte PVC/PV wordt momenteel op geen enkele manier gebruikt.

We kunnen een test-Pod aanmaken, bijvoorbeeld zo:

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

Laten we nu naar de PVC kijken:

kubectl get pvc

De grootte is veranderd, alles is in orde.

In het eerste deel hebben we gewerkt met het blokapparaat RBD (wat staat voor Rados Block Device), maar dit is niet mogelijk als meerdere microservices gelijktijdig toegang tot deze schijf nodig hebben. Voor het werken met bestanden in plaats van een schijfafbeelding is CephFS veel beter geschikt.
We zullen een installatie van CSI en andere benodigde entiteiten voor CephFS configureren op basis van Ceph- en Kubernetes-clusters.

We halen de waarden uit de gewenste nieuwe Helm-chart:

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

We moeten opnieuw het bestand cephfs.yml invullen. Zoals eerder, kunnen de Ceph-commando's hierbij helpen:

ceph fsid
ceph mon dump

We vullen het waardenbestand ongeveer zo in:

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

Let op dat de adressen van de monitors in de eenvoudige vorm address:port worden opgegeven. Voor het koppelen van cephfs op de knooppunt worden deze adressen doorgegeven aan de kernelmodule, die nog niet met het v2 monitorprotocol kan werken.
We wijzigen de poort voor httpMetrics (waar Prometheus metrics voor monitoring zal ophalen) zodat deze niet in conflict komt met de nginx-proxy die door Kubespray wordt geïnstalleerd. U heeft dit mogelijk niet nodig.

We installeren de Helm-chart in het Kubernetes-cluster:

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

We gaan naar de Ceph-opslag om daar een aparte gebruiker aan te maken. In de documentatie staat dat de CephFS-provisioner beheerdersrechten voor het cluster nodig heeft. Maar we zullen een aparte gebruiker aanmaken fs met beperkte rechten:

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'

En laten we meteen zijn toegangsgegevens bekijken, die we later nodig zullen hebben:

ceph auth get-key client.fs

We zullen aparte Secret en StorageClass aanmaken.
Niets nieuws, we hebben dit al gezien met het RBD-voorbeeld:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-cephfs-secret
  namespace: ceph-csi-cephfs
stringData:
  # Vereist voor dynamisch gemaakte volumes
  adminID: fs
  adminKey:

We passen de manifest toe:

kubectl apply -f secret.yaml

En nu – een aparte StorageClass:

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

  # De naam van het CephFS-bestandssysteem waarin de volume zal worden aangemaakt
  fsName: cephfs

  # (optioneel) De Ceph-pool waarin de gegevens van het volume worden opgeslagen
  # pool: cephfs_data

  # (optioneel) Door komma's gescheiden montagopties voor Ceph-fuse
  # bijvoorbeeld:
  # fuseMountOptions: debug

  # (optioneel) Door komma's gescheiden montagopties voor CephFS voor de kernel
  # Zie man mount.ceph voor een lijst van deze opties. Bijvoorbeeld:
  # kernelMountOptions: readdir_max_bytes=1048576,norbytes

  # Secrets moeten toegang bevatten voor de admin en/of gebruiker van 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

  # (optioneel) De driver kan ofwel ceph-fuse (fuse) gebruiken,
  # ofwel ceph kernelclient (kernel).
  # Als niet opgegeven, wordt de standaard volume mounting gebruikt,
  # die wordt bepaald door ceph-fuse en mount.ceph
  # mounter: kernel
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
  - debug

Laten we dit invullen clusterID en toepassen in Kubernetes:

kubectl apply -f storageclass.yaml

Controle

Om te controleren, zoals in het vorige voorbeeld, creëren we een PVC:

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

En we controleren de aanwezigheid van PVC/PV:

kubectl get pvc
kubectl get pv

Als je de bestanden en mappen in CephFS wilt bekijken, kun je dit bestandssysteem ergens monteren. Bijvoorbeeld, zoals hieronder weergegeven.

Laten we naar een van de knooppunten van de Ceph-cluster gaan en de volgende stappen uitvoeren:

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

Natuurlijk is het monteren van een FS op een Ceph-knooppunt uitsluitend geschikt voor opleidingsdoeleinden, wat we ook doen in onze Slurm-cursussen. Ik denk niet dat iemand dit in productie zal doen, er is een groot risico om belangrijke bestanden per ongeluk te overschrijven.

En tot slot, laten we controleren hoe het zit met de wijziging van de volumematen in het geval van CephFS. We keren terug naar Kubernetes en bewerken ons manifest voor de PVC — bijvoorbeeld, we verhogen de grootte naar 7Gi.

Toepassen van het bewerkte bestand:

kubectl apply -f pvc.yaml

Laten we kijken naar de gemonteerde map en hoe het quotum is veranderd:

getfattr -n ceph.quota.max_bytes

Voor het uitvoeren van deze opdracht moet je mogelijk het pakket installeren in het systeem attr.

De ogen zijn bang, maar de handen doen

Hoewel al deze toverspreuken en lange YAML-manifesten moeilijk lijken, begrijpen de Slurm-studenten ze in de praktijk vrij snel.
In dit artikel zijn we niet diep op de materie ingegaan — daarvoor is er de officiële documentatie. Als je geïnteresseerd bent in de details van het instellen van Ceph-opslag samen met een Kubernetes-cluster, kunnen deze links helpen:

Algemene principes van Kubernetes met volumes
Documentatie over RBD
Integratie van RBD en Kubernetes vanuit het perspectief van Ceph
Integratie van RBD en Kubernetes vanuit het perspectief van CSI
Algemene documentatie over CephFS
Integratie van CephFS en Kubernetes vanuit het perspectief van CSI

Op de Slurm-cursus Kubernetes Basis kun je nog een stap verder gaan en een echte applicatie in Kubernetes uitrollen die CephFS als opslag voor bestanden gebruikt. Via GET/POST-aanvragen kun je bestanden verzenden en ontvangen uit Ceph.

Als je meer geïnteresseerd bent in gegevensopslag, schrijf je dan in voor een nieuwe cursus over Ceph. Tijdens de bètatest is de cursus met korting beschikbaar en kun je invloed uitoefenen op de inhoud.

Auteur van het artikel: Alexander Shvalov, praktiserend ingenieur Southbridge, Certified Kubernetes Administrator, auteur en ontwikkelaar van Slurm-cursussen.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster