Managed Kubernetes Teaser

Kubernetes – Alles über Cluster, Pods und Kubelets

Durch die Zunahme der Komplexität von IT-Infrastrukturen scheinen monolithischen Software-Lösungen immer schlechter geeignet um moderne Systeme abzubilden. Monolithische Lösungen sind oft zu komplex und unflexibel. Mittlerweile gibt es deutlich bessere Methoden und Anwendungen dieses Konzepts. 

Die sogenannten Microservices sind im Grunde nichts weiter als monolithische Strukturen, die in kleine Teile heruntergebrochen werden, um jede einzelne Anwendung skalieren und verwalten zu können. Der Einsatz von Microservices z.B. in der Cloud, ist heute eines der wichtigsten Kernelemente bei der Verwendung einer komplementäre Lösungen.

Die Verwaltung von vielen einzelnen Microservices kann jedoch wiederum sehr zeitaufwendig und kostspielig sein. Warum das so ist, wird deutlich, wenn man sich komplexere IT-Strukturen anschaut: Oft werden viele Anwendungen parallel gestartet, verwaltet und neu strukturiert und das manchmal mehrmals am Tag. Dieser Aufwand ist händisch kaum zu bewältigen und muss daher sinnvoll organisiert werden. Das Stichwort der Stunde lautet hier Orchestrierung mithilfe von Kubernetes.

Kubernetes kümmert sich um die komplette Bereitstellung von Anwendungen. Die verschiedene Anwendungen werden innerhalb von Servern, unter Berücksichtigung einer optimalen Auslastung, platziert. Kubernetes kommuniziert zwischen den Anwendungen und sagt ihnen wie sie einander finden können. Das heißt wiederum, dass die Administrationsarbeiten deutlich abnehmen.

Der Aufbau von Kubernetes

Wie schon gesagt, nimmt Kubernetes die Steuerung von Anwendungen in die Hand. Um diesen Mechanismus besser nachvollziehen zu können, müssen wir uns genauer mit dem Aufbau beschäftigen.

Kubernetes besteht aus zwei verschiedenen Ebenen: Master- und Arbeitsknoten. Der Kubernetes-Master, auch Steuerebene genannt, kümmert sich um die Verwaltung und Steuerung des gesamten Systems. Der Arbeitsknotenhingegen führt nur die bereitgestellten Anwendungen aus. Jede Ebene besteht aus definierten Bereichen, die man kennen muss, um zu verstehen, wie Kubernetes in der Lage ist, die Anwendungen zu orchestrieren.

Steuerebene

  • Der API-Server: führt eine Kommunikation mit dem Kubernetes-Cluster sowie Operationen auf ihm aus
  • Der Scheduler: plant die Anwendungen (Zuweisung eines Arbeitsknotens zu jeder bereitstellbarer
    Komponente der Anwendung)
  • Der Controller-Manager: übt clusterweite Funktionen aus, z. B. die Replikation von Komponenten, Verfolgung der Arbeitsknoten, Handhabung von Knotenausfällen
  • Der Verteilte Datenspeicher etcd: Hier ist die gesamte Clusterkonfiguration dauerhaft festgehalten

Arbeitsknoten

  • Containerlaufzeit: führt die Container wie Docker oder rkt aus
  • Das Kubelet: kommuniziert mit dem Master und steuert die Container auf dem Knoten
  • Der Kubernetes-Dienstproxy (Kube-Proxy): übernimmt Proxy- und Lastenausgleichsfunktionen für den Datenverkehr zwischen den Anwendungskomponenten

Bevor wir die Zusammenarbeit der Komponenten näher beschreiben, beschäftigen wir uns mit dem Grundstein von Kubernetes, den sogenannte Pods.

Ein Pod ist eine Einheit bestehend aus einem oder mehreren Containern, die stets zusammen auf einer Node ausgeführt werden. Damit lässt sich sicherstellen, dass Container, die ohne einander nicht funktionieren würden, als eine Einheit auf dem selben Node ausgeführt werden.

Darüber hinaus teilen sich die Container eines Pods einen Netzwerk-Namespace und sprechen so direkt via Loopback-Interface miteinander. Pods untereinander kommunizieren jedoch über ihre IP-Adresse. Die Pods sind vergleichbar mit einem Host oder einer VM. Bei der Trennung von Pods geht es vor allem um die Skalierung und Aktualisierung der einzelnen Komponenten unabhängig voneinander.

Kommunikation von Komponenten

Die oben beschriebenen Steuerkomponenten kommunizieren indirekt über den API-Server miteinander, wobei der API-Server als einziger mit etcd kommuniziert. Der Kubernetes-API-Server kommuniziert also direkt mit etcd; alle anderen Komponenten lesen und schreiben über den API-Server in den etcd.

Das bietet einige Vorteile, wie ein stabiles und optimistisches Sperrsystem und vor allem eine stabilere Validierung. Weiterhin ist etcd vor allen Komponenten verborgen, welche ein eventuelles Ersetzen einfacher macht.

Die Komponenten der Steuerebene müssen über API-Server laufen, da nur so eine konsistente Aktualisierung des Clusterstatus stattfinden kann. Das Abfragen und Bearbeiten des Clusterstatus geschieht durch die CRUD-Schnittstelle (Create, Read, Update, Delete), welche über REST-API zur Verfügung gestellt wird.

Der API-Server sorgt zum einen dafür, dass die geschriebene Datei im Speicher immer gültig ist und zum anderen, dass die Änderungen nur von autorisierten Clients durchgeführt werden können.

Der Scheduler nutzt genau diesen Beobachtugsmechanismus von API-Servern und wartet darauf, sobald neue Pods erstellt werden, diesen neue Knoten zuzuweisen. Weiterhin bearbeitet der Scheduler die Poddefinition (In Poddefinition sind Status, Metadaten und die Beschreibung der Podinhalte enthalten) über den API-Server.

Die Aufgabe des Schedulers ist es, einen passenden Knoten zu finden. Dazu filtert er die Knotenliste, um eine Liste akzeptabler Knoten nach Priorität und Wahl des geeignetsten Knote/n für den Pod zu finden. Der Scheduler versucht dadurch eine gleichmäßige Auslastung der Nodes zu erreichen.

Was bis jetzt noch fehlt ist eine gewisse Kontrolle über das gesamte System. Dafür sind die Controller im Controller-Manager verantwortlich. Die Controller haben die Aufgabe den Ist-Zustand des Systems an den Soll-Zustand anzupassen. Der Soll-Zustand ist in den bereitgestellten Ressourcen des API-Server festgelegt.

[sc name=“focusitem-midnightblue-whitepaper-kubernetes“]
Es gibt verschiedenen Controller, die innerhalb von Controller-Manager-Prozessen festgelegt sind, wie zum Beispiel Replikationsmanager für eine Replikationskontrolle, Deploymentcontroller, StatefulSet Controller usw. Diese Controller kommunizieren indirekt über API-Server miteinander. Sie überwachen den API-Server, um die Änderung der Ressourcen nicht zu verpassen.

Sie führen benötigte Operationen (Erstellen eines neuen Objekts oder Änderung oder Löschung eines bereits Vorhandenen) durch und tragen anschließend den neuen Status in die Ressourcen ein.

Nachdem wir uns mit den Steuerungskomponenten auseinandergesetzt haben, beschäftigen wir uns im Folgenden mit zwei wichtigen Komponenten der Arbeitsknoten.

Als erstes stellen wir den orchestrierten Teil, den Scheduler, vor. Er plant die angegebenen Containergruppe auf den verfügbaren Arbeitsknoten ein, hierbei orientiert er sich am Ressourcenbedarf der Containergruppen.

Das Kubelet teilt Containerlaufzeit zu, um die erforderlichen Containerimages herunterzuladen und sie auszuführen. Das Kubelet ist die Komponente, die für alle laufenden Prozesse im Arbeitsknoten verantwortlich ist. Das Kubelet registriert den Knoten, auf dem es ausgeführt wird. Dafür erstellt es eine Knotenressource im API-Server. Dann muss das Kubelet den API-Server über Pods im Auge behalten, um Container starten zu können.

Hierzu weist es die Containerlaufzeitumgebung wie Docker an, einen Container auf der Basis eines Containerimages auszuführen. Das Kubelet überwacht die laufenden Container und meldet den Status oder den Ressourcenverbrauch an den API-Server. Der Entwickler hinterlässt eine Beschreibung auf dem Kubernetes-API-Server.

Die ursprüngliche Beschreibung des Pods und anderer Komponenten kommen vom Entwickler der Applikation. Sie enthält Informationen darüber, welche Containerimages die Anwendung enthalten und wie die verschiedene Komponenten miteinander in Beziehung stehen oder welche Anwendungen von demselben Knoten ausgeführt werden sollen. Die Beschreibung kann auch aussagen, welche Komponenten ein Dienst für interne oder externe Clients anbietet.

Die Dienst-Proxys oder auch Kube-Proxys genannt, sorgen für eine Verbindung zwischen den Clients und den (über Kubernetes-API definierten) Diensten. Sie stellen sicher, dass die IP-Adresse und der Port des Dienstes bei einem Pod landet, der auch denselben Dienst unterstützt. Falls mehrere Pods für einen Dienst zur Verfügung stehen, führt der Proxy gleichzeitig einen Lastenausgleich durch.

Vorteile von Kubernetes

Kubernetes bereitet mit Hilfe von Containern Umgebungen vor, die die verschiedenen Anwendungen benötigen. K8s übernimmt somit nicht nur die Administrationsarbeit, sondern vereinfacht so auch die Bereitstellung von Diensten. Hinzu kommt noch, dass Entwickler sich nicht mehr damit befassen müssen, auf welchem Server welche Anwendung läuft, solange der Server die benötigten Ressourcen zur Verfügung stellt.

Aufgrund der Beschreibung der Ressourcenanforderungen des Entwicklers, kümmert sich Kubernetes alleine darum auf welchen Arbeitsknoten die Anwendungen laufen sollten. So kann er bei Bedarf die Anwendungen aufräumen und woanders platzieren. So kann Kubernetes viel besser als menschliche Entwickler optimale Kombinationen finden und eine gute Auslastung garantieren.

Ein weiterer Vorteil ist die Zustandsprüfung der Arbeitsknoten. Je größer die Infrastruktur ist, desto wahrscheinlicher ist der Ausfall des ein oder anderen Knoten. Hier hilft Kubernetes, indem es die Anwendungen auf anderen Knoten verschiebt, falls die Ursprünglichen ausfallen sollten.

Die automatische Skalierbarkeit von Pods ist ein weiterer Vorteil. So können, da Kubernetes in der Lage ist ein Pod vertikal zu skalieren, unnötige Redundanzen vermieden werden.