Wie ein Pod in Kubernetes eine IP-Adresse erhält

Anmerkung des Übersetzers.: Dieser Artikel, verfasst von einem SRE-Ingenieur von LinkedIn, beschreibt im Detail die „interne Magie“ von Kubernetes — genauer gesagt, die Interaktion zwischen CRI, CNI und kube-apiserver: was passiert, wenn ein neuer Pod eine IP-Adresse zugewiesen bekommen muss.

Eine der grundlegenden Anforderungen des Kubernetes-Netzwerkmodells besteht darin, dass jeder Pod seine eigene IP-Adresse haben muss und jeder andere Pod im Cluster in der Lage sein sollte, mit ihm über diese Adresse zu kommunizieren. Es gibt viele Netzwerk „Provider“ (Flannel, Calico, Canal usw.), die dabei helfen, dieses Netzwerkmodell umzusetzen.

Als ich anfing, mit Kubernetes zu arbeiten, war mir nicht ganz klar, wie genau Pods ihre IP-Adressen erhalten. Selbst mit dem Verständnis, wie die einzelnen Komponenten funktionieren, war es schwierig, sich deren Zusammenarbeit vorzustellen. Zum Beispiel wusste ich, wozu CNI-Plugins nötig sind, aber ich wusste nicht, wie genau sie aufgerufen werden. Deshalb habe ich beschlossen, diesen Artikel zu schreiben, um mein Wissen über die verschiedenen Netzwerkkomponenten und deren Zusammenarbeit im Kubernetes-Cluster zu teilen, die es jedem Pod ermöglichen, seine einzigartige IP-Adresse zu erhalten.

Es gibt verschiedene Möglichkeiten, die Netzwerkkommunikation in Kubernetes zu organisieren — ähnlich wie es verschiedene Runtime-Optionen für Container gibt. In dieser Veröffentlichung wird Flannel zum Aufbau des Netzwerks im Cluster verwendet, während als Runtime Containerd. Ich gehe außerdem 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 zahlreiche hervorragende Artikel, die erklären, wie Container miteinander über das Netzwerk verbunden sind. Daher werde ich nur eine allgemeine Übersicht über die grundlegenden Konzepte geben und mich auf einen Ansatz beschränken, der den Aufbau eines Linux-Bridges und die Kapselung von Paketen umfasst. Einzelheiten werden weggelassen, da das Thema der Netzwerkkommunikation zwischen Containern einen separaten Artikel verdient. Links zu einigen besonders inhaltsreichen und lehrreichen Artikeln werden im Folgenden bereitgestellt.

Container auf demselben Host

Eine Möglichkeit, die IP-Adresskommunikation zwischen Containern, die auf demselben Host arbeiten, zu organisieren, besteht darin, eine Linux-Brücke zu schaffen. Dazu werden in Kubernetes (und Docker) virtuelle Geräte erstellt veth (virtuelles Ethernet). Ein Ende des veth-Geräts ist mit dem Netzwerk-Namensraum des Containers verbunden, das andere mit der Linux-Brücke im Netzwerk des Hosts.

Bei allen Containern auf demselben Host ist eines der Enden von veth mit der Brücke verbunden, über die sie über IP-Adressen miteinander kommunizieren können. Die Linux-Brücke hat ebenfalls eine IP-Adresse und fungiert als Gateway für ausgehenden (Egress)-Traffic aus Pods, der für andere Knoten bestimmt ist.

Wie ein Pod in Kubernetes eine IP-Adresse erhält

Container auf verschiedenen Hosts

Das Kapseln von Paketen ist eine Möglichkeit, wie Container auf verschiedenen Knoten über IP-Adressen miteinander kommunizieren können. In Flannel ist die Technologie dafür zuständig vxlan, die das ursprüngliche Paket in ein UDP-Paket "verpackt" und es dann an das Ziel sendet.

Im Kubernetes-Cluster erstellt Flannel ein vxlan-Gerät und ergänzt die Routingtabelle entsprechend auf jedem Knoten. Jedes Paket, das für einen Container auf einem anderen Host bestimmt ist, durchläuft das vxlan-Gerät und wird in ein UDP-Paket kapselt. Am Ziel wird das eingekapselte Paket extrahiert und an den entsprechenden Pod weitergeleitet.

Wie ein Pod in Kubernetes eine IP-Adresse erhält
Hinweis: Dies ist nur ein Weg, um die Netzwerkkonnektivität zwischen Containern zu organisieren.

Was ist CRI?

CRI (Container Runtime Interface) ist ein Plugin, das es kubelet ermöglicht, verschiedene Container-Laufzeitumgebungen zu nutzen. Die CRI-API ist in verschiedene Laufzeitumgebungen integriert, sodass Benutzer die Laufzeit nach ihrem Ermessen auswählen können.

Was ist CNI?

Das CNI-Projekt stellt dar Spezifikation dient der Bereitstellung einer universellen Netzwerk-Lösung für Linux-Container. Zudem umfasst es erlauben Plugins, die Funktionen von K9s zu erweitern. Ich habe in der Praxis nur eines davon verwendet —, die verschiedene Funktionen beim Einrichten des Pod-Netzwerks übernehmen. Ein CNI-Plugin ist eine ausführbare Datei, die den Spezifikationen entspricht (einige Plugins werden wir im Folgenden besprechen).

Zuweisung von Subnetzen an Knoten zur Vergabe von IP-Adressen an Pods

Da jeder Pod im Cluster eine IP-Adresse haben muss, ist es wichtig sicherzustellen, dass diese Adresse einzigartig ist. Dies wird erreicht, indem jedem Knoten ein einzigartiges Subnetz zugewiesen wird, aus dem dann IP-Adressen für die Pods auf diesem Knoten vergeben werden.

Der IPAM-Controller des Knotens

Wenn nodeipam wird als Parameter im Flag übergeben --controllers des kube-controller-managers, er weist jedem Knoten ein separates podCIDR (podCIDR) aus dem CIDR des Clusters zu (d.h. einen IP-Adressbereich für das Netzwerk des Clusters). Da diese podCIDR's nicht überlappen, ist es möglich, jedem Pod eine einzigartige IP-Adresse zuzuweisen.

Einem Knoten von Kubernetes wird das podCIDR zum Zeitpunkt seiner ersten Registrierung im Cluster zugewiesen. Um das podCIDR der Knoten zu ändern, müssen diese deregistriert und anschließend erneut registriert werden, wobei in der Zwischenzeit die entsprechenden Änderungen in der Konfiguration der Kubernetes-Steuerebene vorgenommen werden müssen. Das podCIDR eines Knotens kann mit dem folgenden Befehl ausgegeben werden:

$ 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 Knoten ist mit der Ausführung vieler vorbereitender Maßnahmen verbunden. In diesem Abschnitt konzentriere ich mich nur auf die, die direkt mit der Netzwerkkonfiguration des Pods verbunden sind.

Die Planung eines Pods auf einem bestimmten Knoten löst folgende Ereigniskette aus:

Wie ein Pod in Kubernetes eine IP-Adresse erhält

Hinweis: Architektur von CRI-Plugins Containerd.

Interaktion zwischen der Container-Laufzeitumgebung und CNI-Plugins

Jeder Netzwerkanbieter hat sein eigenes CNI-Plugin. Die Container-Laufzeitumgebung startet es, um das Netzwerk für den Pod während seiner Ausführung zu konfigurieren. Im Falle von containerd wird das CNI-Plugin von dem Plugin Containerd CRI.

Dabei hat jeder Anbieter seinen eigenen Agenten. Dieser wird auf allen Knoten von Kubernetes installiert und ist für die Netzwerkkonfiguration der Pods verantwortlich. Dieser Agent wird entweder zusammen mit der CNI-Konfiguration geliefert oder erstellt sie eigenständig auf dem Knoten. Die Konfiguration hilft dem CRI-Plugin, welches CNI-Plugin aufgerufen werden soll.

Der Speicherort der CNI-Konfiguration kann eingestellt werden; standardmäßig befindet sie sich in /etc/cni/net.d/<config-file>. Die Administratoren des Clusters sind ebenfalls verantwortlich für die Installation der CNI-Plugins auf jedem Knoten des Clusters. Auch deren Speicherort kann konfiguriert werden; 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 [plugins."io.containerd.grpc.v1.cri".cni] in der Konfigurationsdatei von containerd.

Da wir Flannel als Netzwerkanbieter verwenden, lassen Sie uns etwas über seine Konfiguration sprechen:

  • Flanneld (der Flannel-Daemon) wird normalerweise im Cluster als DaemonSet mit install-cni als Init-Container.
  • Install-cni erstellt eine CNI-Konfigurationsdatei (/etc/cni/net.d/10-flannel.conflist) auf jedem Knoten.
  • Flanneld erstellt ein vxlan-Gerät, ruft Netzwerkmetadaten vom API-Server ab und überwacht die Aktualisierungen der Pods. Mit ihrer Erstellung verbreitet es die Routen für alle Pods im gesamten Cluster.
  • Diese Routen ermöglichen es den Pods, sich untereinander über IP-Adressen zu verbinden.

Für detailliertere Informationen zur Funktionsweise von Flannel empfehle ich, die Links am Ende des Artikels zu nutzen.

Hier ist das Schema der Interaktion zwischen dem Containerd CRI-Plugin und den CNI-Plugins:

Wie ein Pod in Kubernetes eine IP-Adresse erhält

Wie oben zu sehen, ruft kubelet das Containerd CRI-Plugin auf, um einen Pod zu erstellen, und dieses ruft dann das CNI-Plugin zur Netzwerkkonfiguration des Pods auf. Dabei ruft das CNI-Plugin des Netzwerkproviders andere grundlegende CNI-Plugins zur Konfiguration verschiedener Aspekte des Netzwerks auf.

Interaktion zwischen CNI-Plugins

Es gibt verschiedene CNI-Plugins, deren Aufgabe es ist, die Netzwerkintegration zwischen Containern auf dem Host zu unterstützen. In diesem Artikel werden drei von ihnen behandelt.

CNI-Plugin Flannel

Bei der Verwendung von Flannel als Netzwerkprovider ruft die Containerd CRI-Komponente auf CNI-Plugin Flannel, indem sie die CNI-Konfigurationsdatei verwendet. /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 ruft Flanneld podCIDR und andere netzwerkbezogene Details vom API-Server ab 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 verwendet die Daten aus /run/flannel/subnet.env zur Konfiguration und zum Aufruf des CNI-Bridge-Plugins.

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"
  }
}

Bei der ersten Aufruf erstellt er einen Linux-Bridge mit "name": "cni0", wie im Konfigurationsfile angegeben. Anschließend wird für jeden Pod ein veth-Paar erstellt. Ein Ende wird mit dem Netzwerk-Namespace des Containers verbunden, das andere endet in der Linux-Brücke im Netzwerk des Hosts. CNI-Plugin Bridge verbindet alle Container des Hosts mit der Linux-Brücke im Netzwerk des Hosts.

Nachdem die veth-Paar-Konfiguration abgeschlossen ist, ruft das Bridge-Plugin den lokalen (host-local) CNI-IPAM-Plugin auf. Der Typ des IPAM-Plugins kann in der CNI-Konfiguration angepasst werden, die das CRI-Plugin zum Aufruf des Flannel-CNI-Plugins verwendet.

Lokale für den Host IPAM-Plugins CNI

Bridge CNI ruft auf lokalen IPAM-Plugin CNI mit folgender Konfiguration auf:

{
  "name": "cni0",
  "ipam": {
    "type": "host-local",
    "subnet": "10.244.0.0/24",
    "dataDir": "/var/lib/cni/networks"
  }
}

Host-lokaler IPAM-Plugin (IP AAdresse MManagement — Verwaltung der 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>. In dieser Datei ist die ID des Containers enthalten, dem diese IP-Adresse zugewiesen wurde.

Bei der Aufruf des Host-lokalen IPAM-Plugins gibt es die folgenden Daten zurück:

{
  "ip4": {
    "ip": "10.244.4.2",
    "gateway": "10.244.4.3"
  },
  "dns": {}
}

Zusammenfassung

Der Kube-Controller-Manager weist jedem Knoten eine PodCIDR zu. Pods jedes Knotens erhalten IP-Adressen aus dem Adressraum im zugewiesenen Bereich der PodCIDR. Da die PodCIDRs der Knoten sich nicht überschneiden, erhalten alle Pods eindeutige IP-Adressen.

Der Kubernetes-Cluster-Administrator konfiguriert und installiert kubelet, die Container-Laufzeit-Umgebung, den Agenten des Netzwerk-Anbieters und kopiert die CNI-Plugins auf jeden Knoten. Während des Starts generiert der Agent des Netzwerk-Anbieters die CNI-Konfiguration. Wenn ein Pod auf einen Knoten geplant wird, ruft kubelet das CRI-Plugin zu seiner Erstellung auf. Wenn containerd verwendet wird, ruft das Containerd CRI-Plugin das in der CNI-Konfiguration angegebene CNI-Plugin auf, um das Netzwerk des Pods zu konfigurieren. Dadurch erhält der Pod eine IP-Adresse.

Ich habe eine Weile gebraucht, um alle Feinheiten und Nuancen dieser Interaktionen zu verstehen. Ich hoffe, die gesammelte Erfahrung hilft Ihnen ebenfalls, zu verstehen, wie Kubernetes funktioniert. Wenn ich mich irgendwo irre, kontaktieren Sie mich bitte unter Twitter oder schreiben Sie an hello@ronaknathani.com. 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:

Quelle: habr.com

60GB SSD 8Gb DDR4