Cómo abrir un túnel en Kubernetes pod o contenedor con tcpserver y netcat

Nota perev. : Esta nota práctica del creador de LayerCI es una gran ilustración de los llamados consejos y trucos para Kubernetes (y no solo). La solución propuesta aquí es solo una de las pocas y, quizás, no la más obvia (en algunos casos, el " kubectl port-forward " nativo de K8 mencionado en los comentarios puede ser adecuado). Sin embargo, le permite al menos ver el problema desde la perspectiva del uso de las utilidades clásicas y su combinación adicional, tanto simple, flexible como potente (consulte "otras ideas" al final para obtener inspiración).



Imagine una situación típica: desea que el puerto en la computadora local redirija mágicamente el tráfico al pod / contenedor (o viceversa).

Posibles casos de uso


  1. Compruebe que el punto final HTTP /healthz en el clúster de producción.
  2. Conecte un depurador TCP al pod en la máquina local.
  3. Obtenga acceso a la base de datos de producción desde las herramientas locales para trabajar con la base de datos sin tener que molestarse con la autenticación (generalmente localhost tiene privilegios de root).
  4. Ejecute un script de migración de una sola vez para los datos en el clúster provisional sin tener que crear un contenedor para él.
  5. Conecte una sesión de VNC a un pod que ejecute un escritorio virtual (consulte XVFB).

Algunas palabras sobre las herramientas necesarias.


Tcpserver es una utilidad de código abierto disponible en la mayoría de los repositorios de paquetes de Linux. Le permite abrir un puerto local y redirigir el tráfico recibido a través de stdin / stdout desde cualquier comando especificado:

 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 hace lo contrario. Le permite conectarse a un puerto abierto y transferir la entrada / salida recibida de él a 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 )

En el ejemplo anterior, netcat solicita una página a través de HTTP. El indicador -C hace que agregue CRLF al final de la línea.

Enlace con kubectl: escuche en el host y conéctese al pod


Si combinamos las herramientas anteriores con kubectl, obtenemos un comando como este:

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

Por analogía, para acceder al puerto 80 dentro del pod, será suficiente para hacer 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 )


Esquema de interacción de utilidad

En la dirección opuesta: escuche en el pod y conéctese al host


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

Este comando permite que el pod acceda al puerto 8000 en la máquina local.

Script para Bash


Escribí un script especial para Bash que le permite administrar el clúster de producción Kubernetes LayerCI utilizando el método descrito anteriormente:

 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 agrega esta función a ~/.bashrc , puede abrir fácilmente el túnel en el pod kubetunnel web-pod 8080 y hacer curl localhost:6666 .

  • Para un túnel en Docker, puede reemplazar la línea principal con:

     tcpserver 127.0.0.1 6666 docker exec -i "$CONTAINER" nc 127.0.0.1 "$DESTPORT" 
  • para el túnel en K3s - cámbielo a:

     tcpserver 127.0.0.1 6666 k3s kubectl exec 
  • etc.

Otras ideas


  • Puede redirigir el tráfico UDP utilizando netcat -l -u -c lugar de tcpserver y netcat -u lugar de netcat respectivamente.
  • Ver E / S a través del visor de tuberías:

    nc 127.0.0.1 8000 | pv --progress | kubectl exec -i web-pod tcpserver 127.0.0.1 8080 cat
  • Puede comprimir y descomprimir el tráfico en ambos extremos usando gzip .
  • Conéctese a través de SSH a otra computadora con el archivo kubeconfig correspondiente:

    tcpserver ssh workcomputer "kubectl exec -i my-pod nc 127.0.0.1 80"
  • Puede conectar dos pods en diferentes grupos utilizando mkfifo y ejecutar dos kubectl separados.

¡Las posibilidades son infinitas!

PD del traductor


Lea también en nuestro blog:

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


All Articles