So überprüfen Sie das Kubernetes-Netzwerk

Einführung

Kubernetes ist ein Container-Orchestrierungssystem, das containerisierte Anwendungen in einem Cluster von Serverknoten verwalten kann. Um die Netzwerkkonnektivität zwischen allen Containern in einem Cluster aufrechtzuerhalten, sind einige fortgeschrittene Netzwerktechniken erforderlich. In diesem Artikel werden einige Tools und Techniken zur Überprüfung dieser Netzwerkkonfiguration kurz beschrieben.

Diese Tools können hilfreich sein, wenn Sie Konnektivitätsprobleme beheben, Probleme mit dem Netzwerkdurchsatz untersuchen oder Kubernetes untersuchen, um zu erfahren, wie es funktioniert.

Wenn Sie mehr über Kubernetes im Allgemeinen erfahren möchten, werden in unserem LeitfadenAn Introduction to Kubernetes die Grundlagen behandelt. Für eine netzwerkspezifische Übersicht über Kubernetes lesen Sie bitteKubernetes Networking Under the Hood.

Anfangen

In diesem Lernprogramm wird davon ausgegangen, dass Sie einen Kubernetes-Cluster haben, in demkubectl lokal installiert und für die Verbindung mit dem Cluster konfiguriert ist.

Die folgenden Abschnitte enthalten viele Befehle, die auf einem Kubernetes-Knoten ausgeführt werden sollen. Sie werden so aussehen:

echo 'this is a node command'

Befehle, die auf Ihrem lokalen Computer ausgeführt werden sollen, sehen folgendermaßen aus:

echo 'this is a local command'

[.note] #Note: Die meisten Befehle in diesem Lernprogramm müssen als Benutzer vonrootausgeführt werden. Wenn Sie stattdessen einen sudo-fähigen Benutzer auf Ihren Kubernetes-Knoten verwenden, fügen Sie bittesudo hinzu, um die Befehle bei Bedarf auszuführen.
#

Ermitteln der Cluster-IP eines Pods

Verwenden Sie den Befehlkubectl get pod auf Ihrem lokalen Computer mit der Option-o wide, um die Cluster-IP-Adresse eines Kubernetes-Pods zu ermitteln. Diese Option listet weitere Informationen auf, einschließlich des Knotens, auf dem sich der Pod befindet, und der Cluster-IP des Pods.

kubectl get pod -o wide
OutputNAME                           READY     STATUS    RESTARTS   AGE       IP            NODE
hello-world-5b446dd74b-7c7pk   1/1       Running   0          22m       10.244.18.4   node-one
hello-world-5b446dd74b-pxtzt   1/1       Running   0          22m       10.244.3.4    node-two

Die SpalteIP enthält die interne Cluster-IP-Adresse für jeden Pod.

Wenn der gesuchte Pod nicht angezeigt wird, vergewissern Sie sich, dass Sie sich im richtigen Namespace befinden. Sie können alle Pods in allen Namespaces auflisten, indem Sie das Flag--all-namespaces hinzufügen.

Ermitteln der IP eines Dienstes

Wir können eine Service-IP auch mitkubectl finden. In diesem Fall listen wir alle Services in allen Namespaces auf:

kubectl get service --all-namespaces
OutputNAMESPACE     NAME                       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)         AGE
default       kubernetes                 ClusterIP   10.32.0.1               443/TCP         6d
kube-system   csi-attacher-doplugin      ClusterIP   10.32.159.128           12345/TCP       6d
kube-system   csi-provisioner-doplugin   ClusterIP   10.32.61.61             12345/TCP       6d
kube-system   kube-dns                   ClusterIP   10.32.0.10              53/UDP,53/TCP   6d
kube-system   kubernetes-dashboard       ClusterIP   10.32.226.209           443/TCP         6d

Die Dienst-IP finden Sie in der SpalteCLUSTER-IP.

Suchen und Eingeben von Pod-Netzwerk-Namespaces

Jedem Kubernetes-Pod wird ein eigener Netzwerk-Namespace zugewiesen. Netzwerknamespaces (oder Netns) sind ein Linux-Netzwerkprimitiv, das die Isolierung zwischen Netzwerkgeräten ermöglicht.

Es kann nützlich sein, Befehle aus den Netzen eines Pods auszuführen, um die DNS-Auflösung oder die allgemeine Netzwerkkonnektivität zu überprüfen. Dazu müssen wir zuerst die Prozess-ID eines der Container in einem Pod nachschlagen. Für Docker können wir dies mit einer Reihe von zwei Befehlen tun. Listen Sie zunächst die Container auf, die auf einem Knoten ausgeführt werden:

docker ps
OutputCONTAINER ID        IMAGE                                   COMMAND                  CREATED             STATUS              PORTS               NAMES
173ee46a3926        gcr.io/google-samples/node-hello        "/bin/sh -c 'node se…"   9 days ago          Up 9 days                               k8s_hello-world_hello-world-5b446dd74b-pxtzt_default_386a9073-7e35-11e8-8a3d-bae97d2c1afd_0
11ad51cb72df        k8s.gcr.io/pause-amd64:3.1              "/pause"                 9 days ago          Up 9 days                               k8s_POD_hello-world-5b446dd74b-pxtzt_default_386a9073-7e35-11e8-8a3d-bae97d2c1afd_0
. . .

Suchen Sie diecontainer ID odername aller Container in dem Pod, an dem Sie interessiert sind. In der obigen Ausgabe werden zwei Container angezeigt:

  • Der erste Container ist die Apphello-world, die im Podhello-worldausgeführt wird

  • Der zweite ist einpause-Container, der imhello-world-Pod ausgeführt wird. Dieser Container dient ausschließlich zur Speicherung des Netzwerknamensbereichs des Pods

Um die Prozess-ID eines Containers abzurufen, notieren Sie sich die Container-ID oder den Namen und verwenden Sie sie im folgenden Befehldocker:

docker inspect --format '{{ .State.Pid }}' container-id-or-name
Output14552

Eine Prozess-ID (oder PID) wird ausgegeben. Jetzt können wir das Programmnsenterverwenden, um einen Befehl im Netzwerk-Namespace dieses Prozesses auszuführen:

nsenter -t your-container-pid -n ip addr

Stellen Sie sicher, dass Sie Ihre eigene PID verwenden, und ersetzen Sieip addr durch den Befehl, den Sie im Netzwerk-Namespace des Pods ausführen möchten.

[.note] #Note: Ein Vorteil der Verwendung vonnsenter zum Ausführen von Befehlen im Namespace eines Pods gegenüber der Verwendung vondocker exec besteht darin, dass Sie Zugriff auf alle auf dem Befehl verfügbaren Befehle haben Knoten anstelle des normalerweise begrenzten Befehlssatzes, der in Containern installiert ist.
#

Suchen der virtuellen Ethernet-Schnittstelle eines Pods

Der Netzwerknamespace jedes Pods kommuniziert über eine virtuelle Ethernet-Pipe mit den Root-Netzen des Knotens. Auf der Knotenseite wird diese Pipe als Gerät angezeigt, das normalerweise mitveth beginnt und mit einer eindeutigen Kennung endet, z. B.veth77f2275 oderveth01. Innerhalb des Pods erscheint dieses Rohr alseth0.

Es kann nützlich sein, zu korrelieren, welchesveth-Gerät mit einem bestimmten Pod gekoppelt ist. Zu diesem Zweck werden alle Netzwerkgeräte auf dem Knoten und anschließend die Geräte im Netzwerknamespace des Pods aufgelistet. Wir können dann die Gerätenummern zwischen den beiden Listen korrelieren, um die Verbindung herzustellen.

Führen Sie zunächstip addr im Netzwerk-Namespace des Pods mitnsenter aus. Weitere Informationen hierzu finden Sie im vorherigen AbschnittFinding and Entering Pod Network Namespaces
:

nsenter -t your-container-pid -n ip addr
Output1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
10: eth0@if11:  mtu 1450 qdisc noqueue state UP group default
    link/ether 02:42:0a:f4:03:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.244.3.4/24 brd 10.244.3.255 scope global eth0
       valid_lft forever preferred_lft forever

Der Befehl gibt eine Liste der Schnittstellen des Pods aus. Notieren Sie dieif11-Zahl nacheth0@ in der Beispielausgabe. Dies bedeutet, dass dieeth0 dieses Pods mit der 11. Schnittstelle des Knotens verknüpft sind. Führen Sie nunip addr im Standard-Namespace des Knotens aus, um dessen Schnittstellen aufzulisten:

ip addr
Output1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever

. . .

7: veth77f2275@if6:  mtu 1450 qdisc noqueue master docker0 state UP group default
    link/ether 26:05:99:58:0d:b9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::2405:99ff:fe58:db9/64 scope link
       valid_lft forever preferred_lft forever
9: vethd36cef3@if8:  mtu 1450 qdisc noqueue master docker0 state UP group default
    link/ether ae:05:21:a2:9a:2b brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::ac05:21ff:fea2:9a2b/64 scope link
       valid_lft forever preferred_lft forever
11: veth4f7342d@if10:  mtu 1450 qdisc noqueue master docker0 state UP group default
    link/ether e6:4d:7b:6f:56:4c brd ff:ff:ff:ff:ff:ff link-netnsid 2
    inet6 fe80::e44d:7bff:fe6f:564c/64 scope link
       valid_lft forever preferred_lft forever

Die 11. Schnittstelle istveth4f7342d in dieser Beispielausgabe. Dies ist die virtuelle Ethernet-Pipe zu dem Pod, den wir untersuchen.

Conntrack Connection Tracking überprüfen

Vor Version 1.11 verwendete Kubernetes iptables NAT und das conntrack-Kernelmodul, um Verbindungen zu verfolgen. Verwenden Sie den Befehlconntrack, um alle derzeit verfolgten Verbindungen aufzulisten:

conntrack -L

Verwenden Sie das Flag-E, um kontinuierlich nach neuen Verbindungen zu suchen:

conntrack -E

Verwenden Sie das Flag-d, um Verbindungen mit Verfolgung zu einer bestimmten Zieladresse aufzulisten:

conntrack -L -d 10.32.0.1

Wenn Ihre Knoten Probleme haben, zuverlässige Verbindungen zu Diensten herzustellen, ist möglicherweise Ihre Verbindungsverfolgungstabelle voll und es werden neue Verbindungen getrennt. In diesem Fall werden in Ihren Systemprotokollen möglicherweise Meldungen wie die folgenden angezeigt:

/var/log/syslog

Jul 12 15:32:11 worker-528 kernel: nf_conntrack: table full, dropping packet.

Es gibt eine Sysctl-Einstellung für die maximale Anzahl der zu verfolgenden Verbindungen. Sie können Ihren aktuellen Wert mit dem folgenden Befehl auflisten:

sysctl net.netfilter.nf_conntrack_max
Outputnet.netfilter.nf_conntrack_max = 131072

Verwenden Sie das Flag-w, um einen neuen Wert festzulegen:

sysctl -w net.netfilter.nf_conntrack_max=198000

Um diese Einstellung dauerhaft zu machen, fügen Sie sie der Dateisysctl.confhinzu:

/etc/sysctl.conf

. . .
net.ipv4.netfilter.ip_conntrack_max = 198000

Regeln für die Überprüfung von Iptables

Vor Version 1.11 verwendete Kubernetes iptables NAT, um die virtuelle IP-Übersetzung und den Lastenausgleich für Service-IPs zu implementieren.

Verwenden Sie den Befehliptables-save, um alle iptables-Regeln auf einem Knoten abzulegen:

iptables-save

Da die Ausgabe langwierig sein kann, möchten Sie möglicherweise zu einer Datei (iptables-save > output.txt) oder einem Pager (iptables-save | less) weiterleiten, um die Regeln einfacher überprüfen zu können.

Verwenden Sie den Befehliptables und das Flag-L, um nur die NAT-Regeln des Kubernetes-Dienstes aufzulisten und die richtige Kette anzugeben:

iptables -t nat -L KUBE-SERVICES
OutputChain KUBE-SERVICES (2 references)
target     prot opt source               destination
KUBE-SVC-TCOU7JCQXEZGVUNU  udp  --  anywhere             10.32.0.10           /* kube-system/kube-dns:dns cluster IP */ udp dpt:domain
KUBE-SVC-ERIFXISQEP7F7OF4  tcp  --  anywhere             10.32.0.10           /* kube-system/kube-dns:dns-tcp cluster IP */ tcp dpt:domain
KUBE-SVC-XGLOHA7QRQ3V22RZ  tcp  --  anywhere             10.32.226.209        /* kube-system/kubernetes-dashboard: cluster IP */ tcp dpt:https
. . .

Cluster-DNS abfragen

Eine Möglichkeit zum Debuggen Ihrer Cluster-DNS-Auflösung besteht darin, einen Debug-Container mit allen benötigten Tools bereitzustellen und dannkubectl zu verwenden, umnslookup darauf auszuführen. Dies ist inthe official Kubernetes documentation beschrieben.

Eine andere Möglichkeit, den Cluster-DNS abzufragen, besteht darin,dig undnsenter von einem Knoten zu verwenden. Wenndig nicht installiert ist, kann es mitapt auf Debian-basierten Linux-Distributionen installiert werden:

apt install dnsutils

Ermitteln Sie zunächst die Cluster-IP des Diensteskube-dns:

kubectl get service -n kube-system kube-dns
OutputNAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
kube-dns   ClusterIP   10.32.0.10           53/UDP,53/TCP   15d

Die Cluster-IP ist oben hervorgehoben. Als Nächstes verwenden wirnsenter, umdig im a-Container-Namespace auszuführen. Weitere Informationen hierzu finden Sie im AbschnittFinding and Entering Pod Network Namespaces:

nsenter -t 14346 -n dig kubernetes.default.svc.cluster.local @10.32.0.10

Dieser Befehldig sucht den vollständigen Domänennamen des Dienstes vonservice-name.namespace.svc.cluster.local und gibt die IP der IP-Adresse des Cluster-DNS-Dienstes (@10.32.0.10) an.

IPVS-Details anzeigen

Ab Kubernetes 1.11 könnenkube-proxyIPVS so konfigurieren, dass die Übersetzung von virtuellen Service-IPs in Pod-IPs erfolgt. Sie können die Übersetzungstabelle von IPs mitipvsadm auflisten:

ipvsadm -Ln
OutputIP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  100.64.0.1:443 rr
  -> 178.128.226.86:443           Masq    1      0          0
TCP  100.64.0.10:53 rr
  -> 100.96.1.3:53                Masq    1      0          0
  -> 100.96.1.4:53                Masq    1      0          0
UDP  100.64.0.10:53 rr
  -> 100.96.1.3:53                Masq    1      0          0
  -> 100.96.1.4:53                Masq    1      0          0

Verwenden Sie zum Anzeigen einer einzelnen Dienst-IP die Option-t und geben Sie die gewünschte IP an:

ipvsadm -Ln -t 100.64.0.10:53
OutputProt LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  100.64.0.10:53 rr
  -> 100.96.1.3:53                Masq    1      0          0
  -> 100.96.1.4:53                Masq    1      0          0

Fazit

In diesem Artikel haben wir einige Befehle und Techniken zum Erkunden und Untersuchen der Details des Netzwerks Ihres Kubernetes-Clusters besprochen. Weitere Informationen zu Kubernetes finden Sie unterour Kubernetes tutorials tag undthe official Kubernetes documentation.