Kubernetes CRI-O: Wirft Red Hat Docker aus dem Ring?

Seit Kubernetes das Container Runtime Interface vorgestellt hat, ist kubelet nicht mehr an die Verwendung von fest implementierten Container-Runtimes gebunden. Es kann jede Runtime eingesetzt werden, die das Interface implementiert. CRI-O ist eine leichtgewichtige Container-Runtime, die federführend von Red Hat entwickelt wird und für den Einsatz mit Kubernetes optimiert ist. Die Beweggründe zur Entwicklung von CRI-O, dessen Architektur und Funktionsweise, sowie die möglichen Konsequenzen der aktuellen Entwicklung für Docker werden in diesem Beitrag erläutert.

Etwas Geschichte (zur Erläuterung der Zusammenhänge)

Zu Beginn hat Kubernetes Docker als einzige Container-Runtime unterstützt. Im Laufe der Zeit ist rkt hinzugekommen und es hat sich abgezeichnet, dass in Zukunft weitere Runtimes folgen würden. Durch die feste Verdrahtung der Runtimes in kubelet, war das Hinzufügen weiterer aufwändig. Somit kam der Wunsch auf, kubelet und die Containter-Runtimes zu entkoppeln, um dynamisch Runtimes zu Kubernetes hinzufügen zu können. Dies resultierte im Container Runtime Interface (CRI), das 2016 vorgestellt wurde.

Basierend darauf hat Red Hat als treibende Kraft das Projekt CRI-O initiiert. Die Entwicklung wurde mit dem Fokus betrieben, Container in Produktivumgebungen einzusetzen. Für Red Hat steht in diesem Zusammenhang natürlich OpenShift bzw. Kubernetes im Mittelpunkt. Im Gegensatz dazu hat Docker sich zu Beginn in erster Linie an Entwickler gewandt und kann als Vorreiter für die Bereitstellung einer einfachen Möglichkeit zur Erstellung von containerisierten Applikationen angesehen werden. Die Anforderungen, die im produktiven Betrieb entstehen, unterscheiden sich jedoch von den Erwartungen die Entwickler an Docker stellen. In diesem Bereich sind vor allem die Attribute Einfachheit, Stabilität und Effizienz entscheidend. Um diese für Kubernetes zu erreichen wurden mehrere Schritte eingeleitet:

  • Entwicklung des Container Runtime Interfaces (CRI) und somit Entkoppelung von kubelet und der Container Runtime
  • Entwicklung von CRI-O als leichtgewichtige Container Runtime, die selbst aus mehreren Komponenten besteht

Inwieweit auch die Marktmacht von Docker eine Rolle für den Anstoß zu der Entwicklung gegeben hat, lässt sich nur spekulieren. Jedenfalls ist auffällig, dass insbesondere Konkurrenten von Docker (u. a. Red Hat, SUSE, Intel, Hyper, IBM) an der Entwicklung von CRI-O beteiligt sind.

Der Vollständigkeit halber soll nicht unerwähnt bleiben, dass auch Docker den "monolithischen" Daemon, der Container direkt gestartet hat, in mehrere Komponenten aufgeteilt hat. In aktuellen Versionen wird containerd, für das Handling des Container-Lifecycles verwendet, der wiederum runC nutzt, um Container zu starten.

Fokus auf Kubernetes und die Komponenten

Das Credo mit dem CRI-O entwickelt wird, ist eine möglichst minimale, dediziert auf Kubernetes ausgerichtete, aus Standardkomponenten bestehende Container-Runtime zu erstellen. Durch den Fokus auf Kubernetes und mit dem Verzicht auf CLI-Werkzeuge zur Bedienung von CRI-O kann jeglicher unnötige "Ballast" weggelassen werden. Die große Bindung an Kubernetes manifestiert sich auch in den Versionen von CRI-O, die an die Versionen von Kubernetes gekoppelt sind. Die Komponenten aus denen CRI-O besteht, orientieren sich an dem was einen Container ausmacht bzw. aus welchen Teilen ein Container besteht. Das CRI bietet zwei Services an, die beide von CRI-O implementiert werden. Dies sind der RuntimeService (Management des Container-Lifecycles und Verbindungen zu Containern) und den CRI ImageService (Downloaden, Untersuchen und Löschen von Images). Im Folgenden sind die Komponenten von CRI-O einzeln aufgeführt.

OCI kompatible Runtime: Es wird theoretisch jede OCI kompatible Runtime für das Starten der Container unterstützt. Getestet wird CRI-O mit runC und Clear Containers, wobei runC der Default ist. Für das Erstellen der der OCI Runtime Spezifikation, die die notwendigen Informationen zum Starten der Container beinhaltet, werden die OCI Runtime Tools verwendet. 

Storage: Die containers/storage Bibliothek wird genutzt, um die einzelnen Layer zu verwalten und die root-Filesysteme der Container in einem Pod bereitzustellen. Aktuell werden die folgenden Treiber unterstützt: OverlayFS (default), Device Mapper, aufs und btrfs. Der Support von Netzwerk basierten Dateisystem Images (z. B. NFS und GlusterFS) ist in der Entwicklung. 

Container Images: Für die Verwaltung der Images und das Herunterladen neuer Images von Registries wird auf die containers/image Bibliothek zurückgegriffen. Sie unterstützt Docker Images nach Schema 2 Version 1 und 2. 

Netzwerk: Die Bereitstellungen des Netzwerks für die Pods erfolgt über das Container Networking Interface (CNI). Ähnlich wie bei der Runtime funktioniert theoretisch jedes CNI-Plugin, wobei nur die wichtigsten getestet werden. 

Monitoring: Das Monitoring der Container, sowie deren Logging, das Attachen von Clients an Container und das Erkennen und Behandeln von OOM-Situationen im Container wird mit Hilfe des conmon-Utility ermöglicht. Dies ist ein schlankes C-Programm, von dem jeweils eine Instanz als Parent für jeden Container fungiert. Damit ist es möglich CRI-O neu zu starten ohne laufende Container zu beeinflussen.

Security: Für die Separierung der Container aus Security-Sicht werden die gängigen Tools wie, u. a. SELinux, Capabilities und Seccomp-Profile eingesetzt, die in der OCI-Spezifikation beschrieben sind.

Architektur und Abläufe

Die Integration von CRI-O in Kubernetes, dessen Architektur und das Zusammenspiel der einzelnen Komponenten lassen sich am einfachsten mit dem Ablauf des Startvorgangs eines Containers erläutern (siehe Abbildung).

  1. kubelet wird beauftragt einen Pod zu starten
  2. kubelet leitet den Request an den CRI-O Daemon über das Container Runtime Interface via gRPC weiter
  3. CRI-O nutzt die containers/image-Bibliothek, um das Image aus einer Container Registry zu laden
  4. Das geladenen Image wird in das Container-Root-Filesystem entpackt, das mittels der containers/storage Bibliothek in COW-Dateisystemen gespeichert wird
  5. Nachdem das root-Filesystem für den Container erstellt wurde, generiert CRI-Omit Hilfe der OCI Runtime Tools eine OCI Runtime Spezifikation
  6. CRI-O startet eine OCI kompatible Runtime (Default runC), die unter Nutzung der Spezifikationen, den Container-Prozess startet
  7. Jeder Container wird von einem separaten conmon-Prozess überwacht
  8. Netzwerk für den Pod wird mittels CNI bereitgestellt

Was bedeutet CRI-O für Docker?

Seit Kubernetes 1.9 bzw. OpenShift 3.9 wird CRI-O vollständig unterstützt, jedoch ist Docker weiterhin die Default-Container-Runtime. In Zukunft wird Red Hat laut eigener Aussage in OpenShift Online CRI-O einsetzen. Damit zeigen sie deutlich welche Container-Runtime aus ihrer Sicht am besten für Kubernetes geeignet ist. Doch jeder kann das Kubernetes Container Runtime Interface in seiner Runtime implementieren, womit Kubernetes dank CRI sehr flexibel ist.

Docker hat, wie bereits erwähnt, die Zeichen der Zeit erkannt und mit containerd eine eigene schlanke Container-Runtime entwickelt. Seit Version 1.1 beinhaltet containerd ein natives CRI-Plugin und kann damit ohne Umwege von kubelet genutzt werden. Im Gegensatz zu CRI-O, das aus verschiedenen eigenständigen Komponenten besteht, sind alle Features zum Betrieb von Containern fest in containerd inkludiert. Des Weiteren ist containerd nicht für den Einsatz mit Kubernetes optimiert, sondern kommt in verschiedenen Szenarien zum Einsatz.

Daher wird Docker, trotz der Bemühungen eine für den produktiven Betrieb optimierte Container-Runtime zur Verfügung zu stellen, es aus unserer Sicht schwer haben auch in Zukunft die Standard-Runtime für Kubernetes zu bleiben. Dies lässt sich zum einen mit der engen Verbindung von CRI-O und Kubernetes und zum anderen mit der Marktmacht von Red Hat (OpenShift) begründen. Dies bedeutet nicht, dass Docker den gesamten Container-Markt verlieren wird, jedoch werden sie wahrscheinlich in produktiven Umgebungen, die von Kubernetes dominiert werden, an Präsenz einbüßen.

Quellen

0
Wir vergrößern unser Team – Datenbankspezialist Or...
Cloud Services 2018 im Vergleich

Unsere Autoren

Technologie Blogs

Tutorials

4 members

Webentwicklung

3 members

Java

3 members

Archiv | Blog-Beiträge

Login