Persistenter Storage ist eine Herausforderung, ohne Frage. Besonders wenn du auf mehrere Server skalierst, verlangt diese Herausforderung dringlich nach Lösungen, die ich dir sehr gerne liefere. CEPH hat sich als zuverlässiges Storage System herausgestellt, das du ganz einfach an dein Kubernetes Cluster anbinden kannst, um dynamisch Storage zu provisionieren.
Persistenter Storage
Du unterscheidest in der Regel zwischen persistentem und flüchtigem Speicher. Der flüchtige Speicher wird nach der Verwendung verworfen und ist nicht weiter relevant. Der persistente Speicher enthält in der Regel die Nutzdaten, die du auch behalten möchtest. Das können zum Beispiel Datenbanken mit Benutzeraccounts oder Messdaten sein. Wenn du dein Programm beim nächsten Mal startest, sollen sie unbedingt wieder da sein und müssen daher persistent (lat. persistere = fortdauern) gespeichert werden.
Persistenter Speicher bedarf jedoch genaueren Managements. Die Daten dürfen nicht einfach auf einen "Nicht-Vergessen"-Haufen geworfen werden, sondern sollen fein säuberlich getrennt abgelegt werden. Doch wie stellst du den Speicher dafür bereit?
Ceph
Speicher auf einem Server bereitzustellen ist kein Kunststück: Du schiebst einfach eine Festplatte rein, fertig! Um Storage auch auf verschiedenen Servern und über die Grenzen von einzelnen Maschinen hinweg anbieten zu können braucht es aber ein verteiltes Storage-System. Alle Server sollen schnell und zuverlässig auf alle Daten zugreifen können, damit Daten niemals an einen Server gebunden sind. Dieser kann nämlich ausfallen, der Speicher und die Anwendung sollen aber weiterlaufen.
An dieser Stelle kommt CEPH ins Spiel, welches sich selbst als hochperformantes, verlässliches und skalierbares Storage-System beschreibt. In Lösungen wie Proxmox ist es ratz fatz eingerichtet und liefert beeindruckende Ergebnisse, die es absolut als Storage-System für dein Cluster qualifizieren.
Kubernetes & Rancher
Kubernetes Cluster zu managen ist absolut nicht trivial und es gibt auf dem Markt nur eine handvoll von Tools, die dir deine Arbeit auch wirklich erleichtern. Ein sehr etabliertes und von mir hoch geschätztes Tool dafür ist Rancher. Das einfache Setup und die übersichtliche Administration, Provisionierung und Wartung von Kubernetes Clusters macht damit tatsächlich Spaß.
Du brauchst Hilfe bei der Einrichtung oder Administration deines Clusters? Dann halte an dieser Stelle inne und vereinbare einen Termin, damit wir die folgenden Schritte zusammen durchgehen können:
Kubernetes CEPH storage class
Damit du Speicher dynamisch zur Verfügung stellen kannst arbeitet Kubernetes mit Storage Classes. Du brauchst also eine einfache storage class, die auf dein CEPH Cluster zugreift. Du brauchst dafür:
- Ein laufendes CEPH Cluster mit ausreichend Speicher
- Zugangsdaten für dein CEPH Cluster
- Die IPs deiner CEPH Monitors (Ich verwende hier exemplarisch 10.0.10.1, 10.0.10.2 und 10.0.10.3)
- Einen CEPH pool, den du als Speicher benutzen möchtest (Ich habe meinen kube genannt)
- Einen fetzigen Namen für deine Storage Class, ich nenne meine hier ceph-fra-01 (Weil es sich um das CEPH Cluster #1 in Frankfurt handelt)
Zugangsdaten über Kubernetes Secrets
Die Zugangsdaten für CEPH legen wir auf einem der CEPH Monitors an (Vorausgesetzt, dass der Pool kube heißt):
ceph auth get-or-create client.kube mon 'allow r' osd 'allow rw pool=kube'
Die Zugangsdaten müssen danach ausgelesen werden:
ceph auth get-key client.admin | base64
ceph auth get-key client.kube | base64
Nun kümmern wir uns um entsprechende Zugangsdaten in Kubernetes, die wir in Form von Secrets anlegen:
apiVersion: v1 kind: Secret metadata: name: ceph-admin-secret namespace: kube-system type: "kubernetes.io/rbd" data: key: --Dein Admin Key-- --- apiVersion: v1 kind: Secret metadata: name: ceph-secret namespace: kube-system type: "kubernetes.io/rbd" data: key: --Dein user key--
Die Storage class anlegen
Daraufhin kannst du ein entsprechendes Storage Class Objekt anlegen:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: ceph-fra-01 annotations: storageclass.beta.kubernetes.io/is-default-class: "true" provisioner: kubernetes.io/rbd parameters: monitors: 10.0.100.1:6789,10.0.100.2:6789,10.0.100.3:6789 adminId: admin adminSecretName: ceph-admin-secret adminSecretNamespace: kube-system pool: kube userId: kube userSecretName: ceph-secret userSecretNamespace: kube-system
Hinweis: Beachte, dass die entsprechenden Keyrings von ceph (z.B. /etc/ceph/xxx.keyring) auf den K8s Nodes liegen müssen und das ceph-common Paket installiert sein muss, damit deine Nodes Zugriff auf CEPH bekommen.
Das sollten wir einmal detailliert durchgehen. Durch eine Annotation haben wir die neue Storage Class zur Standard-Class gemacht. Dass heißt, dass alle Persistent Volume Claims bei uns anklopfen und nach Speicher fragen, wenn wir es ihnen nicht explizit anders befohlen haben sollten. Außerdem werden alle Monitors angegeben, um eine gewissen Ausfallsicherheit zu gewährleisten. Von hier aus werden nur noch der zu verwendende Pool und die entsprechenden Zugangsdaten angegeben.
Wenn du dich weniger mit den Kubernetes Ressourcen beschäftigen möchtest, so kannst du hier die Brücke zurück zu Rancher schlagen, das die Verwaltung von Storage Classes und Secrets über die Web UI ermöglicht:
- Für die Secrets navigierst du zu deinem Cluster und dem System Projekt. Unter Ressources kannst du die Secrets anlegen. Achte hier jedoch darauf, dass das Secrets den kubernetes.io/rbd type braucht! (Ich empfehle in diesem Fall, die Secrets per kubectl anzulegen)
- Für die Storage Classes navigierst du zu deinem Cluster und kannst dann unter Storage deine Classes verwalten. Doch Achtung: Damit du das mit CEPH arbeiten kannst musst du Global > Settings > Feature Flags die unsupported-storage-drivers einschalten.
Test-Volume Claim
Um die Storage Class zu testen, provisionieren wir zum Testen einfach ein Volume:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-pvc spec: storageClassName: ceph-fra-01 accessModes: - ReadWriteOnce resources: requests: storage: 3Gi
Sollte ein Volume gebunden werden, haben wir von nun an einen dynamisch provisionierten CEPH Storage in unserem Kubernetes 🎉
Fazit
Das Setup ist nicht immer einfach und birgt einige Fallen, in vielen Fällen wird es Probleme geben, aber das Endergebnis ist es auf jeden Fall wert. Einfacher, skalierbarer, hyperkonvergenter Speicher ist nun einmal nicht umsonst. Wenn du Probleme mit dem Setup hast, darfst du mich gerne kontaktieren und wir setzen zusammen deinen CEPH Storage auf:
Kommentieren