Come aprire un tunnel in un pod o container Kubernetes con tcpserver e netcat

Nota. trad.: Questa nota pratica del creatore di LayerCI è un'eccellente illustrazione dei cosiddetti suggerimenti e trucchi per Kubernetes (e altro). La soluzione qui proposta è solo una delle poche e, forse, non la più ovvia (in alcuni casi potrebbe essere adatta quella “nativa” per K8 già menzionata nei commenti) kubectl port-forward). Tuttavia, ti consente almeno di guardare il problema dal punto di vista dell'utilizzo delle utilità classiche e della loro ulteriore combinazione - allo stesso tempo semplice, flessibile e potente (vedi "altre idee" alla fine per l'ispirazione).

Come aprire un tunnel in un pod o container Kubernetes con tcpserver e netcat

Immagina una situazione tipica: vuoi che una porta sul tuo computer locale inoltri magicamente il traffico a un pod/container (o viceversa).

Possibili casi d'uso

  1. Controlla cosa restituisce l'endpoint HTTP /healthz pod nel cluster produttivo.
  2. Connetti un debugger TCP al pod sulla macchina locale.
  3. Ottieni l'accesso al database di produzione dagli strumenti del database locale senza doverti preoccupare dell'autenticazione (di solito localhost ha i diritti di root).
  4. Esegui uno script di migrazione una tantum per i dati in un cluster di staging senza dover creare un contenitore per esso.
  5. Connetti una sessione VNC a un pod che esegue un desktop virtuale (vedi XVFB).

Qualche parola sugli strumenti necessari

Tcpserver — Un'utilità Open Source disponibile nella maggior parte dei repository di pacchetti Linux. Ti consente di aprire una porta locale e reindirizzare il traffico ricevuto tramite stdin/stdout da qualsiasi comando specificato ad essa:

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 fa il contrario. Ti consente di connetterti a una porta aperta e passare l'I/O ricevuto da essa 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)

Nell'esempio sopra, netcat richiede la pagina tramite HTTP. Bandiera -C fa sì che aggiunga CRLF alla fine della riga.

Connessione con kubectl: ascolto sull'host e connessione al pod

Se combiniamo gli strumenti di cui sopra con kubectl, otteniamo un comando come questo:

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

Per analogia, per accedere alla porta 80 all'interno del pod basterà fare 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)

Come aprire un tunnel in un pod o container Kubernetes con tcpserver e netcat
Diagramma di interazione delle utenze

Nella direzione opposta: ascolta nel pod e connettiti all'host

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

Questo comando consente al pod di accedere alla porta 8000 sul computer locale.

Script Bash

Ho scritto uno script speciale per Bash che permette di gestire un cluster di produzione Kubernetes LayerCIutilizzando il metodo sopra descritto:

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"
}

Se aggiungi questa funzione a ~/.bashrc, puoi facilmente aprire un tunnel in un pod con il comando kubetunnel web-pod 8080 e fai curl localhost:6666.

  • Per il tunnel dentro docker puoi sostituire la riga principale con:
    tcpserver 127.0.0.1 6666 docker exec -i "$CONTAINER" nc 127.0.0.1 "$DESTPORT"
  • per il tunnel dentro K3s - cambialo in:
    tcpserver 127.0.0.1 6666 k3s kubectl exec …
  • eccetera

Altre idee

  • Puoi reindirizzare il traffico UDP utilizzando i comandi netcat -l -u -c invece di tcpserver и netcat -u invece di netcat rispettivamente.
  • Visualizza I/O tramite visualizzatore di tubi:

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

  • Puoi comprimere e decomprimere il traffico su entrambe le estremità utilizzando gzip.
  • Connettiti tramite SSH a un altro computer con il file corrispondente kubeconfig:

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

  • Puoi connettere due pod in cluster diversi utilizzando mkfifo ed eseguire due comandi separati kubectl.

Le possibilità sono infinite!

PS da traduttore

Leggi anche sul nostro blog:

Fonte: habr.com

Aggiungi un commento