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

Nota. traducir: Esta nota práctica del creador de LayerCI es una excelente ilustración de los llamados consejos y trucos para Kubernetes (y más). La solución propuesta aquí es sólo una de las pocas y, quizás, no la más obvia (para algunos casos, la solución "nativa" para K8 ya mencionada en los comentarios puede ser adecuada kubectl port-forward). Sin embargo, le permite al menos mirar el problema desde la perspectiva del uso de utilidades clásicas y combinarlas aún más, al mismo tiempo que es simple, flexible y potente (consulte "otras ideas" al final para inspirarse).

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

Imagine una situación típica: desea que un puerto en su máquina local reenvíe mágicamente el tráfico a un pod/contenedor (o viceversa).

Posibles casos de uso

  1. Compruebe lo que devuelve el punto final HTTP /healthz pod 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 herramientas de bases de datos locales sin tener que preocuparse por la autenticación (normalmente localhost tiene derechos de root).
  4. Ejecute un script de migración único para datos en un 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.

servidor tcp — 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 hacia él:

colin@colin-work:~$ tcpserver 127.0.0.1 8080 echo -e 'HTTP/1.0 200 OKrnContent-Length: 19rnrn<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 pasar las E/S recibidas desde é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 la página a través de HTTP. Bandera -C hace que agregue CRLF al final de la línea.

Conexión 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 bastará con 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)

Cómo abrir un túnel en un pod o contenedor de Kubernetes con tcpserver y netcat
Diagrama de interacción de servicios públicos

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 de bash

Escribí un script especial para Bash que te permite administrar un clúster de producción de Kubernetes. CapaCIutilizando 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, puedes abrir fácilmente un túnel en una cápsula con el comando kubetunnel web-pod 8080 y hacer curl localhost:6666.

  • Para el túnel en Docker puedes reemplazar la línea principal con:
    tcpserver 127.0.0.1 6666 docker exec -i "$CONTAINER" nc 127.0.0.1 "$DESTPORT"
  • para túnel en K3s - cámbielo a:
    tcpserver 127.0.0.1 6666 k3s kubectl exec …
  • etcétera

Más ideas

  • Puede redirigir el tráfico UDP usando los comandos netcat -l -u -c en lugar de tcpserver и netcat -u en 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 vía SSH a otra computadora con el archivo correspondiente kubeconfig:

    tcpserver ssh workcomputer "kubectl exec -i my-pod nc 127.0.0.1 80"

  • Puede conectar dos pods en diferentes clústeres usando mkfifo y ejecutar dos comandos separados kubectl.

¡Las posibilidades son infinitas!

PD del traductor

Lea también en nuestro blog:

Fuente: habr.com

Añadir un comentario