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)
- 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).
- kubelet wird beauftragt einen Pod zu starten
- kubelet leitet den Request an den CRI-O Daemon über das Container Runtime Interface via gRPC weiter
- CRI-O nutzt die containers/image-Bibliothek, um das Image aus einer Container Registry zu laden
- Das geladenen Image wird in das Container-Root-Filesystem entpackt, das mittels der containers/storage Bibliothek in COW-Dateisystemen gespeichert wird
- Nachdem das root-Filesystem für den Container erstellt wurde, generiert CRI-Omit Hilfe der OCI Runtime Tools eine OCI Runtime Spezifikation
- CRI-O startet eine OCI kompatible Runtime (Default runC), die unter Nutzung der Spezifikationen, den Container-Prozess startet
- Jeder Container wird von einem separaten conmon-Prozess überwacht
- Netzwerk für den Pod wird mittels CNI bereitgestellt
Was bedeutet CRI-O für Docker?
Quellen
- http://cri-o.io/
- https://github.com/kubernetes-incubator/cri-o
- https://kubernetes.io/blog/2016/12/container-runtime-interface-cri-in-kubernetes/
- https://www.redhat.com/en/blog/introducing-cri-o-10
- https://github.com/containerd/cri
- https://www.redhat.com/en/blog/running-production-applications-containers-introducing-ocid
Principal Consultant bei ORDIX
Kommentare
Bei Updates im Blog, informieren wir per E-Mail.