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

Nota di traduzione.: Questa nota pratica dal creatore di LayerCI è un'ottima illustrazione dei cosiddetti tips & tricks per Kubernetes (e non solo). La soluzione qui proposta è solo una delle poche e, probabilmente, non la più ovvia (per alcuni casi potrebbe andare bene quella già menzionata nei commenti «nativa» per K8s. kubectl port-forward). Tuttavia, consente perlomeno di guardare al problema dalla prospettiva dell'utilizzo di utilità classiche e delle loro ulteriori combinazioni - simultaneamente semplici, flessibili e potenti (vedi «altre idee» alla fine per ispirazione).

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

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

Possibili scenari d'uso

  1. Verificare cosa restituisce l'endpoint HTTP /healthz del pod in un cluster di produzione.
  2. Collegare un debugger TCP al pod sulla macchina locale.
  3. Accedere al database di produzione dagli strumenti locali per lavorare con i DB senza dover gestire l'autenticazione (di solito localhost ha diritti di root).
  4. Eseguire uno script di migrazione una tantum per i dati nel cluster di staging senza dover creare un contenitore per esso.
  5. Collegare una sessione VNC al pod con un desktop virtuale in esecuzione (vedi XVFB).

Qualche parola sugli strumenti necessari

Tcpserver — un'utilità open source, disponibile nella maggior parte dei repository di pacchetti Linux. Consente di aprire una porta locale e reindirizzare il traffico a essa ricevuto tramite stdin/stdout da qualsiasi comando specificato:

colin@colin-work:~$ tcpserver 127.0.0.1 8080 echo -e 'HTTP/1.0 200 OKrnContent-Length: 19rnrn<body>ciao!</body>'&amp;
[1] 17377
colin@colin-work:~$ curl localhost:8080
<body>ciao!</body>colin@colin-work:~$

(asciinema.org)

Netcat fa l'opposto. Consente di collegarsi a una porta aperta e trasmettere l'input/output ricevuto 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 via HTTP. L'opzione -C fa sì che aggiunga CRLF alla fine della riga.

Collegamento con kubectl: ascolta sull'host e collegati al pod

Se si uniscono gli strumenti presentati sopra con kubectl, si ottiene un comando simile a questo:

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

Analogamente, per accedere alla porta 80 all'interno del pod sarà sufficiente utilizzare 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
Lettura delle liste dei pacchetti... Fatto
Costruzione dell'albero delle dipendenze
Lettura delle informazioni sullo stato... Fatto
netcat-openbsd è già la versione più recente (1.195-2).
0 aggiornati, 0 nuovi installati, 0 da rimuovere e 10 non aggiornati.
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 contenitore Kubernetes con tcpserver e netcat
Schema di interazione delle utilità

Nella direzione opposta: ascolta nel pod e collegati 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 sulla macchina locale.

Script per Bash

Ho scritto uno script speciale per Bash che consente di gestire un cluster di produzione Kubernetes LayerCI, utilizzando il metodo sopra descritto:

kubetunnel() {
    POD="$1"
    DESTPORT="$2"
    if [ -z "$POD" -o -z "$DESTPORT" ]; then
        echo "Uso: kubetunnel [nome pod] [porta di destinazione]"
        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 "Collegati a 127.0.0.1:6666 per accedere a $POD:$DESTPORT"
}

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

  • Per il tunnel in 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 in K3s — cambiala in:
    tcpserver 127.0.0.1 6666 k3s kubectl exec …
  • ecc.

Altre idee

  • Reinviare il traffico UDP è possibile con i comandi netcat -l -u -c anziché tcpserver e netcat -u anziché netcat rispettivamente.
  • Visualizza l'input/output tramite pipe viewer:

    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 entrambi i lati usando gzip.
  • Collegati 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 usando mkfifo e avviare due comandi separati kubectl.

Le possibilità sono infinite!

P.S. dal traduttore

Leggi anche nel nostro blog:

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster