Auf dieser Seite wird beschrieben, wie Sie Verbindungsprobleme in Ihrem Cluster beheben.
Verbindungsprobleme beim Erfassen von Netzwerkpaketen in GKE
In diesem Abschnitt wird beschrieben, wie Sie Verbindungsprobleme im Zusammenhang mit der Erfassung von Netzwerkpaketen beheben, z. B. Symptome wie Zeitüberschreitungen bei der Verbindung, Fehler aufgrund abgelehnter Verbindungen oder unerwartetes Anwendungsverhalten. Diese Verbindungsprobleme können auf Knoten- oder Podebene auftreten.
Verbindungsprobleme in Ihrem Clusternetzwerk fallen häufig in eine der folgenden Kategorien:
- Pods nicht erreichbar: Auf einen Pod kann aufgrund von Netzwerkfehlern möglicherweise nicht von innerhalb oder außerhalb des Clusters zugegriffen werden.
- Dienstunterbrechungen: Bei einem Dienst kann es zu Unterbrechungen oder Verzögerungen kommen.
- Kommunikationsprobleme zwischen Pods: Pods können möglicherweise nicht effektiv miteinander kommunizieren.
Verbindungsprobleme in Ihrem GKE-Cluster können verschiedene Ursachen haben, darunter:
- Fehlkonfigurationen des Netzwerks: Falsche Netzwerkrichtlinien, Firewallregeln oder Routingtabellen.
- Anwendungsfehler: Fehler im Anwendungscode, die sich auf Netzwerkinteraktionen auswirken.
- Infrastrukturprobleme: Netzwerküberlastung, Hardwarefehler oder Ressourceneinschränkungen.
Im folgenden Abschnitt wird gezeigt, wie Sie das Problem bei den problematischen Knoten oder Pods beheben.
Ermitteln Sie mit dem folgenden Befehl den Knoten, auf dem der problematische Pod ausgeführt wird:
kubectl get pods POD_NAME -o=wide -n NAMESPACE
Ersetzen Sie Folgendes:
POD_NAME
durch den Namen des -Pods.NAMESPACE
durch den Kubernetes-Namespace.
Stellen Sie eine Verbindung zum Knoten her:
gcloud compute ssh NODE_NAME \ --zone=ZONE
Ersetzen Sie Folgendes:
NODE_NAME
: Name Ihres Knotens.ZONE
: Name der Zone, in der der Knoten ausgeführt wird.
Wenn Sie einen bestimmten Pod debuggen möchten, ermitteln Sie die
veth
-Schnittstelle, die mit dem Pod verknüpft ist:ip route | grep POD_IP
Ersetzen Sie
POD_IP
durch die Pod-IP-Adresse.Führen Sie die Toolbox-Befehle aus.
toolbox
-Befehle
toolbox
ist ein Dienstprogramm, das eine containerisierte Umgebung in Ihren GKE-Knoten für das Debuggen und die Fehlerbehebung bereitstellt. In diesem Abschnitt wird beschrieben, wie Sie das Dienstprogramm toolbox
installieren und damit Fehler am Knoten beheben.
Starten Sie das
toolbox
-Tool, während Sie mit dem Knoten verbunden sind:toolbox
Dadurch werden die Dateien heruntergeladen, die das
toolbox
-Dienstprogramm unterstützen.Installieren Sie
tcpdump
in der Root-Eingabeaufforderungtoolbox
:Für Cluster mit externen IP-Adressen oder Cloud NAT:
apt update -y && apt install -y tcpdump
Für private Cluster ohne Cloud NAT:
Wenn Sie einen privaten Cluster ohne Cloud NAT haben, können Sie
tcpdump
nicht mitapt
installieren. Laden Sie stattdessen die Release-Dateienlibpcap
undtcpdump
aus dem offiziellen Repository herunter und kopieren Sie sie mitgcloud compute scp
odergsutil
auf die VM. Installieren Sie die Bibliotheken dann manuell mit den folgenden Schritten:cp /media/root/home/USER_NAME/tcpdump-VERSION.tar.gz /usr/sbin/ cp /media/root/home/USER_NAME/libpcap-VERSION.tar.gz /usr/sbin/ cd /usr/sbin/ tar -xvzf tcpdump-VERSION.tar.gz tar -xvzf libpcap-VERSION.tar.gz cd libpcap-VERSION ./configure ; make ; make install cd ../tcpdump-VERSION ./configure ; make ; make install tcpdump --version
Ersetzen Sie Folgendes:
USER_NAME
: Ihr Nutzername auf dem System, auf dem sich die Dateien befinden.VERSION
: Die spezifische Versionsnummer dertcpdump
- undlibpcap
-Pakete.
Starten Sie die Paketerfassung:
tcpdump -i eth0 -s 100 "port PORT" \ -w /media/root/mnt/stateful_partition/CAPTURE_FILE_NAME
Ersetzen Sie Folgendes:
PORT
: Name Ihrer Portnummer.CAPTURE_FILE_NAME
: Name der Aufnahmedatei.
Beenden Sie die Paketerfassung und unterbrechen Sie die
tcpdump
.Verlassen Sie die Toolbox, indem Sie
exit
eingeben.Liste der Paket-Capture-Datei aufrufen und Größe prüfen:
ls -ltr /mnt/stateful_partition/CAPTURE_FILE_NAME
Kopieren Sie die Paketerfassung vom Knoten in das aktuelle Arbeitsverzeichnis auf Ihrem Computer:
gcloud compute scp NODE_NAME:/mnt/stateful_partition/CAPTURE_FILE_NAME \ --zone=ZONE
Ersetzen Sie Folgendes:
NODE_NAME
: Name Ihres Knotens.CAPTURE_FILE_NAME
: Name der Aufnahmedatei.ZONE
: Name der Zone.
Alternative Befehle
Sie können auch die folgenden Methoden verwenden, um Verbindungsprobleme bei den problematischen Pods zu beheben:
Sitzungsspezifische Debugging-Arbeitslast, die an den Pod-Container angehängt ist.
Führen Sie mit
kubectl exec
eine Shell direkt auf dem Ziel-Pod aus und installieren Sie dann den Befehltcpdump
.
Probleme mit der Pod-Netzwerkverbindung
Damit Sie Fehler erfolgreich beheben können, sollten Sie wissen, wie die Netzwerk-Namespaces von Pods mit dem Stamm-Namespace auf dem Knoten verbunden sind (siehe Netzwerkübersicht). Gehen Sie bei der folgenden Erläuterung davon aus, dass der Cluster das native CNI von GKE und nicht das CNI von Calico verwendet (sofern nicht anders angegeben). Das heißt, es wurde keine Netzwerkrichtlinie angewendet.
Pods auf bestimmten Knoten sind nicht verfügbar
Wenn Pods auf bestimmten Knoten keine Netzwerkverbindung haben, prüfen Sie, ob die Linux-Bridge aktiv ist:
ip address show cbr0
Wenn die Linux-Bridge nicht aktiv ist, starten Sie sie:
sudo ip link set cbr0 up
Prüfen Sie, ob der Knoten Pod-MAC-Adressen in Erfahrung bringt, die zu cbr0 gehören:
arp -an
Pods auf bestimmten Knoten haben nur minimale Konnektivität
Wenn Pods auf bestimmten Knoten nur minimale Konnektivität haben, sollten Sie zuerst prüfen, ob Pakete verloren gegangen sind. Führen Sie dazu tcpdump
im Toolbox-Container aus:
sudo toolbox bash
Installieren Sie tcpdump
in der Toolbox, wenn nicht bereits geschehen:
apt install -y tcpdump
Führen Sie tcpdump
für cbr0 aus:
tcpdump -ni cbr0 host HOSTNAME and port PORT_NUMBER and [TCP|UDP|ICMP]
Wenn es so aussieht, als würden große Pakete nach der Bridge verloren gehen (der TCP-Handshake wird beispielsweise abgeschlossen, es gehen aber keine SSL-Hellos ein), prüfen Sie, ob die MTU für jede Linux-Pod-Schnittstelle richtig auf die die MTU des VPC-Netzwerks des Clusters festgelegt ist.
ip address show cbr0
Wenn Overlays verwendet werden (z. B. Weave oder Flannel), muss dieser MTU-Wert weiter reduziert werden, um Kapselungsoverhead für das Overlay aufzufangen.
GKE-MTU
Die für eine Pod-Schnittstelle ausgewählte MTU hängt von der von den Clusterknoten verwendeten Container Network Interface (CNI) und der zugrunde liegenden VPC-MTU-Einstellung ab. Weitere Informationen finden Sie unter Pods.
Der MTU-Wert der Pod-Schnittstelle ist entweder 1460
oder wird von der primären Schnittstelle des Knotens übernommen.
CNI | MTU | GKE Standard |
---|---|---|
kubenet | 1460 | Standard |
kubenet (GKE-Version 1.26.1 und höher) |
Übernommen | Standard |
Calico | 1460 |
Aktiviert mit Weitere Informationen finden Sie unter Kommunikation zwischen Pods und Services mithilfe von Netzwerkrichtlinien steuern. |
netd | Übernommen | Aktiviert durch Verwendung einer der folgenden Optionen: |
GKE Dataplane V2 | Übernommen |
Aktiviert mit Weitere Informationen finden Sie unter GKE Dataplane V2 verwenden. |
Zeitweise fehlgeschlagene Verbindungen
Verbindungen zu und von den Pods werden von iptables weitergeleitet. Datenflüsse werden als Einträge in der Conntrack-Tabelle verfolgt. Wenn viele Arbeitslasten pro Knoten vorhanden sind, kann die Überfüllung der Conntrack-Tabelle zu einem Fehler führen. Solche Fehler können in der seriellen Konsole des Knotens protokolliert werden. Beispiel:
nf_conntrack: table full, dropping packet
Wenn sich zeitweise auftretende Probleme auf eine volle Conntrack-Tabelle zurückführen lassen, können Sie die Größe des Clusters erhöhen, um die Anzahl der Arbeitslasten und Datenflüsse pro Knoten zu reduzieren, oder nf_conntrack_max
erhöhen:
new_ct_max=$(awk '$1 == "MemTotal:" { printf "%d\n", $2/32; exit; }' /proc/meminfo)
sysctl -w net.netfilter.nf_conntrack_max="${new_ct_max:?}" \
&& echo "net.netfilter.nf_conntrack_max=${new_ct_max:?}" >> /etc/sysctl.conf
Sie können auch NodeLocal DNSCache verwenden, um Einträge für das Verbindungs-Tracking zu reduzieren.
„bind: Address already in use“ wird für einen Container gemeldet
Aus den Containerlogs geht hervor, dass ein Container in einem Pod nicht gestartet werden kann, da der Port, an den sich die Anwendung binden möchte, bereits reserviert ist. Der Container gerät in eine Absturzschleife. Zum Beispiel in Cloud Logging:
resource.type="container"
textPayload:"bind: Address already in use"
resource.labels.container_name="redis"
2018-10-16 07:06:47.000 CEST 16 Oct 05:06:47.533 # Creating Server TCP listening socket *:60250: bind: Address already in use
2018-10-16 07:07:35.000 CEST 16 Oct 05:07:35.753 # Creating Server TCP listening socket *:60250: bind: Address already in use
Wenn Docker abstürzt, wird manchmal ein veralteter Container weiterhin ausgeführt. Der Prozess läuft im Netzwerk-Namespace weiter, der dem Pod zugewiesen ist, und überwacht seinen Port. Da Docker und das kubelet nichts von dem veralteten Container wissen, versuchen sie, einen neuen Container mit einem neuen Prozess zu starten. Dieser Prozess kann sich jedoch nicht an den Port binden, da er dem Netzwerk-Namespace hinzugefügt wird, der bereits mit dem Pod verknüpft ist.
So diagnostizieren Sie dieses Problem:
Sie benötigen die UUID des Pods im Feld
.metadata.uuid
:kubectl get pod -o custom-columns="name:.metadata.name,UUID:.metadata.uid" ubuntu-6948dd5657-4gsgg name UUID ubuntu-6948dd5657-4gsgg db9ed086-edba-11e8-bdd6-42010a800164
Rufen Sie die Ausgabe der folgenden Befehle vom Knoten ab:
docker ps -a ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep [Pod UUID]
Prüfen Sie die laufenden Prozesse von diesem Pod. Da die UUID der cgroup-Namespaces die UUID des Pods enthält, können Sie die Pod-UUID mit grep in
ps
ausgeben. Rufen Sie auch die Zeile davor mit grep ab, sodass Sie diedocker-containerd-shim
-Prozesse erhalten, die auch die Container-ID im Argument haben. Schneiden Sie den Rest der cgroup-Spalte ab, um die Ausgabe zu vereinfachen:# ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep -B 1 db9ed086-edba-11e8-bdd6-42010a800164 | sed s/'blkio:.*'/''/ 1283089 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim 276e173b0846e24b704d4 12: 1283107 1283089 Ss sys_pause 4026532393 pause /pause 12: 1283150 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim ab4c7762f5abf40951770 12: 1283169 1283150 Ss do_wait 4026532393 sh /bin/sh -c echo hello && sleep 6000000 12: 1283185 1283169 S hrtimer_nanosleep 4026532393 sleep sleep 6000000 12: 1283244 959 Sl futex_wait_queue_me 4026531993 docker-co docker-containerd-shim 44e76e50e5ef4156fd5d3 12: 1283263 1283244 Ss sigsuspend 4026532393 nginx nginx: master process nginx -g daemon off; 12: 1283282 1283263 S ep_poll 4026532393 nginx nginx: worker process
Dieser Liste können Sie die Container-IDs entnehmen, die auch in
docker ps
sichtbar sein sollten.In diesem Fall:
docker-containerd-shim 276e173b0846e24b704d4
für pausedocker-containerd-shim ab4c7762f5abf40951770
für sh mit sleep (sleep-ctr)docker-containerd-shim 44e76e50e5ef4156fd5d3
für nginx (echoserver-ctr)
Prüfen Sie diese in der Ausgabe von
docker ps
:# docker ps --no-trunc | egrep '276e173b0846e24b704d4|ab4c7762f5abf40951770|44e76e50e5ef4156fd5d3' 44e76e50e5ef4156fd5d383744fa6a5f14460582d0b16855177cbed89a3cbd1f gcr.io/google_containers/echoserver@sha256:3e7b182372b398d97b747bbe6cb7595e5ffaaae9a62506c725656966d36643cc "nginx -g 'daemon off;'" 14 hours ago Up 14 hours k8s_echoserver-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0 ab4c7762f5abf40951770d3e247fa2559a2d1f8c8834e5412bdcec7df37f8475 ubuntu@sha256:acd85db6e4b18aafa7fcde5480872909bd8e6d5fbd4e5e790ecc09acc06a8b78 "/bin/sh -c 'echo hello && sleep 6000000'" 14 hours ago Up 14 hours k8s_sleep-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0 276e173b0846e24b704d41cf4fbb950bfa5d0f59c304827349f4cf5091be3327 registry.k8s.io/pause-amd64:3.1
Normalerweise werden alle Container-IDs aus
ps
indocker ps
angezeigt. Wenn Sie eine ID nicht sehen, ist der Container veraltet. Wahrscheinlich sehen Sie dann einen untergeordneten Prozess vondocker-containerd-shim process
, der den TCP-Port überwacht, der als bereits verwendet gemeldet wird.Damit Sie das prüfen können, führen Sie
netstat
im Netzwerk-Namespace des Containers aus. Rufen Sie die PID eines beliebigen Containerprozesses (jedoch NICHTdocker-containerd-shim
) für den Pod ab.Aus dem vorherigen Beispiel:
- 1283107 – pause
- 1283169 – sh
- 1283185 – sleep
- 1283263 – nginx-Master
- 1283282 – nginx-Worker
# nsenter -t 1283107 --net netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast gke-zonal-110-default-pool-fe00befa-n2hx ~ # nsenter -t 1283169 --net netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast
Sie können auch
netstat
mitip netns
ausführen, müssen jedoch den Netzwerk-Namespace des Prozesses manuell verbinden, da Docker die Verbindung nicht herstellt:# ln -s /proc/1283169/ns/net /var/run/netns/1283169 gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns list 1283169 (id: 2) gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns exec 1283169 netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1283263/nginx: mast Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 3 [ ] STREAM CONNECTED 3097406 1283263/nginx: mast unix 3 [ ] STREAM CONNECTED 3097405 1283263/nginx: mast gke-zonal-110-default-pool-fe00befa-n2hx ~ # rm /var/run/netns/1283169
Abhilfe:
Zur vorläufigen Abhilfe können Sie veraltete Prozesse mit der zuvor beschriebenen Methode identifizieren und die Prozesse mit dem Befehl kill [PID]
beenden.
Zur langfristigen Abhilfe müssen Sie feststellen, warum Docker abstürzt, und dieses Problem beheben. Mögliche Gründe:
- Es sammeln sich Zombie-Prozesse an, sodass PID-Namespaces ausgehen
- Programmfehler in Docker
- Ressourcenknappheit/nicht genügend Arbeitsspeicher
Nächste Schritte
- Allgemeine Informationen zur Diagnose von Kubernetes DNS-Problemen finden Sie unter Debugging bei der DNS-Auflösung.