Comment ouvrir un tunnel dans un pod ou un conteneur Kubernetes avec tcpserver et netcat

Remarque perev. : Cette note pratique du créateur de LayerCI est une excellente illustration des soi-disant trucs et astuces pour Kubernetes (et pas seulement). La solution proposée ici n'est que l'une des rares et peut-être pas la plus évidente (dans certains cas, le « kubectl port-forward » natif des K8 mentionné dans les commentaires peut convenir). Cependant, il vous permet au moins d'examiner le problème du point de vue de l'utilisation des utilitaires classiques et de leur combinaison supplémentaire - à la fois simple, flexible et puissante (voir «d'autres idées» à la fin pour l'inspiration).



Imaginez une situation typique: vous voulez que le port de l'ordinateur local redirige comme par magie le trafic vers le pod / conteneur (ou vice versa).

Cas d'utilisation possibles


  1. Vérifiez que le /healthz point de terminaison HTTP /healthz dans le cluster de production.
  2. Connectez un débogueur TCP au pod sur la machine locale.
  3. Accédez à la base de données de production à partir d'outils locaux pour travailler avec la base de données sans avoir à vous soucier de l'authentification (généralement, l'hôte local a les privilèges root).
  4. Exécutez un script de migration unique pour les données du cluster intermédiaire sans avoir à créer un conteneur pour celui-ci.
  5. Connectez une session VNC à un pod exécutant un bureau virtuel (voir XVFB).

Quelques mots sur les outils nécessaires


Tcpserver est un utilitaire Open Source disponible dans la plupart des référentiels de packages Linux. Il vous permet d'ouvrir un port local et de rediriger le trafic reçu via stdin / stdout à partir de n'importe quelle commande spécifiée:

 colin@colin-work:~$ tcpserver 127.0.0.1 8080 echo -e 'HTTP/1.0 200 OK\r\nContent-Length: 19\r\n\r\n<body>hello!</body>'& [1] 17377 colin@colin-work:~$ curl localhost:8080 <body>hello!</body>colin@colin-work:~$ 

( asciinema.org )

Netcat fait le contraire. Il vous permet de vous connecter à un port ouvert et de transférer l'entrée / sortie reçue de celui-ci vers stdin / stdout:

 colin@colin-work:~$ nc -C httpstat.us 80 GET /200 HTTP/1.0 Host: httpstat.us HTTP/1.1 200 OK Cache-Control: private Server: Microsoft-IIS/10.0 X-AspNetMvc-Version: 5.1 Access-Control-Allow-Origin: * X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Set-Cookie: ARRAffinity=93fdbab9d364704de8ef77182b4d13811344b7dd1ec45d3a9682bbd6fa154ead;Path=/;HttpOnly;Domain=httpstat.us Date: Fri, 01 Nov 2019 17:53:04 GMT Connection: close Content-Length: 0 ^C colin@colin-work:~$ 

( asciinema.org )

Dans l'exemple ci-dessus, netcat demande une page via HTTP. L'indicateur -C fait ajouter CRLF à la fin de la ligne.

Lien avec kubectl: écoutez sur l'hôte et connectez-vous au pod


Si nous combinons les outils ci-dessus avec kubectl, nous obtenons une commande comme celle-ci:

 tcpserver 127.0.0.1 8000 kubectl exec -i web-pod nc 127.0.0.1 8080 

Par analogie, pour accéder au port 80 à l'intérieur du pod, il suffira de faire curl "127.0.0.1:80" :

 colin@colin-work:~$ sanic kubectl exec -it web-54dfb667b6-28n85 bash root@web-54dfb667b6-28n85:/web# apt-get -y install netcat-openbsd Reading package lists... Done Building dependency tree Reading state information... Done netcat-openbsd is already the newest version (1.195-2). 0 upgraded, 0 newly installed, 0 to remove and 10 not upgraded. root@web-54dfb667b6-28n85:/web# exit colin@colin-work:~$ tcpserver 127.0.0.1 8000 sanic kubectl exec -i web-54dfb667b6-28n85 nc 127.0.0.1 8080& [1] 3232 colin@colin-work:~$ curl localhost:8000/healthz {"status":"ok"}colin@colin-work:~$ exit 

( asciinema.org )


Schéma d'interaction avec les services publics

Dans le sens inverse: écoutez dans le pod et connectez-vous à l'hôte


 nc 127.0.0.1 8000 | kubectl exec -i web-pod tcpserver 127.0.0.1 8080 cat 

Cette commande permet au pod d'accéder au port 8000 sur la machine locale.

Script pour Bash


J'ai écrit un script spécial pour Bash qui vous permet de gérer le cluster de production Kubernetes LayerCI en utilisant la méthode décrite ci-dessus:

 kubetunnel() { POD="$1" DESTPORT="$2" if [ -z "$POD" -o -z "$DESTPORT" ]; then echo "Usage: kubetunnel [pod name] [destination port]" return 1 fi pkill -f 'tcpserver 127.0.0.1 6666' tcpserver 127.0.0.1 6666 kubectl exec -i "$POD" nc 127.0.0.1 "$DESTPORT"& echo "Connect to 127.0.0.1:6666 to access $POD:$DESTPORT" } 

Si vous ajoutez cette fonction à ~/.bashrc , vous pouvez facilement ouvrir le tunnel dans pod kubetunnel web-pod 8080 et faire curl localhost:6666 .

  • Pour un tunnel dans Docker, vous pouvez remplacer la ligne principale par:

     tcpserver 127.0.0.1 6666 docker exec -i "$CONTAINER" nc 127.0.0.1 "$DESTPORT" 
  • pour le tunnel dans K3s - changez-le en:

     tcpserver 127.0.0.1 6666 k3s kubectl exec 
  • etc.

Autres idées


  • Vous pouvez rediriger le trafic UDP en utilisant respectivement netcat -l -u -c au lieu de tcpserver et netcat -u au lieu de netcat .
  • Afficher les E / S via la visionneuse de tuyaux:

    nc 127.0.0.1 8000 | pv --progress | kubectl exec -i web-pod tcpserver 127.0.0.1 8080 cat
  • Vous pouvez compresser et décompresser le trafic aux deux extrémités à l'aide de gzip .
  • Connectez-vous via SSH à un autre ordinateur avec le fichier kubeconfig correspondant:

    tcpserver ssh workcomputer "kubectl exec -i my-pod nc 127.0.0.1 80"
  • Vous pouvez connecter deux pods dans des clusters différents à l'aide de mkfifo et exécuter deux kubectl distinctes.

Les possibilités sont infinies!

PS du traducteur


Lisez aussi dans notre blog:

Source: https://habr.com/ru/post/fr479910/


All Articles