Cette page explique comment résoudre les problèmes de connectivité dans votre cluster.
Problèmes de connectivité liés à la capture de paquets réseau dans GKE
Cette section explique comment résoudre les problèmes de connectivité liés à la capture des paquets réseau, y compris les symptômes tels que expirations de connexions, les erreurs de connexion refusée ou les comportements d'application inattendus. Ces problèmes de connectivité peuvent se produire au niveau du nœud ou du pod.
Les problèmes de connectivité de votre réseau de cluster relèvent souvent des catégories suivantes :
- Pods non accessibles : un pod peut ne pas être accessible depuis l'intérieur ou l'extérieur du cluster en raison d'une mauvaise configuration réseau.
- Interruptions de service : un service peut subir des interruptions ou des retards.
- Problèmes de communication entre pods : les pods peuvent ne pas être en mesure de communiquer efficacement entre eux.
Les problèmes de connectivité de votre cluster GKE peuvent provenir de diverses causes, y compris les suivantes :
- Mauvaise configuration réseau : stratégies réseau, règles de pare-feu ou tables de routage incorrectes.
- Bugs d'application : erreurs affectant les interactions réseau dans le code d'application.
- Problèmes d'infrastructure : congestion du réseau, défaillances matérielles ou limites de ressources.
La section suivante montre comment résoudre le problème sur les nœuds ou les pods problématiques.
Identifiez le nœud sur lequel le pod problématique s'exécute à l'aide de la commande suivante :
kubectl get pods
POD_NAME -o=wide -nNAMESPACE Remplacez les éléments suivants :
POD_NAME
par le nom du pod.NAMESPACE
par l'espace de noms Kubernetes.
Connectez-vous au nœud :
gcloud compute ssh
NODE_NAME \ --zone=ZONE Remplacez les éléments suivants :
NODE_NAME
: nom de votre nœud.ZONE
: nom de la zone dans laquelle le nœud s'exécute.
Pour déboguer un pod spécifique, identifiez l'interface
veth
associée au pod :ip route | grep
POD_IP Remplacez
POD_IP
par l'adresse IP du pod.Exécutez les commandes de la boîte à outils.
Commandes toolbox
toolbox
est un utilitaire qui fournit un environnement conteneurisé dans vos nœuds GKE pour le débogage et le dépannage. Cette section explique comment installer l'utilitaire toolbox
et l'utiliser pour résoudre les problèmes liés au nœud.
Lorsque vous êtes connecté au nœud, démarrez l'outil
toolbox
:toolbox
Les fichiers qui facilitent l'utilitaire
toolbox
sont téléchargés.Dans l'invite racine
toolbox
, installeztcpdump
:Pour les clusters avec des adresses IP externes ou Cloud NAT :
apt update -y && apt install -y tcpdump
Pour les clusters privés sans Cloud NAT :
Si vous disposez d'un cluster privé sans Cloud NAT, vous ne pouvez pas installer
tcpdump
à l'aide deapt
. Au lieu de cela, téléchargez les fichiers de versionlibpcap
ettcpdump
à partir du dépôt officiel, puis copiez-les fichiers sur la VM à l'aide degcloud compute scp
ougsutil
. Installez ensuite les bibliothèques manuellement en procédant comme suit :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 --versionRemplacez les éléments suivants :
USER_NAME
: votre nom d'utilisateur sur le système où se trouvent les fichiers.VERSION
: numéro de version spécifique des packagestcpdump
etlibpcap
.
Lancez la capture de paquets :
tcpdump -i eth0 -s 100 "port
PORT " \ -w /media/root/mnt/stateful_partition/CAPTURE_FILE_NAME Remplacez les éléments suivants :
PORT
: nom de votre numéro de port.CAPTURE_FILE_NAME
: nom de votre fichier de capture.
Arrêtez la capture de paquets et interrompez
tcpdump
.Quittez la boîte à outils en saisissant
exit
.Listez le fichier de capture de paquets et vérifiez sa taille :
ls -ltr /mnt/stateful_partition/
CAPTURE_FILE_NAME Copiez la capture de paquets du nœud vers le répertoire de travail actuel de votre ordinateur :
gcloud compute scp
NODE_NAME :/mnt/stateful_partition/CAPTURE_FILE_NAME \ --zone=ZONE Remplacez les éléments suivants :
NODE_NAME
: nom de votre nœud.CAPTURE_FILE_NAME
: nom de votre fichier de capture.ZONE
: nom de votre zone.
Autres commandes
Vous pouvez également utiliser les méthodes suivantes pour résoudre les problèmes de connectivité sur les pods problématiques :
Charge de travail de débogage éphémère associée au conteneur du pod.
Exécutez un shell directement sur le pod cible à l'aide de
kubectl exec
, puis installez et lancez la commandetcpdump
.
Problèmes de connectivité réseau du pod
Comme indiqué dans la partie Présentation du réseau, il est important de comprendre comment les pods sont connectés entre leurs espaces de noms réseau et l'espace de noms racine sur le nœud afin de procéder au dépannage de façon efficace. Dans la démonstration suivante, sauf indication contraire, nous supposerons que le cluster utilise la CNI native (Container Network Interface) de GKE plutôt que celle de Calico. C'est-à-dire qu'aucune stratégie réseau n'a été appliquée.
Les pods sur les nœuds sélectionnés n'ont pas de disponibilité
Si les pods sur certains nœuds ne disposent pas d'une connectivité réseau, assurez-vous que le pont Linux est actif :
ip address show cbr0
Si le pont Linux est arrêté, activez-le :
sudo ip link set cbr0 up
Assurez-vous que le nœud apprend les adresses MAC du pod associées à cbr0 :
arp -an
La connectivité des pods sur certains nœuds est minimale
Si les pods sur certains nœuds ont une connectivité minimale, vous devez d’abord rechercher une perte de paquets éventuelle en exécutant la commande tcpdump
dans le conteneur de la boîte à outils :
sudo toolbox bash
Installez tcpdump
dans la boîte à outils si ce n'est déjà fait :
apt install -y tcpdump
Exécutez tcpdump
sur cbr0 :
tcpdump -ni cbr0 host HOSTNAME and port PORT_NUMBER and [TCP|UDP|ICMP]
Si vous constatez que des paquets volumineux sont rejetés en aval du pont (par exemple, le handshake TCP a bien lieu, mais aucun "hello" SSL n'est reçu), assurez-vous que la MTU de chaque interface de pod Linux est correctement définie sur la MTU deRéseau VPC du cluster.
ip address show cbr0
En cas d'utilisation de superpositions (par exemple, Weave ou Flannel), cette MTU doit être encore réduite pour tolérer la surcharge d'encapsulation sur la superposition.
MTU GKE
La MTU sélectionnée pour une interface de pod dépend de l'interface CNI (Container Network Interface) utilisée par les nœuds du cluster et du paramètre de MTU sous-jacent du VPC. Pour en savoir plus, consultez la section Pods.
La valeur de la MTU de l'interface de pod est 1460
ou héritée de l'interface principale du nœud.
CNI | MTU | GKE Standard |
---|---|---|
kubenet | 1460 | Par défaut |
kubenet (version 1.26.1 de GKE et versions ultérieures) |
Hérité | Par défaut |
Calico | 1460 |
Activation à l'aide de Pour en savoir plus, consultez la page Contrôler la communication entre les pods et les services à l'aide de règles de réseau. |
netd | Hérité | Activation à l'aide de l'une des options suivantes : |
GKE Dataplane V2 | Hérité |
Activation à l'aide de Pour en savoir plus, consultez la page Utiliser GKE Dataplane V2. |
Échecs de connexion intermittents
Les connexions vers et depuis les pods sont transférées au moyen de règles iptables. Les flux sont suivis en tant qu'entrées dans la table conntrack et, lorsqu'il existe de nombreuses charges de travail par nœud, l'épuisement de la table conntrack peut se traduire par un échec. Ceux-ci peuvent être enregistrés dans la console série du nœud, par exemple :
nf_conntrack: table full, dropping packet
Si vous parvenez à déterminer que les déconnexions intermittentes sont liées à l'épuisement de conntrack, augmentez la taille du cluster (réduisant ainsi le nombre de charges de travail et de flux par nœud), ou augmentez nf_conntrack_max
:
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
Vous pouvez également utiliser NodeLocal DNSCache pour réduire les entrées de suivi de connexion.
"Liaison : adresse déjà utilisée" signalé pour un conteneur
Un conteneur dans un pod ne parvient pas à démarrer car, d'après les journaux du conteneur, le port auquel l'application tente de se connecter est déjà réservé. Le conteneur est bloqué dans une boucle de plantage. Par exemple, dans 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
Lorsque Docker plante, un conteneur en cours d'exécution est parfois laissé de côté et n'est plus actualisé. Le processus est toujours en cours d'exécution dans l'espace de noms réseau attribué au pod et en écoute sur son port. Comme Docker et le kubelet ignorent que le conteneur est obsolète, ils tentent de démarrer un nouveau conteneur avec un nouveau processus, qui ne peut pas se connecter au port puisqu'il est ajouté à l'espace de nom réseau déjà associé au pod.
Pour diagnostiquer ce problème, procédez comme suit :
Vous avez besoin de l'UUID du pod dans le champ
.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
Obtenez le résultat des commandes suivantes à partir du nœud :
docker ps -a ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep [Pod UUID]
Vérifiez les processus en cours depuis ce pod. Comme l'UUID des espaces de noms cgroup contient l'UUID du pod, vous pouvez utiliser une commande grep pour le pod UUID dans le résultat
ps
. Appliquez également une commande grep à la ligne précédente, de façon à obtenir les processusdocker-containerd-shim
qui contiennent aussi l'identifiant du conteneur dans l'argument. Coupez le reste de la colonne cgroup pour simplifier la sortie obtenue :# 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
Dans cette liste, les identifiants de conteneur s'affichent et devraient également être visibles dans
docker ps
.Dans ce cas :
docker-containerd-shim 276e173b0846e24b704d4
pour la mise en pausedocker-containerd-shim ab4c7762f5abf40951770
pour sh avec mise en veille (sleep-ctr)docker-containerd-shim 44e76e50e5ef4156fd5d3
pour nginx (echoserver-ctr)
Vérifiez les identifiants dans le résultat de
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
Normalement, tous les identifiants de conteneur de
ps
apparaissent dansdocker ps
. Si l'un d'entre eux n'apparaît pas, il s'agit d'un conteneur obsolète, et vous verrez probablement un processus enfant dedocker-containerd-shim process
en écoute sur le port TCP signalé comme déjà utilisé.Pour le vérifier, exécutez la commande
netstat
dans l'espace de noms réseau du conteneur. Récupérez le pid d'un processus de conteneur pour le pod (et NONdocker-containerd-shim
).Dans l'exemple précédent :
- 1283107 - pause
- 1283169 - sh
- 1283185 - veille
- 1283263 - maître nginx
- 1283282 - nœud de calcul nginx
# 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
Vous pouvez également exécuter
netstat
en utilisantip netns
, mais vous devez relier manuellement l'espace de noms réseau du processus, car Docker n'effectue par la liaison :# 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
Atténuation :
L'atténuation à court terme consiste à identifier les processus obsolètes à l'aide de la méthode décrite précédemment, puis à les éliminer en exécutant la commande kill [PID]
.
L'atténuation à long terme consiste à identifier l'origine des plantages de Docker et à y remédier. Voici les différents motifs possibles :
- Les processus zombies s'empilent et les espaces de noms PID deviennent insuffisants
- Bug dans Docker
- Ressource saturée/OOM
Étape suivante
- Pour obtenir des informations générales sur l'analyse des problèmes de DNS de Kubernetes, consultez la section Déboguer la résolution DNS.