E aí, devs! Já precisou expor um serviço do seu cluster Kubernetes pra internet e ficou naquela: abrir porta no firewall, configurar IP público, LoadBalancer, Ingress Controller, cert-manager… uma lista infinita de coisas pra dar errado? 😅
Hoje vou mostrar como resolver isso com Cloudflare Tunnel — sem abrir porta, sem IP público, sem dor de cabeça.
🤔 O que é o Cloudflare Tunnel?
O Cloudflare Tunnel (antigo Argo Tunnel) cria uma conexão de saída entre o seu cluster e a rede da Cloudflare. Ou seja, o tráfego sai do seu pod direto pro edge da Cloudflare. Ninguém precisa entrar no seu servidor.

Internet → Cloudflare Edge → Tunnel (conexão de saída) → cloudflared (pod) → Service → sua app
Pronto. Sem firewall, sem NAT, sem LoadBalancer. Simples assim. 🔥
🛠 Bora pro código
1. Criar o namespace
Primeiro, cria um namespace pra isolar os recursos do tunnel:
kubectl create namespace cloudflared
2. Criar o Secret com o token 🔐
O token do tunnel é sensível — não joga ele direto no Deployment. Cria um Secret:
# secret.yaml apiVersion: v1 kind: Secret metadata: name: cloudflared-token namespace: cloudflared type: Opaque stringData: token: <SEU_TOKEN_AQUI>
kubectl apply -f secret.yaml
Pega o token lá no painel do Cloudflare → Networks → Tunnels. Cria um tunnel e copia o token gerado no campo “Run tunnel with Docker”.
3. Criar o Deployment do cloudflared ⚡
Agora sim, o Deployment que vai rodar o tunnel:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloudflared
namespace: cloudflared
labels:
app: cloudflared
spec:
replicas: 1
selector:
matchLabels:
app: cloudflared
template:
metadata:
labels:
app: cloudflared
spec:
containers:
- name: cloudflared
image: cloudflare/cloudflared:latest
args:
- tunnel
- --no-autoupdate
- run
- --token
- $(TUNNEL_TOKEN)
env:
- name: TUNNEL_TOKEN
valueFrom:
secretKeyRef:
name: cloudflared-token
key: token
resources:
limits:
memory: "128Mi"
cpu: "100m"
requests:
memory: "64Mi"
cpu: "50m"
kubectl apply -f deployment.yaml
Repara nos detalhes:
- ✔
--no-autoupdate— desliga a auto atualização do binário. Quem controla a versão é a imagem Docker, não o próprio cloudflared. - ✔ Token via Secret — o token nunca fica exposto no manifest do Deployment.
- ✔ Resources leves — o cloudflared é muito leve. 50m de CPU e 64Mi de memória dão conta tranquilo.
4. Verificar se tá rodando 🔍
kubectl get pods -n cloudflared kubectl logs -n cloudflared -l app=cloudflared
Se no log aparecer algo como Connection registered, tá tudo certo. O tunnel tá de pé. 💪
5. Subir um Nginx pra testar 🧪
Pra validar que o tunnel tá funcionando de verdade, sobe um Nginx simples:
# nginx.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: cloudflared
labels:
app: nginx
spec:
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: cloudflared
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
resources:
limits:
memory: "128Mi"
cpu: "100m"
requests:
memory: "64Mi"
cpu: "50m"
kubectl apply -f nginx.yaml
Agora vai no painel do Cloudflare Tunnel, adiciona uma Public Hostname apontando pra http://nginx.cloudflared:80 e acessa pelo navegador. Se aparecer a página do Nginx, tá funcionando! 🎉
🔥 Por que usar isso?
Segurança
- Zero portas abertas — o cloudflared só faz conexão de saída. Ninguém entra no seu cluster.
- Token protegido — fica no Secret do Kubernetes, não no YAML do Deployment.
- Zero Trust — integra com o Cloudflare Access pra adicionar autenticação nos serviços expostos. Quer proteger com login? É só ativar.
Custo e simplicidade
- Sem LoadBalancer — elimina custo com IP público e LoadBalancer do cloud provider.
- Sem Ingress Controller — não precisa de Nginx Ingress, Traefik, nem nada.
- Sem cert-manager — o TLS é gerenciado pela Cloudflare automaticamente.
- Baixo consumo — o cloudflared consome quase nada de CPU e memória.
🏁 Resumo
| O que antes era | Agora é |
|---|---|
| IP público + firewall + NAT | Conexão de saída via tunnel |
| Ingress Controller + cert-manager | Cloudflare gerencia tudo |
| LoadBalancer ($$$) | ClusterIP + tunnel (grátis) |
| YAML infinito de config | 2 arquivos e um kubectl apply |
Se você tá com um homelab, cluster pequeno, ou quer expor serviços de dev sem complicação — Cloudflare Tunnel resolve com poucos YAMLs e zero dor de cabeça.
Bora praticar! 💙
✍️ Post produzido por Washington Luiz e Madson Silva