introduction
Kubernetes est un système d'orchestration de conteneur capable de gérer des applications conteneurisées sur un cluster de nœuds de serveur. Le maintien de la connectivité réseau entre tous les conteneurs d'un cluster nécessite des techniques réseau avancées. Dans cet article, nous aborderons brièvement quelques outils et techniques permettant d'inspecter cette configuration réseau.
Ces outils peuvent être utiles si vous corrigez des problèmes de connectivité, étudiez des problèmes de débit du réseau ou explorez Kubernetes pour en apprendre plus sur son fonctionnement.
Si vous souhaitez en savoir plus sur Kubernetes en général, notre guideAn Introduction to Kubernetes couvre les bases. Pour un aperçu de Kubernetes spécifique au réseau, veuillez lireKubernetes Networking Under the Hood.
Commencer
Ce didacticiel suppose que vous disposez d'un cluster Kubernetes, aveckubectl
installé localement et configuré pour se connecter au cluster.
Les sections suivantes contiennent de nombreuses commandes destinées à être exécutées sur un nœud Kubernetes. Ils vont ressembler à ceci:
echo 'this is a node command'
Les commandes devant être exécutées sur votre ordinateur local auront l'aspect suivant:
echo 'this is a local command'
[.note] #Note: La plupart des commandes de ce didacticiel devront être exécutées en tant qu'utilisateurroot. Si vous utilisez à la place un utilisateur sudo sur vos nœuds Kubernetes, ajoutezsudo
pour exécuter les commandes si nécessaire.
#
Recherche d’une IP de cluster du pod
Pour trouver l'adresse IP du cluster d'un pod Kubernetes, utilisez la commandekubectl get pod
sur votre machine locale, avec l'option-o wide
. Cette option répertorie davantage d’informations, notamment le nœud sur lequel se trouve le pod et l’adresse IP du cluster du pod.
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
La colonneIP contiendra l'adresse IP du cluster interne pour chaque pod.
Si vous ne voyez pas le pod que vous recherchez, assurez-vous que vous êtes dans le bon espace de noms. Vous pouvez lister tous les pods dans tous les espaces de noms en ajoutant l'indicateur--all-namespaces
.
Recherche de l’adresse IP d’un service
Nous pouvons également trouver une adresse IP de service en utilisantkubectl
. Dans ce cas, nous listerons tous les services dans tous les espaces de noms:
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
L'adresse IP du service se trouve dans la colonneCLUSTER-IP.
Recherche et entrée d'espaces de noms de réseau de pod
Chaque pod Kubernetes se voit attribuer son propre espace de noms réseau. Les espaces de noms réseau (ou réseaux) sont une primitive réseau Linux qui fournit une isolation entre les périphériques réseau.
Il peut être utile d’exécuter des commandes à partir des réseaux d’un pod, pour vérifier la résolution DNS ou la connectivité générale du réseau. Pour ce faire, nous devons d’abord rechercher l’ID de processus de l’un des conteneurs d’un conteneur. Pour Docker, nous pouvons le faire avec une série de deux commandes. Commencez par répertorier les conteneurs s'exécutant sur un nœud:
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
. . .
Recherchez lescontainer ID ouname de n'importe quel conteneur du pod qui vous intéresse. Dans la sortie ci-dessus, nous montrons deux conteneurs:
-
Le premier conteneur est l'application
hello-world
exécutée dans le podhello-world
-
Le second est un conteneurpause exécuté dans le pod
hello-world
. Ce conteneur existe uniquement pour conserver l’espace de noms réseau du pod
Pour obtenir l'ID de processus de l'un ou l'autre conteneur, notez l'ID ou le nom du conteneur et utilisez-le dans la commandedocker
suivante:
docker inspect --format '{{ .State.Pid }}' container-id-or-name
Output14552
Un identifiant de processus (ou PID) sera généré. Nous pouvons maintenant utiliser le programmensenter
pour exécuter une commande dans l’espace de nom réseau de ce processus:
nsenter -t your-container-pid -n ip addr
Veillez à utiliser votre propre PID et remplacezip addr
par la commande que vous souhaitez exécuter dans l’espace de nom réseau du pod.
[.note] #Note: Un avantage de l'utilisation densenter
pour exécuter des commandes dans l'espace de noms d'un pod - par rapport à quelque chose commedocker exec
- est que vous avez accès à toutes les commandes disponibles sur le nœud, au lieu de l'ensemble généralement limité de commandes installées dans les conteneurs.
#
Recherche de l’interface Ethernet virtuelle d’un pod
Chaque espace de noms réseau de chaque pod communique avec les réseaux racine du nœud via un canal Ethernet virtuel. Du côté du nœud, ce tube apparaît comme un périphérique qui commence généralement parveth
et se termine par un identifiant unique, tel queveth77f2275
ouveth01
. À l'intérieur du pod, ce tube apparaît sous la formeeth0
.
Il peut être utile de corréler le périphériqueveth
associé à un pod particulier. Pour ce faire, nous allons répertorier tous les périphériques réseau sur le nœud, puis les périphériques dans l’espace de noms réseau du pod. Nous pouvons ensuite corréler les numéros d'appareils entre les deux listes pour établir la connexion.
Tout d'abord, exécutezip addr
dans l'espace de noms réseau du pod à l'aide densenter
. Reportez-vous à la section précédenteFinding and Entering Pod Network Namespaces
pour plus de détails sur la façon de procéder:
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
La commande affichera une liste des interfaces du pod. Notez le nombreif11
aprèseth0@
dans l'exemple de sortie. Cela signifie que leeth0
de ce pod est lié à la 11e interface du nœud. Exécutez maintenantip addr
dans l’espace de noms par défaut du nœud pour lister ses interfaces:
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
La 11ème interface estveth4f7342d
dans cet exemple de sortie. C’est le canal Ethernet virtuel vers le pod sur lequel nous travaillons.
Inspection du suivi de la connexion Conntrack
Avant la version 1.11, Kubernetes utilisait le NAT iptables et le module de noyau conntrack pour suivre les connexions. Pour lister toutes les connexions en cours de suivi, utilisez la commandeconntrack
:
conntrack -L
Pour surveiller en permanence les nouvelles connexions, utilisez l'indicateur-E
:
conntrack -E
Pour répertorier les connexions suivies par conntrack à une adresse de destination particulière, utilisez l'indicateur-d
:
conntrack -L -d 10.32.0.1
Si vos noeuds rencontrent des problèmes pour établir des connexions fiables aux services, il est possible que votre table de suivi des connexions soit saturée et que de nouvelles connexions soient abandonnées. Si tel est le cas, des messages tels que les suivants apparaissent dans les journaux de votre système:
/var/log/syslog
Jul 12 15:32:11 worker-528 kernel: nf_conntrack: table full, dropping packet.
Il existe un paramètre sysctl pour le nombre maximal de connexions à suivre. Vous pouvez lister votre valeur actuelle avec la commande suivante:
sysctl net.netfilter.nf_conntrack_max
Outputnet.netfilter.nf_conntrack_max = 131072
Pour définir une nouvelle valeur, utilisez l'indicateur-w
:
sysctl -w net.netfilter.nf_conntrack_max=198000
Pour rendre ce paramètre permanent, ajoutez-le au fichiersysctl.conf
:
/etc/sysctl.conf
. . .
net.ipv4.netfilter.ip_conntrack_max = 198000
Inspection des règles d'Iptables
Avant la version 1.11, Kubernetes utilisait le NAT iptables pour implémenter la traduction IP virtuelle et l'équilibrage de la charge pour les IP de service.
Pour vider toutes les règles iptables sur un nœud, utilisez la commandeiptables-save
:
iptables-save
Comme la sortie peut être longue, vous souhaiterez peut-être diriger vers un fichier (iptables-save > output.txt
) ou un pager (iptables-save | less
) pour examiner plus facilement les règles.
Pour répertorier uniquement les règles NAT du service Kubernetes, utilisez la commandeiptables
et l'indicateur-L
pour spécifier la chaîne correcte:
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
. . .
Interrogation du DNS du cluster
Une façon de déboguer la résolution DNS de votre cluster consiste à déployer un conteneur de débogage avec tous les outils dont vous avez besoin, puis à utiliserkubectl
pour y exécuternslookup
. Ceci est décrit dansthe official Kubernetes documentation.
Une autre façon d'interroger le DNS du cluster consiste à utiliserdig
etnsenter
à partir d'un nœud. Sidig
n'est pas installé, il peut être installé avecapt
sur les distributions Linux basées sur Debian:
apt install dnsutils
Tout d'abord, recherchez l'adresse IP du cluster du servicekube-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
L'IP du cluster est mis en évidence ci-dessus. Ensuite, nous utiliseronsnsenter
pour exécuterdig
dans l'espace de noms d'un conteneur. Regardez la sectionFinding and Entering Pod Network Namespaces pour plus d'informations à ce sujet:
nsenter -t 14346 -n dig kubernetes.default.svc.cluster.local @10.32.0.10
Cette commandedig
recherche le nom de domaine complet du service deservice-name.namespace.svc.cluster.local et spécifie l'adresse IP de l'IP du service DNS du cluster (@10.32.0.10
).
En regardant les détails IPVS
À partir de Kubernetes 1.11,kube-proxy
peut configurer IPVS pour gérer la traduction des adresses IP de service virtuelles en IP de pod. Vous pouvez lister la table de traduction des adresses IP avecipvsadm
:
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
Pour afficher une seule adresse IP de service, utilisez l'option-t
et spécifiez l'adresse IP souhaitée:
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
Conclusion
Dans cet article, nous avons examiné certaines commandes et techniques permettant d’explorer et d’analyser les détails du réseau de votre cluster Kubernetes. Pour plus d'informations sur Kubernetes, jetez un œil àour Kubernetes tutorials tag etthe official Kubernetes documentation.