Das Container Storage Interface (CSI) ist ein einheitlicher Schnittstellenstandard für die Interaktion zwischen Kubernetes und Speichersystemen. Wir haben bereits kurz darüber gesprochen, , und heute betrachten wir genauer die Verbindung zwischen CSI und Ceph: wir zeigen, wie man zum Kubernetes-Cluster hinzufügt.
Der Artikel enthält einige reale, wenn auch etwas vereinfachte Beispiele zur besseren Verständlichkeit. Informationen zur Installation und Konfiguration von Ceph- und Kubernetes-Clustern werden hier nicht behandelt.
Interessiert es Sie, wie das funktioniert?

Also haben Sie einen Kubernetes-Cluster, der beispielsweise mit bereits eingerichtet wurde. Nebenan läuft ein Ceph-Cluster, das man ebenfalls mit diesem einrichten kann. Ich hoffe, es muss nicht erwähnt werden, dass zwischen ihnen ein Netzwerk mit einer Bandbreite von mindestens 10 Gbit/s bestehen muss.
Wenn Sie all das haben, legen wir los!
Zuerst melden wir uns an einem der Knoten des Ceph-Clusters an und überprüfen, ob alles in Ordnung ist:
ceph health
ceph -sDann erstellen wir sofort einen Pool für RBD-Disketten:
ceph osd pool create kube 32
ceph osd pool application enable kube rbdGehen wir zum Kubernetes-Cluster. Dort installieren wir zunächst den Ceph CSI-Treiber für RBD. Wir werden es, wie es sich gehört, über Helm installieren.
Wir fügen das Repository mit dem Chart hinzu und erhalten eine Reihe von Variablen für das Chart ceph-csi-rbd:
helm repo add ceph-csi https://ceph.github.io/csi-charts
helm inspect values ceph-csi/ceph-csi-rbd > cephrbd.ymlJetzt müssen wir die Datei cephrbd.yml ausfüllen. Dafür holen wir uns die Cluster-ID und die IP-Adressen der Monitore in Ceph:
ceph fsid # so erfahren wir die clusterID
ceph mon dump # und hier sehen wir die IP-Adressen der MonitoreDie ermittelten Werte tragen wir in die Datei cephrbd.yml ein. Gleichzeitig aktivieren wir die Erstellung von PSPs (Pod Security Policies). Die Optionen in den Abschnitten nodeplugin und provisioner sind bereits in der Datei vorhanden und können wie folgt geändert werden:
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: trueDanach bleibt uns nur zu tun — das Chart im Kubernetes-Cluster installieren.
helm upgrade -i ceph-csi-rbd ceph-csi/ceph-csi-rbd -f cephrbd.yml -n ceph-csi-rbd --create-namespaceAusgezeichnet, der RBD-Treiber funktioniert!
Lassen Sie uns eine neue StorageClass in Kubernetes erstellen. Dazu müssen wir wieder etwas mit Ceph arbeiten.
Wir erstellen einen neuen Benutzer in Ceph und gewähren ihm Schreibrechte für den Pool kube:
ceph auth get-or-create client.rbdkube mon 'profile rbd' osd 'profile rbd pool=kube'Und nun schauen wir uns den Zugriffsschlüssel dort an:
ceph auth get-key client.rbdkubeDer Befehl wird etwas Ähnliches ausgeben:
AQCO9NJbhYipKRAAMqZsnqqS/T8OYQX20xIa9A==Wir tragen diesen Wert in einen Secret im Kubernetes-Cluster ein — dorthin, wo er benötigt wird. userKey:
---
apiVersion: v1
kind: Secret
metadata:
name: csi-rbd-secret
namespace: ceph-csi-rbd
stringData:
# Die Schlüsselwerte entsprechen dem Benutzernamen und dessen Schlüssel, wie im
# Ceph-Cluster angegeben. Die ID des Benutzers muss Zugriffsrechte auf den Pool haben,
# der in der Storage Class angegeben ist.
userID: rbdkube
userKey:Und wir erstellen unser Geheimnis:
kubectl apply -f secret.yamlWir benötigen als Nächstes ein ungefähr solches Manifest für die StorageClass:
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
clusterID:
pool: kube
imageFeatures: layering
# Diese Geheimnisse müssen Daten für die Authentifizierung
# in Ihren Pool enthalten.
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:
- discardMuss ausgefüllt werden: clusterID, den wir bereits mit dem Befehl ceph fsid, und wenden dieses Manifest im Kubernetes-Cluster an:
kubectl apply -f storageclass.yamlUm die Funktionalität der Cluster in Verbindung zu überprüfen, erstellen wir diesen PVC (Persistent Volume Claim):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: csi-rbd-scSchauen wir uns sofort an, wie Kubernetes in Ceph das angeforderte Volume erstellt hat:
kubectl get pvc
kubectl get pvSieht gut aus! Und wie sieht es auf der Ceph-Seite aus?
Wir holen uns eine Liste der Volumes im Pool und sehen die Informationen zu unserem Volume an:
rbd ls -p kube
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653 # hier wird natürlich eine andere ID des Volumes angezeigt, die von dem vorherigen Befehl ausgegeben wurde.Jetzt schauen wir uns an, wie die Größe des RBD-Volumes verändert wird.
Wir ändern die Größe des Volumes im Manifest pvc.yaml auf 2Gi und wenden es an:
kubectl apply -f pvc.yamlWarten wir, bis die Änderungen wirksam werden, und sehen wir uns erneut die Größe des Volumes an.
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653
kubectl get pv
kubectl get pvcWir sehen, dass die Größe des PVC unverändert geblieben ist. Um den Grund herauszufinden, können wir Kubernetes auffordern, die Beschreibung des PVC im YAML-Format abzurufen:
kubectl get pvc rbd-pvc -o yamlUnd hier ist das Problem:
message: Warten auf den Benutzer, um einen Pod (neu) zu starten, um die Größenänderung des Dateisystems des Volumes auf dem Knoten abzuschließen. type: FileSystemResizePending
Das bedeutet, die Disk wurde vergrößert, aber das Dateisystem darauf — nicht.
Um das Dateisystem zu vergrößern, muss das Volume gemountet werden. Unser erstellter PVC/PV wird zurzeit jedoch nicht genutzt.
Wir können einen Test-Pod erstellen, zum Beispiel so:
---
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: falseUnd jetzt schauen wir uns das PVC an:
kubectl get pvcDie Größe hat sich geändert, alles in Ordnung.
Im ersten Teil haben wir mit dem Blockgerät RBD gearbeitet (was auch für Rados Block Device steht), aber das ist nicht möglich, wenn verschiedene Mikrodienste gleichzeitig auf dieses Laufwerk zugreifen sollen. Für die Arbeit mit Dateien, und nicht mit einem Abbild des Laufwerks, ist CephFS viel besser geeignet.
Anhand von Ceph- und Kubernetes-Clustern richten wir CSI und andere erforderliche Entitäten für die Arbeit mit CephFS ein.
Wir erhalten die Werte aus dem benötigten neuen Helm-Chart:
helm inspect values ceph-csi/ceph-csi-cephfs > cephfs.ymlWieder müssen wir die Datei cephfs.yml ausfüllen. Wie zuvor helfen uns die Ceph-Befehle:
ceph fsid
ceph mon dumpDas Ausfüllen der Datei mit Werten sieht ungefähr so aus:
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: trueBitte beachten Sie, dass die Adressen der Monitore in einfacher Form address:port angegeben werden. Für das Einhängen von cephfs auf dem Knoten werden diese Adressen an das Kernel-Modul übergeben, das noch nicht mit dem v2-Monitorprotokoll umgehen kann.
Den Port für httpMetrics (woher Prometheus Metriken für das Monitoring abruft) ändern wir, um Konflikte mit dem nginx-proxy zu vermeiden, der von Kubespray installiert wird. Möglicherweise benötigen Sie das nicht.
Wir installieren das Helm-Chart im Kubernetes-Cluster:
helm upgrade -i ceph-csi-cephfs ceph-csi/ceph-csi-cephfs -f cephfs.yml -n ceph-csi-cephfs --create-namespaceWir wechseln zum Ceph-Datenspeicher, um dort einen separaten Benutzer zu erstellen. In der Dokumentation heißt es, dass der Provisionierer für CephFS Administratorrechte im Cluster benötigt. Aber wir werden einen separaten Benutzer erstellen fs mit eingeschränkten 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'Und wir sehen uns sofort seinen Zugriffsschlüssel an, der uns später nützlich sein wird:
ceph auth get-key client.fsWir erstellen separate Secret und StorageClass.
Nichts Neues, das haben wir bereits am Beispiel von RBD gesehen:
---
apiVersion: v1
kind: Secret
metadata:
name: csi-cephfs-secret
namespace: ceph-csi-cephfs
stringData:
# Notwendig für dynamisch erstellte Volumes
adminID: fs
adminKey:Wir wenden das Manifest an:
kubectl apply -f secret.yamlUnd jetzt – eine separate StorageClass:
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-cephfs-sc
provisioner: cephfs.csi.ceph.com
parameters:
clusterID:
# Name des CephFS-Dateisystems, in dem das Volume erstellt wird
fsName: cephfs
# (optional) Ceph-Pool, in dem die Daten des Volumes gespeichert werden
# pool: cephfs_data
# (optional) Durch Kommas getrennte Mount-Optionen für Ceph-fuse
# z. B.:
# fuseMountOptions: debug
# (optional) Durch Kommas getrennte Mount-Optionen für das CephFS-Kernel
# Siehe man mount.ceph für die Liste dieser Optionen. Zum Beispiel:
# kernelMountOptions: readdir_max_bytes=1048576,norbytes
# Die Geheimnisse müssen Zugangsdaten für den Administrator und/oder Benutzer von Ceph enthalten.
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
# (optional) Der Treiber kann entweder ceph-fuse (fuse) oder den Ceph-Kernelclient (kernel) verwenden.
# Wenn nichts angegeben ist, wird die standardmäßige Volume-Montierung verwendet,
# dies wird durch die Suche nach ceph-fuse und mount.ceph bestimmt.
# mounter: kernel
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
- debugWir fügen hier etwas hinzu clusterID und wenden es in Kubernetes an:
kubectl apply -f storageclass.yamlÜberprüfung
Zur Überprüfung, wie im vorherigen Beispiel, erstellen wir ein PVC:
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: csi-cephfs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
storageClassName: csi-cephfs-scUnd wir überprüfen das Vorhandensein von PVC/PV:
kubectl get pvc
kubectl get pvWenn Sie die Dateien und Verzeichnisse in CephFS ansehen möchten, können Sie dieses Dateisystem irgendwo einhängen. Zum Beispiel, wie unten gezeigt.
Gehen wir zu einem der Knoten im Ceph-Cluster und führen wir folgende Schritte aus:
# Точка монтирования
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/cephfsNatürlich ist solch eine FS-Montage auf einem Ceph-Knoten ausschließlich zu Ausbildungszwecken geeignet, was wir auch in unseren . Ich denke nicht, dass das jemand in der Produktion machen würde, da die Gefahr besteht, wichtige Dateien versehentlich zu überschreiben.
Und schließlich wollen wir überprüfen, wie es bei CephFS mit der Größenänderung des Volumes aussieht. Kehren wir zu Kubernetes zurück und bearbeiten wir unser Manifest für PVC – wir erhöhen die Größe beispielsweise auf 7Gi.
Wenden Sie die bearbeitete Datei an:
kubectl apply -f pvc.yamlSehen wir uns im montierten Verzeichnis an, wie sich das Kontingent geändert hat:
getfattr -n ceph.quota.max_bytesUm diesen Befehl auszuführen, müssen Sie möglicherweise das Paket in Ihrem System installieren attr.
Die Augen haben Angst, aber die Hände machen
Auf den ersten Blick erscheinen all diese Zaubersprüche und langen YAML-Manifeste komplex, aber in der Praxis kommen die Studierenden von Sljorm damit ziemlich schnell zurecht.
In diesem Artikel sind wir nicht ins Detail gegangen – dafür gibt es die offizielle Dokumentation. Wenn Sie an den Einzelheiten der Konfiguration des Ceph-Speichers in Verbindung mit dem Kubernetes-Cluster interessiert sind, helfen Ihnen die folgenden Links:
Im Sljorm-Kurs können Sie noch einen Schritt weiter gehen und eine echte Anwendung in Kubernetes bereitstellen, die CephFS als dateispeicher nutzt. Mithilfe von GET/POST-Anfragen können Sie Dateien übertragen und aus Ceph abrufen.
Und wenn Sie sich mehr für die Datenspeicherung interessieren, melden Sie sich für den an. Während der Beta-Testphase kann der Kurs mit Rabatt erworben werden und Sie können auf dessen Inhalt Einfluss nehmen.
Autor des Artikels: Alexander Schvalov, praktizierender Ingenieur , Certified Kubernetes Administrator, Autor und Entwickler der Sljorm-Kurse.
Quelle: habr.com
