Túnel seguro: do localhost ao banco de dados, pelo cluster
No desktop, você trabalha da sua própria máquina: o Kubepier abre um túnel seguro pelo cluster Kubernetes até o banco de dados (um port-forward até o Service, ou um repasse até o RDS e outros hosts da rede) e um terminal local (bash ou zsh no Linux e no macOS, PowerShell no Windows) que lista cada localhost:<porta> → destino. Não há terminal dentro de pod nem campo de chave: você usa os seus clientes e as suas chaves.
O que faz
| Modo | Para | Como funciona |
|---|---|---|
| Serviço do cluster | Um Service do Kubernetes (um banco, uma API, um painel que roda no cluster) | Port-forward direto para o Service. Nenhum pod é criado. |
| Host na rede do cluster | Um host que o cluster alcança fora dele: RDS, Azure Database, VM, banco gerenciado | Um pod de repasse mínimo e restrito (só socat, sem acesso interativo) leva até 5 túneis e é apagado quando o último túnel fecha, em 2 horas ou quando o app fecha. |
Em qualquer modo, a porta local escuta só em 127.0.0.1.
Qual usar?
| Ferramenta | Onde | De onde a conexão parte | Use quando |
|---|---|---|---|
| Shell no pod | Web e desktop | De dentro de um container da aplicação | Você precisa entrar num container que já roda. |
| Shell no nó | Web (admin) e desktop | De um pod privilegiado no próprio nó | O problema é do nó: kubelet, disco, rede do host. |
| Bastion | Só web | De um pod temporário sem privilégios no namespace | Você quer testar ou acessar, pelo navegador, um host que só o cluster alcança (ssh, curl, nc). |
| Túnel seguro | Só desktop | Da sua máquina, passando pelo cluster | Você quer usar os clientes da sua máquina (psql, DBeaver, navegador, ssh) contra um serviço do cluster ou um host da rede dele. |
Passo a passo: pré-requisitos
Plano Pro ou Team. O seu kubeconfig precisa das permissões do modo que você vai usar. Modo Serviço do cluster:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: kubepier-tunel-servico
namespace: <namespace>
rules:
- apiGroups: [""]
resources: ["services", "pods"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["pods/portforward"]
verbs: ["create", "get"] Modo Host na rede do cluster (também cria e apaga o pod de repasse):
Role para o modo Host na rede do cluster
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: kubepier-tunel-relay
namespace: <namespace>
rules:
- apiGroups: [""]
resources: ["services", "pods"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "delete"]
- apiGroups: [""]
resources: ["pods/exec", "pods/portforward"]
verbs: ["create", "get"] list em pods é opcional no modo Host: sem ele, o Kubepier só não apaga relays seus que sobraram. Ligue cada Role à sua identidade com um RoleBinding no mesmo namespace. A rede do cluster precisa alcançar o host de destino.
Passo a passo: abrir um túnel
- No menu do cluster, ou no + do painel inferior, escolha Túnel seguro.
- Escolha o modo. Serviço do cluster: informe o Namespace, escolha o Serviço e a Porta. Host na rede do cluster: informe o Namespace onde o relay vai rodar, o Host de destino e a Porta, como o cluster os enxerga.
- Em Porta local, informe uma porta ou deixe automática.
- Clique em Abrir túnel. No modo Host, o relay aparece como Iniciando e depois Pronto (até 120 segundos).
- O painel Túneis lista localhost:<porta> → destino, com Copiar e, para portas conhecidas, Copiar comando (psql, mysql, redis-cli, ssh -p, sqlcmd, mongosh ou a URL para o navegador).
- Abrir terminal local abre um terminal da sua máquina (bash ou zsh no Linux e no macOS, PowerShell no Windows) com o cabeçalho Túneis seguros ativos: e as variáveis KUBEPIER_TUNNEL_1, KUBEPIER_TUNNEL_2… com 127.0.0.1:<porta> de cada túnel. Os terminais locais desse cluster recebem o mesmo.
Exemplo: port-forward até o PostgreSQL no RDS ou no Azure
Modo Host na rede do cluster, destino meu-rds.xxxx.rds.amazonaws.com:5432, porta local 15432:
# Linux e macOS (bash/zsh) e Windows (PowerShell): o mesmo comando
psql "host=127.0.0.1 port=15432 user=app dbname=app sslmode=require" No DBeaver: Host 127.0.0.1, Port 15432, Database app, User app; em SSL, modo require. O certificado do servidor tem o nome do RDS ou do Azure, não 127.0.0.1, então verify-full falha na verificação de nome: use require, ou informe o nome do servidor esperado se o cliente permitir.
Exemplo: MySQL
Destino na porta 3306, porta local 13306:
mysql -h 127.0.0.1 -P 13306 -u app -p app Use 127.0.0.1, não localhost: com localhost, o cliente mysql tenta o socket local. No Windows, o mesmo comando funciona no PowerShell com o mysql.exe no PATH.
Exemplo: Redis
Destino na porta 6379 (6380 com TLS no Azure Cache), porta local 16379:
redis-cli -h 127.0.0.1 -p 16379 --tls
# servidor sem TLS:
redis-cli -h 127.0.0.1 -p 16379 Com TLS, o nome do certificado também não bate com 127.0.0.1; se o redis-cli recusar, use --sni com o nome do servidor (ou --insecure só para o teste).
Exemplo: SSH numa VM interna
Modo Host na rede do cluster, destino 10.0.1.20:22, porta local 2222:
# Linux e macOS
ssh -p 2222 usuario@127.0.0.1
scp -P 2222 usuario@127.0.0.1:/var/log/app.log .
rsync -e "ssh -p 2222" -av usuario@127.0.0.1:/srv/app/ ./app/
# Windows (PowerShell, OpenSSH do Windows)
ssh -p 2222 usuario@127.0.0.1
scp -P 2222 usuario@127.0.0.1:/var/log/app.log . O known_hosts registra a VM como [127.0.0.1]:2222. O rsync não vem no Windows: use scp, ou o WSL.
Exemplo: SQL Server e MongoDB
# SQL Server (porta local 11433)
sqlcmd -S 127.0.0.1,11433 -U app
# MongoDB (porta local 27018); directConnection evita que o driver tente os outros membros do replica set
mongosh "mongodb://app@127.0.0.1:27018/app?directConnection=true" Exemplo: painel HTTP interno
Destino na porta 80 ou 8080, porta local 8080. Abra http://localhost:8080 no navegador.
# Linux e macOS
curl -H "Host: painel.interno" http://localhost:8080/
# Windows (PowerShell)
Invoke-WebRequest -Uri http://localhost:8080/ -Headers @{ Host = "painel.interno" } Se o serviço responde por virtual host (cabeçalho Host), ele pode recusar localhost. Teste com o cabeçalho acima, ou aponte painel.interno para 127.0.0.1 no arquivo hosts e abra http://painel.interno:8080.
Limites e tempos
| Limite | Valor |
|---|---|
| Túneis por modo, por cluster | até 5 |
| Pod de repasse (relay) | 1 por cluster por pessoa; espera até 120 s ficar pronto; apagado ao fechar o último túnel, em 2 horas ou quando o app fecha |
| Imagem do relay | a mesma do Bastion: docker.io/nicolaka/netshoot:v0.16@sha256:b09d9b21381f47a79b3cbcb30da25266dc17186ea00ae65e99fdc51396f48e70 |
| Porta local | só 127.0.0.1 |
Auditoria
- Cada túnel aberto e fechado (tunel_abrir, tunel_fechar) e cada pod de repasse criado e removido (relay_criar, relay_remover) vão para o kubepier-audit.log, com quem, quando, cluster, namespace e destino.
- Nunca o tráfego que passa pelo túnel.
Erros comuns
- Connection refused: host ou porta errados, ou um NSG/security group bloqueia a sub-rede dos nós do cluster. Teste o destino com nc -vz pelo Bastion da web.
- Porta local em uso: escolha outra porta local.
- A imagem do relay não baixou: os nodes não saem para o Docker Hub; espelhe docker.io/nicolaka/netshoot:v0.16@sha256:b09d9b21381f47a79b3cbcb30da25266dc17186ea00ae65e99fdc51396f48e70 no registry da empresa.
- Já existe um relay seu ativo: feche-o ou espere expirar; é um por cluster.
- Limite de túneis: no máximo 5 por modo neste cluster.
- PodSecurity ou admissão recusou o repasse: ele já é restricted; confira políticas próprias do cluster.
- 403: falta um verbo do Role do modo escolhido.