Як з tcpserver і netcat адкрыць тунэль у Kubernetes pod або кантэйнер

Заўв. перав.: Гэтая практычная нататка ад стваральніка LayerCI - выдатная ілюстрацыя так званых tips & tricks для Kubernetes (і не толькі). Прапанаванае тут рашэнне – толькі адно з нямногіх і, мабыць, не самае відавочнае (для некаторых выпадкаў можа падысці ўжо згаданы ў каментарах "родны" для K8s kubectl port-forward). Аднак яно дазваляе як мінімум паглядзець на праблему з пазіцыі прымянення класічных утыліт і іх далейшага камбінавання - адначасова простага, гнуткага і магутнага (гл. "іншыя ідэі" у канцы для натхнення).

Як з tcpserver і netcat адкрыць тунэль у Kubernetes pod або кантэйнер

Прадстаўце тыповую сітуацыю: вы жадаеце, каб порт на лакальным кампутары чароўнай выявай перанакіроўваў трафік у pod/кантэйнер (ці наадварот).

Магчымыя сцэнары выкарыстання

  1. Праверыць, што вяртае HTTP endpoint /healthz pod'а ў production-кластары.
  2. Падлучыць TCP-адладчык да pod'у на лакальнай машыне.
  3. Атрымаць доступ да production-базе з лакальных прылад для працы з БД без неабходнасці важдацца з аўтэнтыфікацыяй (звычайна ў localhost'а ёсць правы root'а).
  4. Запусціць аднаразовы скрыпт міграцыі для дадзеных у staging-кластары без неабходнасці ствараць для яго кантэйнер.
  5. Падлучыць сесію VNC да pod'у з запушчаным віртуальным працоўным сталом (гл. XVFB).

Некалькі слоў аб неабходных інструментах

Tcpserver - Open Source-ўтыліта, даступная ў большасці рэпазітароў пакетаў Linux. Яна дазваляе адкрыць лакальны порт і перанакіраваць на яго трафік, які атрымліваецца праз stdin/stdout ад любой пазначанай каманды:

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 робіць адваротнае. Яна дазваляе падлучыцца да адчыненага порта і перадаць атрыманы ад яго ўвод/вывад на 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)

У прыведзеным вышэй прыкладзе netcat запытвае старонку па HTTP. Сцяг -C прымушае яго дадаваць CRLF у канец радка.

Звязак з kubectl: слухайце на хасце і падключайцеся да pod'у

Калі аб'яднаць прадстаўленыя вышэй прылады з kubectl, мы атрымаем каманду накшталт гэтай:

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

Па аналогіі, для доступу да порта 80 усярэдзіне pod'а досыць будзе зрабіць 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)

Як з tcpserver і netcat адкрыць тунэль у Kubernetes pod або кантэйнер
Схема ўзаемадзеяння ўтыліт

У адваротны бок: слухайце ў pod'е і падключайцеся да хаста

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

Гэтая каманда дазваляе pod'у атрымаць доступ да порта 8000 на лакальнай машыне.

Скрыпт для Bash

Я напісаў спецыяльны скрыпт для Bash, які дазваляе кіраваць production-кластарам Kubernetes LayerCI, выкарыстоўваючы апісаны вышэй метад:

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

Калі дадаць гэтую функцыю ў ~/.bashrc, можна лёгка адкрываць тунэль у pod камандай kubetunnel web-pod 8080 і рабіць curl localhost:6666.

  • Для тунэля ў Докер можна замяніць асноўны радок на:
    tcpserver 127.0.0.1 6666 docker exec -i "$CONTAINER" nc 127.0.0.1 "$DESTPORT"
  • для тунэля ў К3с - Памяняйце яе на:
    tcpserver 127.0.0.1 6666 k3s kubectl exec …
  • і г.д.

іншыя ідэі

  • Перанакіраваць UDP-трафік можна камандамі netcat -l -u -c замест tcpserver и netcat -u замест netcat адпаведна.
  • Паглядзець увод/вывад праз pipe viewer:

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

  • Можна сціскаць і распакоўваць трафік на абодвух канцах з дапамогай gzip.
  • Падлучыцца па SSH да іншага кампутара з які адпавядае файлам kubeconfig:

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

  • Можна злучыць два pod'а ў розных кластарах з дапамогай mkfifo і запусціць дзве асобныя каманды kubectl.

Возможности безграничный!

PS ад перакладчыка

Чытайце таксама ў нашым блогу:

Крыніца: habr.com

Дадаць каментар