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

Notatka. przeł.: Ta praktyczna notatka od twórcy LayerCI jest doskonałą ilustracją tzw. porad i wskazówek dotyczących Kubernetesa (i nie tylko). Zaproponowane tutaj rozwiązanie jest tylko jednym z nielicznych i być może nie najbardziej oczywistym (w niektórych przypadkach odpowiednie może być „natywne” dla K8 wspomniane już w komentarzach kubectl port-forward). Pozwala jednak przynajmniej spojrzeć na problem z perspektywy wykorzystania klasycznych narzędzi i dalszego ich łączenia - jednocześnie prostego, elastycznego i wydajnego (inspiracje znajdziesz w „innych pomysłach” na końcu).

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

Wyobraź sobie typową sytuację: chcesz, aby port na Twojej lokalnej maszynie w magiczny sposób przekazywał ruch do zasobnika/kontenera (lub odwrotnie).

Możliwe przypadki użycia

  1. Sprawdź, co zwraca punkt końcowy HTTP /healthz pod w klastrze produkcyjnym.
  2. Podłącz debuger TCP do modułu na komputerze lokalnym.
  3. Uzyskaj dostęp do produkcyjnej bazy danych z lokalnych narzędzi bazodanowych bez konieczności zawracania sobie głowy uwierzytelnianiem (zwykle localhost ma prawa roota).
  4. Uruchom jednorazowy skrypt migracji danych w klastrze przejściowym bez konieczności tworzenia dla nich kontenera.
  5. Połącz sesję VNC z modułem z wirtualnym pulpitem (zobacz XVFB).

Kilka słów o niezbędnych narzędziach

Serwer Tcp — Narzędzie Open Source dostępne w większości repozytoriów pakietów systemu Linux. Pozwala otworzyć port lokalny i przekierować do niego ruch otrzymany przez stdin/stdout z dowolnego określonego polecenia:

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 robi odwrotnie. Umożliwia połączenie się z otwartym portem i przekazanie otrzymanych z niego wejść/wyjść 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 poprzez HTTP. Flaga -C powoduje dołączenie CRLF na końcu linii.

Połączenie z kubectl: słuchaj na hoście i połącz się z kapsułą

Jeśli połączymy powyższe narzędzia z kubectl otrzymamy takie polecenie:

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 kapsuły, wystarczy to zrobić 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 zasobniku lub kontenerze Kubernetes za pomocą serwera tcpserver i netcat
Schemat interakcji narzędzi

W odwrotnym kierunku: słuchaj w kapsule i połącz się z hostem

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

To polecenie umożliwia modułowi dostęp do portu 8000 na komputerze lokalnym.

Skrypt Basha

Napisałem specjalny skrypt dla Basha, który pozwala zarządzać klastrem produkcyjnym Kubernetes Warstwa CIstosując metodę opisaną powyżej:

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

Jeśli dodasz tę funkcję do ~/.bashrc, możesz łatwo otworzyć tunel w kapsule za pomocą polecenia kubetunnel web-pod 8080 i robić curl localhost:6666.

  • Do tunelu w Doker możesz zastąpić główną linię:
    tcpserver 127.0.0.1 6666 docker exec -i "$CONTAINER" nc 127.0.0.1 "$DESTPORT"
  • do tunelu K3s - zmień na:
    tcpserver 127.0.0.1 6666 k3s kubectl exec …
  • itd.

Inne pomysły

  • Możesz przekierowywać ruch UDP za pomocą poleceń netcat -l -u -c zamiast tcpserver и netcat -u zamiast netcat odpowiednio.
  • Wyświetl wejścia/wyjścia za pomocą przeglądarki potoków:

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

  • Możesz 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żesz połączyć dwa kapsuły w różnych klastrach za pomocą mkfifo i uruchom dwa osobne polecenia kubectl.

Możliwości są nieskończone!

PS od tłumacza

Przeczytaj także na naszym blogu:

Źródło: www.habr.com

Dodaj komentarz