Résolution des problèmes de connectivité Kubernetes : Utiliser exec et port-forward efficacement

Résolvez les problèmes de connectivité Kubernetes et les problèmes internes d'application en toute confiance. Ce guide fournit des exemples pratiques d'utilisation de `kubectl exec` pour exécuter des commandes dans des conteneurs et de `kubectl port-forward` pour accéder en toute sécurité aux services depuis votre machine locale. Apprenez à diagnostiquer les problèmes réseau, inspecter les configurations et obtenir des informations approfondies sur le comportement de votre application dans le cluster.

Résolution des problèmes de connectivité Kubernetes : Utiliser exec et port-forward efficacement

Lorsqu'un service Kubernetes expire, vous devez généralement répondre à une question simple avant de pouvoir réparer quoi que ce soit : où la connexion cesse-t-elle de fonctionner ? kubectl exec vous permet de tester depuis l'intérieur du cluster, près de l'application. kubectl port-forward vous permet de ramener un pod ou un service sur votre ordinateur portable sans modifier une entrée Ingress, un LoadBalancer, une règle de pare-feu ou un enregistrement DNS.

Utilisés ensemble, ces deux commandes vous aident à éviter les suppositions. Vous pouvez tester si l'application écoute, si le DNS du cluster fonctionne, si un Service pointe vers les bons pods, et si le problème réside dans le réseau Kubernetes ou dans l'application elle-même.

Comprendre kubectl exec

La commande kubectl exec vous permet d'exécuter des commandes à l'intérieur d'un conteneur en cours d'exécution dans un pod. C'est extrêmement utile pour inspecter les journaux, vérifier les configurations et exécuter des outils de diagnostic directement là où votre application s'exécute.

Utilisez-la avec précaution en production. Vous exécutez une commande à l'intérieur d'un conteneur de charge de travail réel. Une commande inoffensive comme env, cat, curl ou ss est normale. Installer des paquets, modifier des fichiers ou exécuter des diagnostics coûteux à l'intérieur d'un pod en direct peut masquer le problème d'origine ou en créer un nouveau.

Syntaxe de base

La syntaxe fondamentale de kubectl exec est :

kubectl exec <nom-du-pod> -- <commande> [args...]
  • <nom-du-pod> : Le nom du pod dans lequel vous souhaitez exécuter une commande.
  • -- : Ce séparateur est crucial. Il distingue les indicateurs kubectl de la commande que vous souhaitez exécuter à l'intérieur du conteneur.
  • <commande> : La commande à exécuter dans le conteneur (par exemple, ls, cat, ping).
  • [args...] : Tous les arguments de la commande.

Accès interactif au shell

L'une des utilisations les plus courantes de kubectl exec est d'obtenir un shell interactif (comme bash ou sh) à l'intérieur d'un conteneur. Cela vous permet d'explorer le système de fichiers du conteneur et d'exécuter plusieurs commandes.

Pour obtenir un shell interactif :

kubectl exec -it <nom-du-pod> -- /bin/bash
  • -i (ou --stdin) : Maintient stdin ouvert même s'il n'est pas attaché.
  • -t (ou --tty) : Alloue un pseudo-TTY, nécessaire pour les sessions shell interactives.

Exemple : Accéder à un shell bash dans un pod nommé my-app-pod :

kubectl exec -it my-app-pod -- /bin/bash

Une fois à l'intérieur, vous pouvez utiliser les commandes Linux standard. Pour quitter le shell, tapez exit ou appuyez sur Ctrl+D. Si /bin/bash n'est pas présent, essayez /bin/sh ; de nombreuses petites images ne sont pas livrées avec Bash.

Exécution d'une commande unique

Vous pouvez également exécuter une commande unique sans shell interactif. Cela est utile pour des vérifications rapides ou des scripts.

Exemple : Vérification des fichiers dans le répertoire /app de my-app-pod :

kubectl exec my-app-pod -- ls /app

Exemple : Affichage du contenu d'un fichier de configuration config.yaml :

kubectl exec my-app-pod -- cat /etc/my-app/config.yaml

Spécification d'un conteneur dans un pod

Si votre pod a plusieurs conteneurs, vous devez spécifier dans quel conteneur exécuter la commande à l'aide de l'indicateur -c.

kubectl exec <nom-du-pod> -c <nom-du-conteneur> -- <commande>

Exemple : Exécution de env dans le sidecar-container de multi-container-pod :

kubectl exec multi-container-pod -c sidecar-container -- env

Comprendre kubectl port-forward

La commande kubectl port-forward vous permet d'établir un tunnel sécurisé de votre machine locale vers un pod ou un service spécifique dans votre cluster Kubernetes. C'est inestimable pour déboguer des applications qui ne sont pas exposées en externe, accéder à des bases de données ou tester des API internes.

Ce n'est pas un chemin de trafic de production. C'est un tunnel de débogage via votre connexion à l'API Kubernetes. Si la connexion au serveur API tombe, votre tunnel local tombe également.

Syntaxe de base

La syntaxe générale est :

kubectl port-forward <nom-du-pod> <port-local>:<port-distant>
  • <nom-du-pod> : Le nom du pod auquel vous souhaitez vous connecter.
  • <port-local> : Le port sur votre machine locale qui écoutera les connexions.
  • <port-distant> : Le port sur le pod qui recevra le trafic transféré.

Exemple : Transfert du port local 8080 vers le port 80 de my-app-pod :

kubectl port-forward my-app-pod 8080:80

Une fois cette commande en cours d'exécution, vous pouvez accéder à votre application en naviguant vers http://localhost:8080 dans votre navigateur Web ou en utilisant des outils comme curl sur votre machine locale.

Transfert vers un Service

Vous pouvez également transférer le trafic vers un Service Kubernetes au lieu d'un pod spécifique. kubectl sélectionnera automatiquement un pod soutenant ce service.

kubectl port-forward service/<nom-du-service> <port-local>:<port-du-service>

Exemple : Transfert du port local 3000 vers le port 80 du service my-service :

kubectl port-forward service/my-service 3000:80

Lors du transfert vers un Service, rappelez-vous que kubectl choisit un pod de soutien. Si un seul réplica est cassé, le transfert au niveau du service peut le manquer. Par exemple, un Déploiement avec trois pods peut avoir deux pods sains et un pod avec une mauvaise configuration. Le transfert vers service/my-service pourrait choisir un pod sain et donner l'impression que le service fonctionne. Lorsque vous soupçonnez un problème spécifique à un réplica, transférez vers le nom exact du pod.

Transfert vers des Déploiements ou StatefulSets

De même, vous pouvez transférer vers des Déploiements ou StatefulSets. kubectl sélectionnera l'un des pods gérés par la ressource spécifiée.

kubectl port-forward deployment/<nom-du-déploiement> <port-local>:<port-du-conteneur>
kubectl port-forward statefulset/<nom-du-statefulset> <port-local>:<port-du-conteneur>

Liaison à une adresse spécifique

Par défaut, port-forward se lie à localhost. Vous pouvez spécifier une adresse locale différente à l'aide de l'indicateur --address.

kubectl port-forward --address 127.0.0.1 <nom-du-pod> <port-local>:<port-distant>

Transfert de plusieurs ports

kubectl port-forward peut transférer plusieurs ports simultanément.

kubectl port-forward my-app-pod 8080:80 9090:90

Cette commande transfère le port local 8080 vers le port 80 du pod et le port local 9090 vers le port 90 du pod.

Scénarios courants de dépannage et solutions

Scénario 1 : L'application ne répond pas, mais le pod semble sain.

  • Problème : Le pod est en cours d'exécution, mais les requêtes vers son service échouent ou expirent. L'application peut avoir des problèmes de configuration interne ou être bloquée.
  • Solution avec kubectl exec :
    1. Obtenez un shell interactif dans le pod : kubectl exec -it <nom-du-pod> -- /bin/bash
    2. Dans le shell, vérifiez les journaux de l'application (par exemple, tail -f /var/log/myapp.log).
    3. Vérifiez les fichiers de configuration internes de l'application.
    4. Vérifiez la connectivité réseau depuis le pod vers d'autres services à l'aide de ping ou curl (si installé).
  • Solution avec kubectl port-forward :
    1. Transférez un port vers le port d'écoute de l'application : kubectl port-forward <nom-du-pod> 8080:<port-app>
    2. Essayez d'accéder à l'application localement via http://localhost:8080. Cela aide à déterminer si le problème vient de la découverte de service Kubernetes ou de l'ingress, ou si l'application elle-même ne répond pas.

Si le port-forward fonctionne mais que l'URL de service normal échoue, inspectez le sélecteur de Service et les points de terminaison :

kubectl get service <nom-du-service> -n <espace-de-noms> -o yaml
kubectl get endpoints <nom-du-service> -n <espace-de-noms>
kubectl get pods -n <espace-de-noms> --show-labels

Une défaillance très courante est une incompatibilité d'étiquettes. Les pods sont sains, le service existe, mais le sélecteur ne correspond pas aux étiquettes du pod, donc le Service n'a pas de points de terminaison.

Scénario 2 : Besoin de déboguer une base de données s'exécutant dans un pod.

  • Problème : Vous devez connecter votre client de base de données local à une base de données s'exécutant dans un pod Kubernetes pour inspecter les données ou exécuter des requêtes.
  • Solution avec kubectl port-forward :
    1. Identifiez le pod exécutant la base de données et son port (par exemple, mysql-pod, port 3306).
    2. Transférez un port local vers le port de la base de données : kubectl port-forward mysql-pod 3306:3306
    3. Configurez votre client de base de données local pour vous connecter à localhost:3306 en utilisant les identifiants de base de données appropriés.

Scénario 3 : Diagnostic des problèmes de résolution DNS dans un pod.

  • Problème : Une application dans un pod ne peut pas atteindre d'autres services par leurs noms de service, ce qui suggère un problème DNS.
  • Solution avec kubectl exec :
    1. Obtenez un shell interactif dans le pod : kubectl exec -it <nom-du-pod> -- /bin/bash
    2. Dans le shell, essayez de résoudre un nom de service connu : nslookup <nom-du-service>.<espace-de-noms>.svc.cluster.local ou dig <nom-du-service>.<espace-de-noms>.svc.cluster.local.
    3. Vérifiez le contenu de /etc/resolv.conf pour vous assurer que la configuration DNS du cluster est correcte dans le pod.

Si l'image n'inclut pas nslookup, dig ou curl, utilisez un pod de débogage temporaire dans le même espace de noms :

kubectl run net-debug -n <espace-de-noms> --rm -it --image=curlimages/curl -- sh

À partir de là, testez le même nom de service que votre application utilise. Cela aide à séparer "mon image d'application n'a pas d'outils" de "le DNS du cluster est cassé".

Scénario 4 : Le port-forward se connecte, puis se ferme immédiatement.

  • Problème : kubectl port-forward imprime un message de transfert, mais la connexion se ferme lorsque vous ouvrez le navigateur ou exécutez curl.
  • Causes probables : Le processus cible n'écoute pas sur le port distant, l'application ne se lie qu'à 127.0.0.1 dans le conteneur, ou le pod redémarre pendant que le tunnel est ouvert.
  • Vérifications :
    kubectl exec <nom-du-pod> -n <espace-de-noms> -- ss -lntp
    kubectl get pod <nom-du-pod> -n <espace-de-noms> -w
    kubectl logs <nom-du-pod> -n <espace-de-noms> --tail=100
    

Si le processus écoute sur le port 8080 mais que vous transférez vers 80, le tunnel lui-même est correct ; la cible est erronée. Si le pod redémarre pendant que vous testez, corrigez la cause du redémarrage avant de chercher des problèmes réseau.

Scénario 5 : Le service fonctionne depuis un pod mais pas depuis un autre.

  • Problème : Un backend peut atteindre Redis, mais un pod worker dans un autre espace de noms ne le peut pas.
  • Vérifications avec exec :
    kubectl exec <pod-source> -n <espace-de-noms-source> -- curl -v http://<service>.<espace-de-noms-cible>.svc.cluster.local:<port>
    kubectl exec <pod-source> -n <espace-de-noms-source> -- cat /etc/resolv.conf
    

Si le DNS résout mais que TCP échoue, vérifiez les NetworkPolicies, les points de terminaison de service et si l'application cible accepte le trafic de cet espace de noms. Si le DNS ne résout pas, testez le nom de service complet avant d'accuser l'application.

Une échelle de connectivité simple

Lorsqu'une requête échoue, testez du plus proche au plus éloigné :

  1. À l'intérieur du pod, testez le processus d'application local :
    kubectl exec <pod> -n <espace-de-noms> -- curl -v http://127.0.0.1:<port>/health
    
  2. Depuis un autre pod dans le même espace de noms, testez le Service :
    kubectl run curl-test -n <espace-de-noms> --rm -it --image=curlimages/curl -- curl -v http://<service>:<port>/health
    
  3. Depuis votre ordinateur portable, testez via port-forward :
    kubectl port-forward service/<service> -n <espace-de-noms> 8080:<port-du-service>
    curl -v http://localhost:8080/health
    
  4. Ce n'est qu'après que ceux-ci réussissent que vous passez à l'Ingress, aux équilibreurs de charge, au DNS et aux règles de pare-feu.

Cet ordre fait gagner du temps car chaque étape prouve une couche. Si localhost dans le pod échoue, l'Ingress n'est pas pertinent. Si le pod-local réussit mais que l'accès au Service échoue, l'application va probablement bien et la découverte de service Kubernetes nécessite une attention particulière.

Une autre habitude aide : gardez l'espace de noms explicite pendant le débogage. De nombreuses sessions déroutantes proviennent de l'exécution de kubectl exec dans l'espace de noms par défaut alors que la charge de travail cassée se trouve ailleurs. Définissez l'espace de noms dans votre contexte pour la session ou ajoutez -n <espace-de-noms> à chaque commande. La frappe supplémentaire coûte moins cher que de tester le mauvais pod.

Enregistrez également la commande exacte qui a prouvé l'échec. La prochaine personne de garde peut la réexécuter sans reconstruire votre contexte de mémoire.

Meilleures pratiques et conseils

  • Gardez port-forward en cours d'exécution : kubectl port-forward s'exécute au premier plan. Vous devrez garder la fenêtre du terminal ouverte. Pour l'exécuter en arrière-plan, vous pouvez utiliser des outils comme nohup ou screen/tmux.
  • Utilisez des pods spécifiques lors du débogage : Bien que le transfert vers des services soit pratique, pour identifier les problèmes avec une instance spécifique, le transfert vers un pod particulier en utilisant son nom est souvent plus efficace.
  • Sécurité : Soyez conscient des ports que vous exposez. Évitez de transférer des ports sensibles sauf en cas d'absolue nécessité et assurez-vous que votre machine locale est sécurisée.
  • Utilisation des ressources : kubectl exec peut consommer des ressources. Utilisez-le judicieusement, en particulier sur les clusters de production.
  • Autorisations : Assurez-vous que votre contexte kubectl dispose des autorisations nécessaires pour exécuter des commandes dans des pods ou transférer des ports.

Ce qu'il faut noter après avoir résolu le problème

Un bon débogage laisse une trace. Capturez l'URL défaillante, le pod source, le service cible, l'espace de noms, la commande exacte qui a reproduit le problème et la couche où il a échoué. "Problème de connectivité" est trop vague pour aider la prochaine fois. "Le sélecteur de Service ne correspondait pas aux pods après le renommage des étiquettes" est un modèle réparable.