Como abrir um túnel em um pod ou contêiner do Kubernetes com tcpserver e netcat

Observação. trad.: Esta nota prática do criador do LayerCI é uma excelente ilustração das chamadas dicas e truques para Kubernetes (e muito mais). A solução aqui proposta é apenas uma das poucas e, talvez, não a mais óbvia (para alguns casos, a “nativa” para K8s já mencionada nos comentários pode ser adequada kubectl port-forward). No entanto, permite pelo menos olhar para o problema da perspectiva do uso de utilitários clássicos e combiná-los ainda mais - ao mesmo tempo simples, flexíveis e poderosos (veja “outras ideias” no final para inspiração).

Como abrir um túnel em um pod ou contêiner do Kubernetes com tcpserver e netcat

Imagine uma situação típica: você deseja que uma porta em sua máquina local encaminhe magicamente o tráfego para um pod/contêiner (ou vice-versa).

Possíveis casos de uso

  1. Verifique o que o endpoint HTTP retorna /healthz pod no cluster de produção.
  2. Conecte um depurador TCP ao pod na máquina local.
  3. Obtenha acesso ao banco de dados de produção a partir de ferramentas de banco de dados locais sem precisar se preocupar com autenticação (geralmente localhost tem direitos de root).
  4. Execute um script de migração único para dados em um cluster de preparo sem precisar criar um contêiner para ele.
  5. Conecte uma sessão VNC a um pod executando um desktop virtual (consulte XVFB).

Algumas palavras sobre as ferramentas necessárias

Servidor TCP — Um utilitário de código aberto disponível na maioria dos repositórios de pacotes Linux. Ele permite que você abra uma porta local e redirecione o tráfego recebido via stdin/stdout de qualquer comando especificado para ela:

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 faz o oposto. Ele permite que você se conecte a uma porta aberta e passe a E/S recebida dela para 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)

No exemplo acima, o netcat solicita a página por HTTP. Bandeira -C faz com que ele anexe CRLF ao final da linha.

Conexão com kubectl: ouça no host e conecte-se ao pod

Se combinarmos as ferramentas acima com o kubectl, obteremos um comando como este:

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

Por analogia, para acessar a porta 80 dentro do pod bastará fazer 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)

Como abrir um túnel em um pod ou contêiner do Kubernetes com tcpserver e netcat
Diagrama de interação de utilitários

Na direção oposta: ouça no pod e conecte-se ao host

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

Este comando permite que o pod acesse a porta 8000 na máquina local.

Script bash

Eu escrevi um script especial para Bash que permite gerenciar um cluster de produção Kubernetes CamadaCIusando o método descrito acima:

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 você adicionar esta função a ~/.bashrc, você pode abrir facilmente um túnel em um pod com o comando kubetunnel web-pod 8080 e fazer curl localhost:6666.

  • Para o túnel em Estivador você pode substituir a linha principal por:
    tcpserver 127.0.0.1 6666 docker exec -i "$CONTAINER" nc 127.0.0.1 "$DESTPORT"
  • para túnel em K3s - altere para:
    tcpserver 127.0.0.1 6666 k3s kubectl exec …
  • и т.д.

Outras ideias

  • Você pode redirecionar o tráfego UDP usando os comandos netcat -l -u -c ao invés de tcpserver и netcat -u ao invés de netcat respectivamente.
  • Visualize E/S via visualizador de pipe:

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

  • Você pode compactar e descompactar o tráfego nas duas extremidades usando gzip.
  • Conecte-se via SSH a outro computador com o arquivo correspondente kubeconfig:

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

  • Você pode conectar dois pods em clusters diferentes usando mkfifo e execute dois comandos separados kubectl.

As possibilidades são infinitas!

PS do tradutor

Leia também em nosso blog:

Fonte: habr.com

Adicionar um comentário