Jak otworzyć tunel w podzie lub kontenerze Kubernetes za pomocą tcpserver i netcat

Przyp. tłum.: Ta praktyczna notatka od twórcy LayerCI to doskonała ilustracja tzw. wskazówek i trików dla Kubernetes (i nie tylko). Proponowane tutaj rozwiązanie to jedno z nielicznych i, być może, nie najbardziej oczywiste (w niektórych przypadkach może pasować już wspomniane w komentarzach „rodzinne” dla K8s kubectl port-forward). Jednak pozwala przynajmniej spojrzeć na problem z perspektywy zastosowania klasycznych narzędzi i ich dalszej kombinacji — jednocześnie prostego, elastycznego i potężnego (zobacz „inne pomysły” na końcu dla inspiracji).

Jak otworzyć tunel w podzie lub kontenerze Kubernetes za pomocą tcpserver i netcat

Wyobraź sobie typową sytuację: chcesz, aby port na lokalnym komputerze magicznie przekierowywał ruch do podu/kontenera (lub odwrotnie).

Możliwe scenariusze użycia

  1. Sprawdź, co zwraca punkt końcowy HTTP /healthz pod w klastrze produkcyjnym.
  2. Podłącz debugger TCP do podu na lokalnej maszynie.
  3. Uzyskaj dostęp do bazy produkcyjnej z lokalnych narzędzi do pracy z bazami danych bez konieczności zajmowania się uwierzytelnianiem (zwykle localhost ma prawa root).
  4. Uruchom jednorazowy skrypt migracji danych w klastrze staging bez konieczności tworzenia dla niego kontenera.
  5. Podłącz sesję VNC do podu z uruchomionym wirtualnym pulpitem (zobacz XVFB).

Kilka słów o potrzebnych narzędziach

Tcpserver — Open Source narzędzie dostępne w większości repozytoriów pakietów Linux. Pozwala otworzyć lokalny port i przekierować na niego ruch uzyskiwany przez stdin/stdout z dowolnej wskazanej komendy:

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

(asciinema.org)

Netcat działa odwrotnie. Pozwala połączyć się z otwartym portem i przekazać uzyskany od niego wejście/wyjście na 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)

W powyższym przykładzie netcat żąda strony przez HTTP. Flaga -C każe mu dodawać CRLF na końcu wiersza.

Powiązanie z kubectl: słuchaj na hoście i łącz się z pod’em

Jeśli połączymy powyższe narzędzia z kubectl, otrzymamy komendę w rodzaju:

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

Analogicznie, aby uzyskać dostęp do portu 80 wewnątrz pod’u, wystarczy wykonać 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)

Jak otworzyć tunel w podzie lub kontenerze Kubernetes za pomocą tcpserver i netcat
Schemat interakcji narzędzi

W drugą stronę: słuchaj w podzie i łącz się z hostem

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

To polecenie pozwala podowi uzyskać dostęp do portu 8000 na lokalnej maszynie.

Skrypt dla Basha

Napisałem specjalny skrypt dla Basha, który pozwala zarządzać klastrem produkcyjnym Kubernetes LayerCI, korzystając z opisanego powyżej sposobu:

kubetunnel() {
    POD="$1"
    DESTPORT="$2"
    if [ -z "$POD" -o -z "$DESTPORT" ]; then
        echo "Usage: kubetunnel [nazwa podu] [port docelowy]"
        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 "Połącz się z 127.0.0.1:6666, aby uzyskać dostęp do $POD:$DESTPORT"
}

Jeśli dodasz tę funkcję do ~\/ .bashrc, możesz łatwo otworzyć tunel w podzie poleceniem kubetunnel web-pod 8080 i wykonać curl localhost:6666.

  • Dla tunelu w Docker możesz zastąpić główną linię na:
    tcpserver 127.0.0.1 6666 docker exec -i "$CONTAINER" nc 127.0.0.1 "$DESTPORT"
  • dla tunelu w K3s — zamień ją na:
    tcpserver 127.0.0.1 6666 k3s kubectl exec …
  • itd.

Inne pomysły

  • Przekierowanie ruchu UDP można zrealizować poleceniami netcat -l -u -c zamiast tcpserver i netcat -u zamiast netcat odpowiednio.
  • Zobacz wejście/wyjście za pomocą pipe viewer:

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

  • Można kompresować i dekompresować ruch na obu końcach za pomocą gzip.
  • Połącz się przez SSH z innym komputerem z odpowiednim plikiem kubeconfig:

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

  • Można połączyć dwa pody w różnych klastrach za pomocą mkfifo i uruchomić dwie oddzielne komendy kubectl.

Możliwości są nieograniczone!

P.S. od tłumacza

Przeczytaj także na naszym blogu:

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster