So trefft ihr auf eurem Weg zu Cloud Native die richtigen technischen Entscheidungen
Sami Alajrami
Sami is a DevOps consultant in our Oslo office. He comes from Palestine and has a PhD in Computing Science from Newcastle University. Sami’s previous work focused on cloud-based software development, model-based engineering, and safety-critical systems. He’s also an INTJ.
Wenn ihr eure Cloud-Native-Reise beginnt, müsst ihr wichtige Entscheidungen zu Cloud-Anbietern, Continuous Deployment sowie zur Einrichtung und Trennung von Umgebungen treffen. Dieser Leitfaden hilft euch dabei, die richtigen Entscheidungen zu treffen, indem er Erkenntnisse aus dem Betrieb von Cloud-Native-Anwendungen in der Produktion vermittelt.
Kubernetes hat sich zur De-facto-Plattform für Container-Orchestrierung entwickelt. Wenn wir Kunden unterschiedlicher Größe und aus verschiedenen Branchen beim Einstieg in Cloud Native mit Kubernetes unterstützen, helfen wir ihnen, fundierte Entscheidungen und Technologieauswahlen zu treffen. Bei der Wahl von Cloud-Anbietern, CI-Tools, Continuous-Deployment-Pipelines usw. gibt es keine Einheitslösung. Daher ist es wichtig, von Anfang an die richtigen Entscheidungen zu treffen. Andernfalls können hohe Kosten durch verlorene Zeit und Geld entstehen.
In diesem Blogbeitrag teilen wir einige wichtige Aspekte, die ihr berücksichtigen solltet, wenn ihr Entscheidungen und technische Auswahlen für den Einstieg mit Kubernetes trefft. Dieser Beitrag richtet sich an alle, die ihren Weg mit Cloud Native und Kubernetes gerade beginnen, aber auch an diejenigen, die bereits gestartet sind und ihre Entscheidungen überprüfen möchten.
Die richtige Plattform wählen
Kubernetes-Cluster können selbst verwaltet oder von einem Cloud-Anbieter gemanagt werden. Als Faustregel gilt: Nutzt einen Managed-Kubernetes-Service, es sei denn, ihr habt einen triftigen technischen oder rechtlichen Grund für einen selbst verwalteten On-Premises-Cluster. Selbst verwaltete Cluster erfordern hochspezialisiertes Fachwissen im Team sowie laufende Infrastruktur- und Wartungskosten.
Wenn ihr euch für einen Managed-Kubernetes-Service entscheidet, solltet ihr den passenden Anbieter wählen. Das hängt von mehreren Faktoren ab, darunter:
Die Vertrautheit eures Teams mit den Services des Anbieters.
Der Reifegrad des Managed-Kubernetes-Angebots des Anbieters sowie dessen Funktionen und technische Einschränkungen. Beispielsweise, ob regionale Redundanz oder Cluster-Autoscaling unterstützt werden. Ein weiteres Beispiel ist die Unterstützung von Pod Security Policies und Network Policies.
Ob ihr weitere Cloud-Services desselben Anbieters nutzen müsst. Benötigt eure Anwendung beispielsweise eine DynamoDB-Datenbank von AWS, ist es sinnvoll, AWS EKS in derselben Region wie eure DynamoDB-Datenbank zu nutzen, um die Latenz beim Datenzugriff zu reduzieren.
Preise, SLA und Support-Pakete des Anbieters.
Grundsätzlich seid ihr mit einem der drei großen Cloud-Anbieter AWS, Google oder Azure gut aufgestellt, wenn ihr einen einfachen Kubernetes-Cluster benötigt. Unserer Erfahrung nach ist Googles GKE jedoch am einfachsten für den Einstieg und das ausgereifteste Managed-Kubernetes-Angebot auf dem Markt.
Entscheiden, wie ihr eure Umgebungen trennt
In den meisten Fällen habt ihr mindestens zwei Umgebungen: Dev/Test und Prod. Wie sollten diese in Kubernetes getrennt werden? Ihr könnt entweder einen Cluster pro Umgebung oder einen Namespace pro Umgebung verwenden. Die Trennung von Umgebungen über Namespaces senkt zwar die Kosten, da dieselbe Infrastruktur gemeinsam genutzt wird, ist aber aufgrund erwartbarer menschlicher Fehler von Entwicklern und Operatoren risikoreicher. Solche Fehler und Zugriffsprobleme lassen sich vermeiden, dies erfordert jedoch hohes Fachwissen im Team für Implementierung und Monitoring. Es besteht ein Zielkonflikt zwischen Infrastrukturkosten und dem Personalaufwand für Zugriffskontrolle und Sicherheit.
Für kleine Teams empfehlen wir einen Cluster pro Umgebung.
Ihr könnt die Cluster auch in separaten virtuellen oder physischen Netzwerken und/oder in separaten Cloud-Projekten bzw. -Konten platzieren. Das schafft eine klarere Trennung, mit der sich strikte Zugriffe auf Prod-Umgebungen einfach aufrechterhalten lassen. Gleichzeitig könnt ihr im Dev-Cluster mit dem Kubernetes-Setup selbst experimentieren. So könnt ihr bestimmte Kubernetes-Funktionen gefahrlos aktivieren oder neuere Kubernetes-Versionen testen.
Euer Kubernetes-Setup standardisieren
Sobald ihr eine Plattform für das Deployment eurer Kubernetes-Cluster gewählt habt, stellt sich die Frage: Wie stellt ihr eure Cluster bereit und wie wartet ihr sie? In den meisten Fällen müsst ihr mehr als einen Cluster verwalten. Daher ist es wichtig, Konfigurationsabweichungen zwischen ihnen zu vermeiden. Beispielsweise habt ihr möglicherweise Dev- und Prod-Cluster und möchtet sicherstellen, dass beide dieselben Konfigurationen haben und ihre Nodes dieselben Zugriffs- und Authentifizierungsberechtigungen für andere Cloud-Services besitzen. Das ist wichtig, weil ihr eure in Dev bereitgestellte Anwendung nach Prod überführt und dabei keine bösen Überraschungen erleben möchtet.
Dafür empfehlen wir einen Infrastructure-as-Code-Ansatz: Ihr definiert die Cluster-Konfiguration als Code und verwaltet diese Konfigurationen in einem Versionskontrollsystem. Liegt eure Cluster-Konfiguration als Code vor, könnt ihr einen neuen, identischen Cluster erstellen, um etwas Neues zu testen – ohne dabei den Workflow der Entwickler zu beeinträchtigen.
Wir empfehlen außerdem, eine Pipeline zu verwenden, um eure Cluster auf Basis von Änderungen an euren versionskontrollierten Konfigurationen bereitzustellen und zu warten. Dies wird häufig als GitOps bezeichnet.
Utilities als Infrastruktur behandeln
Utilities sind Tools oder Services von Drittanbietern, die ihr in eurem Cluster bereitstellt. Dazu gehören Monitoring-Tools wie Prometheus oder Manager für SSL-Zertifikate wie cert-manager. Diese Utilities sollten als Teil der Infrastruktur behandelt werden, das heißt: Sie werden beim Erstellen des Clusters aus Code bereitgestellt und über eine Pipeline gewartet, ähnlich wie der Cluster selbst. Das könnte sogar ein separater Job in derselben Pipeline sein, die den Cluster erstellt. Der Vorteil: Ihr könnt den Cluster mit allen Utilities von Drittanbietern einfach neu erstellen oder replizieren. Unser eigenes Open-Source-Tool Helmsman kann zur Orchestrierung des Deployments von Utility-Anwendungen von Drittanbietern eingesetzt werden.
Namespaces sinnvoll nutzen
Kubernetes-Namespaces sind virtuelle Trennungen innerhalb eines einzelnen Clusters. Sie werden häufig genutzt, um Teams und Anwendungen voneinander zu trennen. Beachtet bei der Nutzung von Namespaces Folgendes:
Gebt Entwicklern in einem Multi-Tenant-Cluster nur Zugriff auf die Namespaces, die sie benötigen, indem ihr Kubernetes RBAC nutzt.
Secrets sind Objekte mit Namespace-Zuordnung und können nicht aus einem anderen Namespace abgerufen werden. Wenn mehrere Anwendungen, die in verschiedenen Namespaces bereitgestellt werden, Zugriff auf denselben Satz von Secrets benötigen, müsst ihr entweder: a) diese Apps im selben Namespace bereitstellen, b) die Secrets namespaceübergreifend replizieren und manuell synchron halten oder, noch besser, c) ein Tool zur Secrets-Verwaltung wie Vault verwenden.
Ihr könnt Ressourcenquoten pro Namespace festlegen und so Limits für einzelne Teams oder Gruppen von Anwendungen definieren.
Mit Network Policies) könnt ihr Datenverkehr zwischen Apps erlauben oder blockieren, die in verschiedenen Namespaces bereitgestellt werden.
Kubernetes-Ressourcennamen (z. B. Deployments, Pods usw.) sind innerhalb eines Namespace eindeutig. Daher müsst ihr entweder verschiedene Versionen derselben App in unterschiedlichen Namespaces bereitstellen oder eure Ressourcennamen dynamisch gestalten. Das ist möglich, wenn ihr eure App mit Helm paketiert.
Helm-Deployment
Helm ist der Paketmanager für Kubernetes. Damit könnt ihr konfigurierbare Kubernetes-Deployment-Vorlagen für eure Anwendungen paketieren und teilen. Wir empfehlen, für das Deployment eurer Anwendungen Helm statt einfacher Kubernetes-YAML-Vorlagen zu verwenden. Helm-Pakete – auch Charts genannt – ermöglichen die Wiederverwendung von Vorlagen mit Konfigurationsparametern. So könnt ihr mehrere Instanzen eurer Anwendung in unterschiedlichen Umgebungen mit verschiedenen Konfigurationen bereitstellen – ohne redundanten Code oder Vorlagen.
Helm 2.x erfordert, dass eine serverseitige Komponente namens Tiller im Cluster bereitgestellt wird. Helm 3.0 wird Tiller entfernen, befindet sich derzeit jedoch noch in der Alpha-Phase. Solange ihr Helm 2.x verwendet, müsst ihr euch Gedanken darüber machen, wie ihr Tiller bereitstellt und absichert. Beachtet dabei Folgendes:
Tiller hat vollständigen Zugriff auf den Cluster. Stellt daher sicher, dass ihr bei der Bereitstellung die empfohlenen Sicherheitskonfigurationen befolgt.
Wir empfehlen, das Tiller-Deployment in eure Cluster-Pipeline aufzunehmen. Das ist hilfreich, wenn ihr das Cluster-Setup replizieren möchtet oder für die Disaster Recovery. Unser Open-Source-Tool Helmsman kann für die Bereitstellung sicherer Tiller-Instanzen verwendet werden.
Stellt in einem Multi-Tenant-Cluster für jedes Team einen Tiller in dessen Namespace bereit und konfiguriert RBAC so, dass der Geltungsbereich von Tiller auf diesen Namespace beschränkt ist.
Continuous Deployment (CD) von Anwendungen
Häufige Application Releases gelten als Best Practice, da sie mit geringeren Ausfallrisiken und kürzeren Wiederherstellungszeiten bei Incidents einhergehen (Quelle: The state of DevOps report 2019). Wenn ihr Kubernetes und Helm verwendet, solltet ihr über eine automatisierte Pipeline verfügen, die eure Änderungen kontinuierlich in K8S bereitstellt.
Abbildung 1 zeigt eine typische CD-Pipeline für Cloud Native Apps, die in K8S bereitgestellt werden.
Überlegt euch bei der Gestaltung eurer Pipeline, wie ihr eure Anwendung von der Dev-/Test-Umgebung in die Prod-Umgebung überführen möchtet. Das kann mit manuellen Freigaben in einer einzigen Pipeline erfolgen, oder ihr trennt die Dev- und Prod-Pipelines. Es gibt keine Universallösung, aber versucht immer, die einfachste Pipeline-Konfiguration zu verwenden, bis es gute Gründe gibt, sie komplexer zu gestalten. Berücksichtigt bei der Gestaltung des Workflows außerdem die Benutzerfreundlichkeit für Entwickler. Wenn ein Entwickler beispielsweise Änderungen in mehreren Repos vornehmen muss, um einen kleinen Bugfix in Prod zu bringen, ist das wahrscheinlich nicht komfortabel genug, um schnelle und häufige Deployments zu fördern.
Helm-Charts und Repos
Beachtet beim Paketieren eurer Anwendungen als Helm-Charts Folgendes:
Wenn mehrere Anwendungen oder Services identische oder sehr ähnliche Kubernetes-Deployment-Vorlagen haben (z. B. ein Deployment, einen Service und einen Ingress), erstellt ein gemeinsames Chart, das sich für all diese Anwendungen konfigurieren lässt. So könnt ihr euch auf ein einzelnes Chart konzentrieren und es absichern, statt viele ähnliche Charts zu pflegen.
Wie verwaltet ihr eure Helm-Charts? Und wie wollt ihr sie bei Bedarf intern oder extern teilen?
Ein weiterer Aspekt ist, wo ihr eure Helm-Charts speichert und wie ihr sie verwendet. Drei Muster sind weit verbreitet:
1) Speichert euer Helm-Chart-Verzeichnis als Teil eures Application-VCS-Repo.
Der Vorteil dieses Ansatzes ist, dass sich alles an einem Ort befindet. Zu den Nachteilen gehören jedoch:
eine komplexe Pipeline-Konfiguration, um das Chart getrennt von der App zu versionieren und zu veröffentlichen (es sei denn, ihr entscheidet euch, das Chart und die App jedes Mal gemeinsam zu releasen, auch wenn sich das Chart möglicherweise gar nicht geändert hat).
Wenn andere Apps (in anderen VCS-Repos) mit demselben Chart bereitgestellt werden, entsteht redundanter Code in euren Repos.
Ihr könnt euer Chart nicht teilen, ohne Zugriff auf euer Application-VCS-Repo zu gewähren.
2) Verwendet ein separates VCS-Repo für Helm-Charts und stellt sie über ein Helm-Repo bereit.
Die Vorteile dieses Ansatzes sind:
Versionierte Charts, die aus öffentlichen oder privaten Helm-Repositories bereitgestellt werden.
Die Möglichkeit, denselben Chart für mehrere Apps zu verwenden, wenn dies sinnvoll ist – ohne Code zu duplizieren.
Der größte Nachteil dieses Ansatzes besteht darin, dass ihr bei Änderungen an eurer Anwendung, die eine Anpassung des Helm-Charts erfordern, zunächst den Helm-Chart separat ändern und anschließend die Änderung am Anwendungscode deployen müsstet.
3) Da Chart-Änderungen in den frühen Phasen der Anwendungsentwicklung häufig vorkommen, könnt ihr die Ansätze 1 und 2 in verschiedenen Phasen eurer Anwendungsentwicklung kombinieren. Zu Beginn kann der erste Ansatz verwendet werden. Sobald sich die Anwendung stabilisiert hat, könnt ihr den zweiten Ansatz einsetzen.
Die oben genannten Muster sind zwar in unterschiedlichen Fällen geeignet, eure Wahl sollte jedoch auf eurem Anwendungsfall und einer Abwägung der jeweiligen Vor- und Nachteile basieren.
Verwaltung des Cluster-Zustands
Es ist wichtig, Ausfälle einzuplanen. Denkt auch über Szenarien nach wie: Was passiert, wenn Anwendungen gelöscht werden? Oder wenn der gesamte Cluster gelöscht wird? Was, wenn wir eine identische Kopie des Clusters in einer anderen Cloud-Region erstellen möchten?
Um auf all diese Szenarien vorbereitet zu sein, müsst ihr den Cluster-Zustand sichern und an einem sicheren Ort speichern. Glücklicherweise gibt es Tools, die euch dabei helfen. Wir setzen erfolgreich Velero von VMWare ein. Mit Velero könnt ihr regelmäßige Backups des Cluster-Zustands erstellen (Deployments, Volumes usw.) und in einem Cloud-Speicher ablegen. Die Cluster-Snapshots können verwendet werden, um den Cluster-Zustand jederzeit wiederherzustellen. Was aber, wenn wir den Cluster selbst neu erstellen müssen? Wenn ihr den Cluster wie oben beschrieben aus Code deployt, könnt ihr ihn mit demselben versionierten Code neu erstellen, mit dem ihr ihn ursprünglich erstellt habt, und seinen Zustand anschließend mithilfe eines Velero-Snapshots wiederherstellen.
Zum Schluss
Wenn ihr gerade erst anfangt, sind Abkürzungen leicht und verlockend. Das ist in der Lern- und Experimentierphase in Ordnung. Sobald ihr jedoch eure Kubernetes-Umgebungen einrichtet, solltet ihr von Anfang an den richtigen Weg wählen – auch wenn das mehr Zeit und Aufwand bedeutet. Das wird sich künftig auszahlen!
- Cloud
Subscribe to our newsletter
Related blogs