Hinweis.: Dieser Artikel, verfasst von einem SRE-Ingenieur aus LinkedIn, erläutert detailliert die „interne Magie“ in Kubernetes – genauer gesagt, das Zusammenspiel von CRI, CNI und kube-apiserver – was passiert, wenn ein neuer Pod eine IP-Adresse zugewiesen bekommen muss.
Eine der grundlegenden Anforderungen besteht darin, dass jeder Pod seine eigene IP-Adresse haben muss und jeder andere Pod im Cluster in der Lage sein sollte, über diese Adresse mit ihm zu kommunizieren. Es gibt viele Netzwerk-„Provider“ (Flannel, Calico, Canal usw.), die helfen, dieses Netzwerkmodell zu implementieren.
Als ich anfing, mit Kubernetes zu arbeiten, war mir nicht ganz klar, wie Pods genau ihre IP-Adressen erhalten. Selbst mit dem Verständnis, wie die einzelnen Komponenten funktionieren, war es schwierig, ihre Zusammenarbeit vorzustellen. Zum Beispiel wusste ich, wozu CNI-Plugins benötigt werden, aber ich konnte mir nicht vorstellen, wie sie genau aufgerufen werden. Daher beschloss ich, diesen Artikel zu schreiben, um mein Wissen über die verschiedenen Netzwerkkomponenten und ihre Zusammenarbeit im Kubernetes-Cluster zu teilen, die es jedem Pod ermöglichen, seine eigene einzigartige IP-Adresse zu erhalten.
Es gibt verschiedene Möglichkeiten, die Netzwerkkommunikation in Kubernetes zu organisieren – ähnlich wie es verschiedene Optionen für die Ausführungsumgebungen (runtime) für Container gibt. In diesem Beitrag wird verwendet um das Netzwerk im Cluster zu organisieren, während als Ausführungsumgebung – . Zudem gehe ich davon aus, dass Sie wissen, wie die Netzwerkkommunikation zwischen Containern funktioniert, daher werde ich nur kurz darauf eingehen, ausschließlich für den Kontext.
Einige grundlegende Konzepte
Container und Netzwerk: eine kurze Übersicht
Im Internet gibt es viele ausgezeichnete Publikationen, die erklären, wie Container miteinander vernetzt sind. Daher werde ich nur einen allgemeinen Überblick über die grundlegenden Konzepte geben und mich auf einen Ansatz konzentrieren, der die Erstellung eines Linux-Bridge und die Kapselung von Paketen beinhaltet. Einzelheiten werden weggelassen, da das Thema der Netzwerkkommunikation zwischen Containern einen eigenen Artikel verdient. Weiter unten sind einige besonders gehaltvolle und erkenntnisreiche Publikationen verlinkt.
Container auf demselben Host
Eine Möglichkeit, die IP-Kommunikation zwischen Containern, die auf demselben Host arbeiten, zu organisieren, besteht darin, einen Linux-Brücke zu erstellen. Dazu werden in Kubernetes (und Docker) virtuelle Geräte . Ein Ende des veth-Geräts wird mit dem Netzwerk-Namensraum des Containers verbunden, das andere Ende mit der im Netzwerk des Hosts.
Alle Container auf einem Host haben ein Ende des veth mit der Brücke verbunden, über die sie miteinander über IP-Adressen kommunizieren können. Die Linux-Brücke hat ebenfalls eine IP-Adresse und fungiert als Gateway für ausgehenden (egress) Datenverkehr aus Pods, der für andere Knoten bestimmt ist.

Container auf verschiedenen Hosts
Die Kapselung von Paketen ist eine der Methoden, die es Containern auf verschiedenen Knoten ermöglicht, über IP-Adressen miteinander zu kommunizieren. In Flannel wird diese Funktion durch die Technologie bereitgestellt, die das ursprüngliche Paket in ein UDP-Paket «verpackt» und dann an sein Ziel sendet.
Im Kubernetes-Cluster erstellt Flannel ein vxlan-Gerät und ergänzt entsprechend die Routing-Tabelle auf jedem der Knoten. Jedes Paket, das für einen Container auf einem anderen Host bestimmt ist, wird über das vxlan-Gerät geleitet und in ein UDP-Paket eingekapselt. Am Zielort wird das eingekapselte Paket extrahiert und an das entsprechende Pod weitergeleitet.

Hinweis: Dies ist nur eine von vielen Möglichkeiten zur Organisation der Netzwerkkommunikation zwischen Containern.
Was ist CRI?
ist ein Plugin, das es kubelet ermöglicht, verschiedene Container-Laufzeitumgebungen zu nutzen. Die API CRI ist in verschiedene Laufzeitumgebungen integriert, sodass Benutzer die Laufzeit nach ihren Wünschen wählen können.
Was ist CNI?
stellt dar stellt eine universelle Netzwerk-Lösung für Linux-Container bereit. Darüber hinaus umfasst es , die für verschiedene Funktionen bei der Netzwerkkonfiguration des Pods verantwortlich sind. Ein CNI-Plugin ist eine ausführbare Datei, die der Spezifikation entspricht (einige Plugins werden wir weiter unten besprechen).
Zuweisung von Subnetzen an Knoten zur Vergabe von IP-Adressen an Pods
Da jeder Pod im Cluster eine IP-Adresse benötigt, ist es wichtig sicherzustellen, dass diese Adresse eindeutig ist. Dies wird erreicht, indem jedem Knoten ein einzigartiges Subnetz zugewiesen wird, aus dem dann den Pods auf diesem Knoten IP-Adressen zugeordnet werden.
IPAM-Controller des Knotens
Wenn nodeipam wird als Parameterflagge übergeben --controllers , weist er jedem Knoten ein separates Subnetz (podCIDR) aus dem CIDR des Clusters (d.h. dem IP-Adressbereich für das Netzwerk des Clusters) zu. Da diese podCIDRs sich nicht überschneiden, ist es möglich, jedem Pod eine einzigartige IP-Adresse zuzuweisen.
Einem Kubernetes-Knoten wird podCIDR zum Zeitpunkt seiner initialen Registrierung im Cluster zugewiesen. Um podCIDR bei den Knoten zu ändern, müssen sie deregistriert und anschließend erneut registriert werden, wobei in der Zwischenzeit die entsprechenden Änderungen in der Konfiguration der Kubernetes-Managementschicht vorgenommen werden müssen. Den podCIDR eines Knotens kann man mit dem folgenden Befehl ausgeben:
$ kubectl get no -o json | jq '.spec.podCIDR'
10.244.0.0/24
Kubelet, die Container-Laufzeitumgebung und CNI-Plugins: wie das alles funktioniert
Die Planung eines Pods auf einem Node ist mit einer Reihe von vorbereitenden Maßnahmen verbunden. In diesem Abschnitt konzentriere ich mich nur auf die Aspekte, die direkt mit der Netzwerkkonfiguration des Pods zu tun haben.
Die Planung eines Pods auf einem bestimmten Node löst die folgende Kette von Ereignissen aus:

Hilfe: .
Interaktion der Containerlaufzeitumgebung mit CNI-Plugins
Jeder Netzwerkprovider hat sein eigenes CNI-Plugin. Die Containerlaufzeit ruft es auf, um das Netzwerk für den Pod während seiner Startphase zu konfigurieren. Im Falle von containerd wird der CNI-Plugin von dem Plugin .
Jeder Provider hat jedoch seinen eigenen Agenten. Dieser wird auf allen Kubernetes-Nodes installiert und ist für die Netzwerkkonfiguration der Pods verantwortlich. Dieser Agent wird entweder zusammen mit dem CNI-Config geliefert oder erstellt ihn eigenständig auf dem Node. Die Konfiguration hilft dem CRI-Plugin zu bestimmen, welches CNI-Plugin aufgerufen werden soll.
Der Speicherort des CNI-Configs kann konfiguriert werden; standardmäßig befindet es sich in /etc/cni/net.d/<config-file>. Die Clusteradministratoren sind ebenfalls verantwortlich für die Installation der CNI-Plugins auf jedem Node des Clusters. Auch deren Speicherort ist konfigurierbar; das Standardverzeichnis ist /opt/cni/bin.
Bei der Verwendung von containerd können die Pfade für die Konfiguration und die Binärdateien des Plugins im Abschnitt angegeben werden [plugins.«io.containerd.grpc.v1.cri».cni] in .
Da wir Flannel als Netzwerkprovider verwenden, lassen Sie uns ein wenig über dessen Konfiguration sprechen:
- Flanneld (der Daemon von Flannel) wird normalerweise als DaemonSet im Cluster installiert mit
install-cnials . Install-cnierstellt (/etc/cni/net.d/10-flannel.conflist) auf jedem Knoten.- Flanneld erstellt ein vxlan-Gerät, extrahiert Netzwerkmetadata vom API-Server und verfolgt die Updates der Pods. Während sie erstellt werden, verteilt es Routen für alle Pods im gesamten Cluster.
- Diese Routen ermöglichen es Pods, über IP-Adressen miteinander zu kommunizieren.
Für detailliertere Informationen zur Funktionsweise von Flannel empfehle ich, die Links am Ende des Artikels zu nutzen.
Hier ist ein Diagramm der Interaktion zwischen dem Containerd CRI-Plugin und den CNI-Plugins:

Wie oben zu sehen, ruft kubelet das Containerd CRI-Plugin auf, um einen Pod zu erstellen, und dieses wiederum ruft das CNI-Plugin zur Konfiguration des Pod-Netzwerks auf. Dabei ruft der CNI-Plugin des Netzwerkproviders andere zugrunde liegende CNI-Plugins auf, um verschiedene Aspekte des Netzwerks zu konfigurieren.
Interaktion zwischen den CNI-Plugins
Es gibt verschiedene CNI-Plugins, die darauf abzielen, die Netzwerkinteraktion zwischen Containern auf dem Host einzurichten. In diesem Artikel werden drei davon behandelt.
CNI-Plugin Flannel
Bei der Verwendung von Flannel als Netzwerkprovider wird das Containerd CRI-Komponente aufgerufen , indem die CNI-Konfigurationsdatei verwendet wird. /etc/cni/net.d/10-flannel.conflist.
$ cat /etc/cni/net.d/10-flannel.conflist
{
"name": "cni0",
"plugins": [
{
"type": "flannel",
"delegate": {
"ipMasq": false,
"hairpinMode": true,
"isDefaultGateway": true
}
}
]
}
Das CNI-Plugin Flannel arbeitet zusammen mit Flanneld. Beim Start extrahiert Flanneld podCIDR und andere netzwerkbezogene Details vom API-Server und speichert sie in einer Datei. /run/flannel/subnet.env.
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.0.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=false
Das CNI-Plugin Flannel nutzt Daten aus /run/flannel/subnet.env um das CNI-Bridge-Plugin einzurichten und aufzurufen.
CNI-Plugin Bridge
Dieses Plugin wird mit folgender Konfiguration aufgerufen:
{
"name": "cni0",
"type": "bridge",
"mtu": 1450,
"ipMasq": false,
"isGateway": true,
"ipam": {
"type": "host-local",
"subnet": "10.244.0.0/24"
}
}
Beim ersten Aufruf wird ein Linux-Bridge mit "name": "cni0", das im Konfigurationsfile angegeben ist, erstellt. Dann wird für jedes Pod ein Paar veth erstellt. Ein Ende wird mit dem Netzwerk-Namespace des Containers verbunden, das andere Ende geht in die Linux-Bridge im Host-Netzwerk. verbindet alle Host-Container mit dem Linux-Bridge-Netzwerk.
Nachdem das Paar veth konfiguriert ist, ruft das Bridge-Plugin den lokalen CNI-Plugin IPAM (host-local) auf. Der Typ des IPAM-Plugins kann in der CNI-Konfiguration festgelegt werden, die das CRI-Plugin verwendet, um den Flannel-CNI-Plugin aufzurufen.
Lokale Host-IPAM-Plugins CNI
Das Bridge CNI ruft mit folgender Konfiguration auf:
{
"name": "cni0",
"ipam": {
"type": "host-local",
"subnet": "10.244.0.0/24",
"dataDir": "/var/lib/cni/networks"
}
}
Host-lokales IPAM-Plugin (IP AAdresse MManagement — Verwaltung von IP-Adressen) gibt die IP-Adresse für den Container aus dem Subnetz zurück und speichert die zugewiesene IP auf dem Host im Verzeichnis, das im Abschnitt dataDir — /var/lib/cni/networks/<network-name=cni0>/<ip>angegeben ist. In dieser Datei befindet sich die ID des Containers, dem diese IP-Adresse zugewiesen wurde.
Beim Aufruf des host-lokalen IPAM-Plugins gibt es folgende Daten zurück:
{
"ip4": {
"ip": "10.244.4.2",
"gateway": "10.244.4.3"
},
"dns": {}
}
Zusammenfassung
Der Kube-controller-manager weist jedem Knoten ein podCIDR zu. Pods jedes Knotens erhalten IP-Adressen aus dem Adressraum im zugewiesenen Bereich podCIDR. Da die podCIDRs der Knoten nicht überschneiden, erhalten alle Pods eindeutige IP-Adressen.
Der Kubernetes-Cluster-Administrator konfiguriert und installiert kubelet, die Container-Laufzeitumgebung, den Agenten für den Netzwerkprovider und kopiert CNI-Plugins auf jeden Knoten. Während des Starts generiert der Agent des Netzwerkproviders die CNI-Konfiguration. Wenn ein Pod auf einem Knoten geplant wird, ruft kubelet das CRI-Plugin zu dessen Erstellung auf. Wenn containerd verwendet wird, ruft das Containerd-CRI-Plugin das im CNI-Config angegebene CNI-Plugin auf, um das Netzwerk des Pods einzurichten. Infolgedessen erhält der Pod eine IP-Adresse.
Es hat eine Weile gedauert, bis ich alle Feinheiten und Nuancen dieser Interaktionen verstanden habe. Ich hoffe, dass die gesammelten Erfahrungen auch Ihnen helfen, besser zu verstehen, wie Kubernetes funktioniert. Wenn ich in irgendetwas falsch liege, kontaktieren Sie mich bitte unter oder unter der Adresse . Zögern Sie nicht, mich zu kontaktieren, wenn Sie Aspekte dieses Artikels oder etwas anderes besprechen möchten. Ich freue mich darauf, mit Ihnen zu sprechen!
Links
Container und Netzwerk
Wie Flannel funktioniert
CRI und CNI
P.S. vom Übersetzer
Lesen Sie auch in unserem Blog:
- «»;
- „Illustriertes Handbuch zur Netzwerkausstattung in Kubernetes“: , ;
- «».
Quelle: habr.com
