Container Storage Interface (CSI) je enotna vmesna plast za interakcijo med Kubernetesom in sistemi za shranjevanje podatkov. Kratko o njem smo že , danes pa bomo podrobneje obravnavali povezavo CSI in Ceph: prikazali bomo, kako s Kubernetes klastrom.
V članku so predstavljeni resnični, čeprav nekoliko poenostavljeni primeri za lažje razumevanje. Namestitve in konfiguracije Ceph in Kubernetes klastrov ne obravnavamo.
Vas zanima, kako to deluje?

Torej, imate na voljo Kubernetes klaster, razporejen, na primer, . Ob njem deluje klaster Ceph — ta se lahko prav tako namesti, na primer, s tem . Upam, da ni treba omenjati, da mora biti za produkcijo med njima omrežje s pasovno širino vsaj 10 Gb/s.
Če imate vse to, gremo naprej!
Najprej se prijavimo na eno od vozlišč klasterja Ceph in preverimo, ali je vse v redu:
ceph health
ceph -sNato takoj ustvarimo bazen za RBD diske:
ceph osd pool create kube 32
ceph osd pool application enable kube rbdPreidemo v Kubernetes klster. Tam bomo najprej namestili Ceph CSI gonilnik za RBD. Namestitev bomo izvedli, kot je potrebno, preko Helma.
Dodajamo repozitorij s chartom in pridobimo niz spremenljivk charta ceph-csi-rbd:
helm repo add ceph-csi https://ceph.github.io/csi-charts
helm inspect values ceph-csi/ceph-csi-rbd > cephrbd.ymlZdaj je treba izpolniti datoteko cephrbd.yml. Za to izvedemo ID klasterja in IP-naslove monitorjev v Ceph:
ceph fsid # tako ugotovimo clusterID
ceph mon dump # in tako bomo videli IP-naslove monitorjevPridobljene vrednosti vnesemo v datoteko cephrbd.yml. Hkrati vklopimo ustvarjanje politik PSP (Pod Security Policies). Možnosti v razdelkih nodeplugin in provisioner so že v datoteki, jih lahko popravimo tako, kot je razloženo spodaj:
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: trueNato je vse, kar nam ostane, namestiti chart v Kubernetes kluster.
helm upgrade -i ceph-csi-rbd ceph-csi/ceph-csi-rbd -f cephrbd.yml -n ceph-csi-rbd --create-namespaceOdlično, RBD gonilnik deluje!
Ustvarimo v Kubernetes nov StorageClass. Za to bo treba spet malo delati s Ceph.
Ustvarjamo novega uporabnika v Ceph in mu dodelimo pravice za pisanje v bazen kube:
ceph auth get-or-create client.rbdkube mon 'profile rbd' osd 'profile rbd pool=kube'Zdaj pa si oglejmo ključe dostopa vse tam:
ceph auth get-key client.rbdkubeUkaz bo prikazal nekaj takega:
AQCO9NJbhYipKRAAMqZsnqqS/T8OYQX20xIa9A==Zabeležimo to vrednost v Secret v klastru Kubernetes — tja, kjer jo potrebujemo userKey:
---
apiVersion: v1
kind: Secret
metadata:
name: csi-rbd-secret
namespace: ceph-csi-rbd
stringData:
# Ključne vrijednosti odgovaraju korisničkom imenu i njegovom ključu, kako je navedeno u
# Ceph klasteru. ID korisnika mora imati pristup bazenu,
# navedenom u storage class
userID: rbdkube
userKey:I stvaramo naš tajni ključ:
kubectl apply -f secret.yamlZatim nam treba otprilike ovakav manifest StorageClass:
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
clusterID:
pool: kube
imageFeatures: layering
# Ovi tajni podaci trebaju sadržavati informacije za autentifikaciju
# u vaš bazen.
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:
- discardTreba popuniti clusterID, kojeg smo već saznali naredbom ceph fsid, i primijeniti ovaj manifest u Kubernetes klasteru:
kubectl apply -f storageclass.yamlDa bismo provjerili rad klastera u suradnji, stvorimo ovakav PVC (Persistent Volume Claim):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: csi-rbd-scOdmah ćemo provjeriti kako je Kubernetes stvorio traženi volumen u Ceph-u:
kubectl get pvc
kubectl get pvIzgleda odlično! Kako to izgleda s Ceph strane?
Dobivamo popis volumena u bazenu i pregledavamo informacije o našem volumenu:
rbd ls -p kube
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653 # ovdje će, naravno, biti drugačiji ID volumena koji je prethodna naredba izdalaSada pogledajmo kako funkcionira promjena veličine RBD volumena.
Promijenimo veličinu volumena u manifestu pvc.yaml na 2Gi i primijenimo ga:
kubectl apply -f pvc.yamlSačekajmo da promjene stupe na snagu i još jednom provjerimo veličinu volumena.
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653
kubectl get pv
kubectl get pvcVidimo da veličina PVC nije promijenjena. Da bismo saznali razlog, možemo zatražiti od Kubernetesa opisati PVC u YAML formatu:
kubectl get pvc rbd-pvc -o yamlA evo i problema:
message: Čekanje da korisnik (re-)pokrene pod za završetak promjene veličine datotečnog sustava volumena na čvoru. type: FileSystemResizePending
Dakle, disk se povećao, ali datotečni sustav na njemu — nije.
Da bismo povećali datotečni sustav, moramo montirati volumen. Naš PVC/PV trenutno nije u upotrebi.
Možemo stvoriti testni Pod, na primjer ovako:
---
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: falseIn now let's take a look at the PVC:
kubectl get pvcThe size has changed, everything is fine.
In the first part we worked with the RBD block device (which stands for Rados Block Device), but this approach is not suitable if different microservices need to access this disk concurrently. For working with files rather than a disk image, CephFS is a much better choice.
We will set up CSI and the other necessary entities for working with CephFS using Ceph and Kubernetes clusters as an example.
We will obtain values from the relevant new Helm chart:
helm inspect values ceph-csi/ceph-csi-cephfs > cephfs.ymlOnce again, we need to fill in the cephfs.yml file. As before, Ceph commands will assist us:
ceph fsid
ceph mon dumpWe fill in the values file approximately like this:
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: trueNote that the addresses of the monitors are specified in a simple form address:port. To mount cephfs on the node, these addresses are passed to the kernel module, which does not yet support the v2 monitor protocol.
We change the port for httpMetrics (where Prometheus will fetch metrics for monitoring) so that it does not conflict with the nginx-proxy set up by Kubespray. You might not need this.
We install the Helm chart in the Kubernetes cluster:
helm upgrade -i ceph-csi-cephfs ceph-csi/ceph-csi-cephfs -f cephfs.yml -n ceph-csi-cephfs --create-namespaceWe go to the Ceph data storage to create a separate user there. The documentation states that the CephFS provisioner needs admin privileges to the cluster. However, we will create a separate user fs with limited permissions:
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'And now let's check its access key, which will be useful later:
ceph auth get-key client.fsWe will create separate Secret and StorageClass.
Nothing new, we've already seen this with RBD:
---
apiVersion: v1
kind: Secret
metadata:
name: csi-cephfs-secret
namespace: ceph-csi-cephfs
stringData:
# Required for dynamically created volumes
adminID: fs
adminKey:We apply the manifest:
kubectl apply -f secret.yamlAnd now – a separate StorageClass:
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-cephfs-sc
provisioner: cephfs.csi.ceph.com
parameters:
clusterID:
# The name of the CephFS file system where the volume will be created
fsName: cephfs
# (optional) Ceph pool where the volume data will be stored
# pool: cephfs_data
# (optional) Comma-separated mount options for Ceph-fuse
# e.g.:
# fuseMountOptions: debug
# (optional) Comma-separated mount options for CephFS for kernel
# See man mount.ceph for a list of these options. For example:
# kernelMountOptions: readdir_max_bytes=1048576,norbytes
# Secrets must contain access for admin and/or user of 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
# (optional) The driver can use either ceph-fuse (fuse),
# or ceph kernelclient (kernel).
# If not specified, the default volume mounting will be used,
# determined by searching for ceph-fuse and mount.ceph
# mounter: kernel
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
- debugLet's fill this in here clusterID and apply it in Kubernetes:
kubectl apply -f storageclass.yamlПроверка
To check, as in the previous example, we will create a PVC:
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: csi-cephfs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
storageClassName: csi-cephfs-scAnd check for the presence of PVC/PV:
kubectl get pvc
kubectl get pvIf you want to look at the files and directories in CephFS, you can mount this file system somewhere. For example, as shown below.
Let's go to one of the nodes in the Ceph cluster and perform the following actions:
# Точка монтирования
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/cephfsOf course, this kind of FS mounting on a Ceph node is suitable only for educational purposes, which we are engaged in on our . I don't think anyone would do this in production, as there is a high risk of accidentally overwriting important files.
And lastly, let's check how the volume resizing works with CephFS. We return to Kubernetes and edit our PVC manifest — let's increase the size, for example, to 7Gi.
We will apply the edited file:
kubectl apply -f pvc.yamlLet's check the mounted directory to see how the quota has changed:
getfattr -n ceph.quota.max_bytesFor this command to work, you may need to install the package in your system attr.
The eyes are afraid, but the hands are doing
Na prvi pogled, svi ovi alati i dugi YAML manifesti izgledaju složeno, ali u praksi studenti Slërma se brzo snalaze sa njima.
U ovom članku se nećemo zateći u dubinama — za to postoji zvanična dokumentacija. Ako vas zanimaju detalji konfiguracije Ceph skladišta u vezi sa Kubernetes klasterom, pomoći će vam sljedeće veze:
Na kursu Slërm možete da odete još malo dalje i implementirate stvarnu aplikaciju u Kubernetes-u koja će koristiti CephFS kao skladište za datoteke. Putem GET/POST zahteva moći ćete da šaljete datoteke i preuzimate ih iz Ceph-a.
A ako vas više zanimaju podaci za skladištenje, prijavite se na . Dok traje beta test, kurs možete dobiti sa popustom i uticati na njegov sadržaj.
Autor članka: Aleksandar Švalov, praktični inženjer , Certified Kubernetes Administrator, autor i developer kurseva Slërm.
Izvor: habr.com
