Container Storage Interface (CSI) ist eine einheitliche Schnittstelle zwischen Kubernetes und Speichersystemen. Wir haben bereits kurz darüber gesprochen
Der Artikel enthält reale, wenn auch leicht vereinfachte Beispiele zur leichteren Wahrnehmung. Wir ziehen die Installation und Konfiguration von Ceph- und Kubernetes-Clustern nicht in Betracht.
Sie fragen sich, wie es funktioniert?
Sie haben also einen Kubernetes-Cluster zur Hand, der beispielsweise bereitgestellt wird
Wenn du das alles hast, lass uns gehen!
Gehen wir zunächst zu einem der Ceph-Clusterknoten und prüfen, ob alles in Ordnung ist:
ceph health
ceph -s
Als nächstes erstellen wir sofort einen Pool für RBD-Festplatten:
ceph osd pool create kube 32
ceph osd pool application enable kube rbd
Kommen wir zum Kubernetes-Cluster. Dort installieren wir zunächst den Ceph CSI-Treiber für RBD. Wir werden wie erwartet über Helm installieren.
Wir fügen ein Repository mit einem Diagramm hinzu und erhalten einen Satz Variablen für das ceph-csi-rbd-Diagramm:
helm repo add ceph-csi https://ceph.github.io/csi-charts
helm inspect values ceph-csi/ceph-csi-rbd > cephrbd.yml
Jetzt müssen Sie die Datei cephrbd.yml ausfüllen. Ermitteln Sie dazu die Cluster-ID und IP-Adressen der Monitore in Ceph:
ceph fsid # так мы узнаем clusterID
ceph mon dump # а так увидим IP-адреса мониторов
Die erhaltenen Werte tragen wir in die Datei cephrbd.yml ein. Nebenbei ermöglichen wir die Erstellung von PSP-Richtlinien (Pod Security Policies). Optionen in Abschnitten Nodeplugin и Versorger bereits in der Datei vorhanden sind, können sie wie folgt korrigiert 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: true
Als nächstes müssen wir nur noch das Diagramm im Kubernetes-Cluster installieren.
helm upgrade -i ceph-csi-rbd ceph-csi/ceph-csi-rbd -f cephrbd.yml -n ceph-csi-rbd --create-namespace
Großartig, der RBD-Treiber funktioniert!
Erstellen wir eine neue StorageClass in Kubernetes. Dies erfordert wiederum ein wenig Bastelei mit Ceph.
Wir erstellen einen neuen Benutzer in Ceph und geben ihm Schreibrechte für den Pool Kuppel:
ceph auth get-or-create client.rbdkube mon 'profile rbd' osd 'profile rbd pool=kube'
Sehen wir uns nun an, dass der Zugriffsschlüssel noch vorhanden ist:
ceph auth get-key client.rbdkube
Der Befehl gibt etwa Folgendes aus:
AQCO9NJbhYipKRAAMqZsnqqS/T8OYQX20xIa9A==
Fügen wir diesen Wert zu Secret im Kubernetes-Cluster hinzu – dort, wo wir ihn benötigen userKey:
---
apiVersion: v1
kind: Secret
metadata:
name: csi-rbd-secret
namespace: ceph-csi-rbd
stringData:
# Значения ключей соответствуют имени пользователя и его ключу, как указано в
# кластере Ceph. ID юзера должен иметь доступ к пулу,
# указанному в storage class
userID: rbdkube
userKey: <user-key>
Und wir schaffen unser Geheimnis:
kubectl apply -f secret.yaml
Als nächstes benötigen wir ein StorageClass-Manifest, etwa so:
---
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
Muss ausgefüllt werden Cluster-ID, was wir vom Team bereits gelernt haben ceph fsid, und wenden Sie dieses Manifest auf den Kubernetes-Cluster an:
kubectl apply -f storageclass.yaml
Um zu überprüfen, wie die Cluster zusammenarbeiten, erstellen wir den folgenden PVC (Persistent Volume Claim):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: csi-rbd-sc
Sehen wir uns gleich an, wie Kubernetes das angeforderte Volume in Ceph erstellt hat:
kubectl get pvc
kubectl get pv
Alles scheint großartig zu sein! Wie sieht das auf der Ceph-Seite aus?
Wir erhalten eine Liste der Volumes im Pool und sehen Informationen zu unserem Volume:
rbd ls -p kube
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653 # тут, конечно же, будет другой ID тома, который выдала предыдущая команда
Sehen wir uns nun an, wie die Größenänderung eines RBD-Volumes funktioniert.
Ändern Sie die Volume-Größe im pvc.yaml-Manifest in 2Gi und wenden Sie es an:
kubectl apply -f pvc.yaml
Warten wir, bis die Änderungen wirksam werden, und schauen wir uns die Volume-Größe noch einmal an.
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653
kubectl get pv
kubectl get pvc
Wir sehen, dass sich die Größe von PVC nicht verändert hat. Um herauszufinden, warum, können Sie Kubernetes nach einer YAML-Beschreibung des PVC abfragen:
kubectl get pvc rbd-pvc -o yaml
Hier ist das Problem:
Nachricht: Warten darauf, dass der Benutzer einen Pod (neu) startet, um die Größenänderung des Dateisystems des Volumes auf dem Knoten abzuschließen. Typ: FileSystemResizePending
Das heißt, die Festplatte ist gewachsen, das darauf befindliche Dateisystem jedoch nicht.
Um das Dateisystem zu vergrößern, müssen Sie das Volume mounten. In unserem Land wird das erzeugte PVC/PV derzeit in keiner Weise verwendet.
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: false
Und nun schauen wir uns PVC an:
kubectl get pvc
Die Größe hat sich geändert, alles ist in Ordnung.
Im ersten Teil haben wir mit dem RBD-Blockgerät (es steht für Rados Block Device) gearbeitet, dies ist jedoch nicht möglich, wenn verschiedene Microservices gleichzeitig mit diesem Datenträger arbeiten müssen. CephFS eignet sich viel besser für die Arbeit mit Dateien als für die Arbeit mit Disk-Images.
Am Beispiel von Ceph- und Kubernetes-Clustern konfigurieren wir CSI und andere notwendige Entitäten für die Arbeit mit CephFS.
Holen wir uns die Werte aus dem neuen Helm-Diagramm, die wir brauchen:
helm inspect values ceph-csi/ceph-csi-cephfs > cephfs.yml
Auch hier müssen Sie die Datei cephfs.yml ausfüllen. Wie zuvor helfen Ceph-Befehle:
ceph fsid
ceph mon dump
Füllen Sie die Datei mit Werten wie diesen 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: true
Bitte beachten Sie, dass Monitoradressen in der einfachen Form Adresse:Port angegeben werden. Um Cephfs auf einem Knoten zu mounten, werden diese Adressen an das Kernel-Modul übergeben, das noch nicht weiß, wie es mit dem v2-Monitor-Protokoll arbeiten soll.
Wir ändern den Port für httpMetrics (Prometheus wird dorthin gehen, um Metriken zu überwachen), damit es nicht zu Konflikten mit nginx-proxy kommt, das von Kubespray installiert wird. Möglicherweise benötigen Sie dies nicht.
Installieren Sie 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-namespace
Gehen wir zum Ceph-Datenspeicher, um dort einen separaten Benutzer zu erstellen. In der Dokumentation heißt es, dass der CephFS-Provisioner Cluster-Administrator-Zugriffsrechte benötigt. Wir werden jedoch 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 schauen wir uns gleich seinen Zugangsschlüssel an, wir werden ihn später brauchen:
ceph auth get-key client.fs
Lassen Sie uns separate Secret- und StorageClass-Klassen erstellen.
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:
# Необходимо для динамически создаваемых томов
adminID: fs
adminKey: <вывод предыдущей команды>
Anwenden des Manifests:
kubectl apply -f secret.yaml
Und jetzt – eine separate StorageClass:
---
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
Füllen wir es hier aus Cluster-ID und anwendbar in Kubernetes:
kubectl apply -f storageclass.yaml
Проверка
Um dies zu überprüfen, erstellen wir wie im vorherigen Beispiel ein PVC:
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: csi-cephfs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
storageClassName: csi-cephfs-sc
Und prüfen Sie das Vorhandensein von PVC/PV:
kubectl get pvc
kubectl get pv
Wenn Sie sich Dateien und Verzeichnisse in CephFS ansehen möchten, können Sie dieses Dateisystem irgendwo mounten. Zum Beispiel wie unten gezeigt.
Gehen wir zu einem der Ceph-Clusterknoten und führen die folgenden Aktionen 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/cephfs
Natürlich ist die Montage von FS auf einem solchen Ceph-Knoten nur für Trainingszwecke geeignet, was wir auf unserem tun
Und zum Schluss schauen wir uns an, wie die Größenänderung von Volumes im Fall von CephFS funktioniert. Kehren wir zu Kubernetes zurück und bearbeiten unser Manifest für PVC – erhöhen Sie die Größe dort beispielsweise auf 7Gi.
Wenden wir die bearbeitete Datei an:
kubectl apply -f pvc.yaml
Schauen wir uns das bereitgestellte Verzeichnis an, um zu sehen, wie sich das Kontingent geändert hat:
getfattr -n ceph.quota.max_bytes <каталог-с-данными>
Damit dieser Befehl funktioniert, müssen Sie das Paket möglicherweise auf Ihrem System installieren attr.
Die Augen haben Angst und die Hände tun es
All diese Zaubersprüche und langen YAML-Manifeste scheinen auf den ersten Blick kompliziert zu sein, aber in der Praxis haben Slurm-Schüler den Dreh ziemlich schnell raus.
In diesem Artikel sind wir nicht tief in den Dschungel vorgedrungen – dafür gibt es eine offizielle Dokumentation. Wenn Sie sich für die Details zum Einrichten von Ceph-Speicher mit einem Kubernetes-Cluster interessieren, helfen Ihnen diese Links weiter:
Auf dem Slurm-Kurs
Und wenn Sie mehr an Datenspeicherung interessiert sind, dann melden Sie sich an
Autor des Artikels: Alexander Shvalov, praktizierender Ingenieur
Source: habr.com