Se o seu cluster K8s faz solicitações externas — para APIs de parceiros, para marketplaces, para plataformas de publicidade — mais cedo ou mais tarde você enfrentará bloqueios por IP. O Ingress Controller por si só gerencia o tráfego de entrada, mas para solicitações de saída através dos pods é necessário um esquema separado com proxy. Neste artigo, analisamos como configurá-lo corretamente: desde a escolha do tipo de proxy até configurações YAML específicas para NGINX Ingress e Traefik.
Por que usar proxy no Kubernetes: cenários reais
Kubernetes é um orquestrador, e a maioria dos artigos sobre ele fala sobre tráfego de entrada: como configurar o Ingress, como emitir um certificado TLS, como rotear solicitações para serviços. Mas há outro lado: o tráfego de saída dos pods. É aqui que surgem problemas com bloqueios, geobloqueios e limites de IP.
Vamos considerar tarefas específicas onde um proxy no cluster K8s se torna uma necessidade:
- Raspagem e monitoramento de preços. Seu cluster executa um CronJob a cada 15 minutos e coleta dados do Wildberries, Ozon, Amazon. Sem rotação de IP, após 2–3 horas você receberá um bloqueio em todo o intervalo de IP do seu provedor de nuvem.
- Trabalho com APIs de publicidade. Facebook Marketing API, TikTok Ads API, Google Ads API — todos eles rastreiam a origem das solicitações. Se dezenas de pods enviam solicitações de um único IP de data center, isso é um gatilho para bloqueio automático.
- Teste de geolocalização. Seu serviço deve mostrar conteúdo diferente para usuários de diferentes países. Através de um proxy, os pods podem simular solicitações das regiões necessárias para testes automatizados.
- Contornando restrições corporativas. Em algumas infraestruturas, todo o tráfego de saída deve passar por um proxy corporativo — isso é um requisito de conformidade.
- Trabalho com APIs de parceiros com lista branca de IP. Quando um parceiro permite solicitações apenas de IPs específicos, e seu cluster está escalando e mudando endereços — um proxy com IPs estáticos resolve o problema.
É importante entender a separação arquitetônica: Ingress Controller gerencia o tráfego de entrada (dos usuários para seus serviços), enquanto o proxy para solicitações de saída é uma tarefa separada. No entanto, eles estão interligados: a configuração do proxy é frequentemente definida no nível do mesmo Ingress Controller ou através de anotações que ele lê.
💡 Distinção chave
Neste artigo, analisamos dois cenários: (1) configuração do Ingress Controller como um proxy reverso para servidores upstream externos, e (2) roteamento de tráfego de saída dos pods através de um servidor proxy externo. Ambos os cenários são encontrados em produção.
Qual tipo de proxy escolher para o cluster K8s
A escolha do tipo de proxy afeta diretamente quanto tempo seu cluster poderá operar sem bloqueios. IPs de data center são os mais baratos, mas são facilmente identificáveis e bloqueáveis. IPs residenciais e móveis são mais caros, mas significativamente mais confiáveis para tarefas onde a simulação de um usuário real é importante.
| Tipo de proxy | Velocidade | Risco de bloqueio | Melhor cenário no K8s |
|---|---|---|---|
| Data center | Alta | Alto | APIs internas, conformidade corporativa, integrações de parceiros com lista branca de IP |
| Residenciais | Média | Baixo | Raspagem de marketplaces, trabalho com APIs de publicidade, geoteste |
| Móveis | Média | Mínimo | Facebook Ads API, TikTok API, tarefas de alta carga com risco de banimento |
Para a maioria das tarefas no cluster K8s relacionadas à raspagem ou trabalho com plataformas de publicidade, a escolha ideal é proxies residenciais com rotação. Eles fornecem IPs reais de usuários domésticos, e os algoritmos de proteção dos sites percebem tais solicitações como tráfego de navegador comum.
Do ponto de vista do protocolo, o proxy HTTP/HTTPS é o mais versátil para K8s — é suportado por todos os clientes HTTP populares em qualquer linguagem de programação através das variáveis de ambiente padrão HTTP_PROXY e HTTPS_PROXY. SOCKS5 é necessário apenas para protocolos não padrão ou quando é necessário proxy não apenas HTTP.
Configuração de proxy através do NGINX Ingress Controller
O NGINX Ingress Controller é a opção mais comum no K8s. Vamos considerar dois cenários: configuração do NGINX como um proxy reverso para um upstream externo através de um servidor proxy, e configuração global de proxy de saída para o próprio controlador.
Anotações para proxy de solicitações para upstream
O NGINX Ingress suporta anotações para gerenciar o comportamento do proxy. Se você precisa que o Ingress envie solicitações para um serviço externo através de um proxy intermediário, use um ConfigMap com uma configuração personalizada:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
data:
# Proxy HTTP global para solicitações de saída do NGINX
http-snippet: |
proxy_connect_timeout 10s;
proxy_read_timeout 30s;
proxy_send_timeout 30s;
# Configuração de upstream através de proxy
use-proxy-protocol: "false"
proxy-real-ip-cidr: "0.0.0.0/0"
Recurso Ingress com anotações para proxy
Para um recurso Ingress separado, você pode definir parâmetros de proxy através de anotações. Isso é útil quando diferentes serviços exigem diferentes timeouts e configurações:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-service-ingress
namespace: production
annotations:
kubernetes.io/ingress.class: "nginx"
# Timeouts do proxy
nginx.ingress.kubernetes.io/proxy-connect-timeout: "10"
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
# Tamanho do buffer
nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
nginx.ingress.kubernetes.io/proxy-buffers-number: "8"
# Transmitir o IP real do cliente
nginx.ingress.kubernetes.io/use-forwarded-headers: "true"
nginx.ingress.kubernetes.io/forwarded-for-header: "X-Forwarded-For"
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
Configuração de proxy externo para solicitações de saída do pod NGINX
Se o próprio NGINX Ingress Controller deve fazer solicitações de saída através de um proxy externo (por exemplo, para verificação de saúde de endpoints externos), você precisa definir variáveis de ambiente no Deployment do controlador:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
template:
spec:
containers:
- name: controller
image: registry.k8s.io/ingress-nginx/controller:v1.9.4
env:
- name: HTTP_PROXY
valueFrom:
secretKeyRef:
name: proxy-credentials
key: http-proxy-url
- name: HTTPS_PROXY
valueFrom:
secretKeyRef:
name: proxy-credentials
key: https-proxy-url
- name: NO_PROXY
value: "localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.cluster.local"
Preste atenção à variável NO_PROXY — ela é criticamente importante. Sem ela, todo o tráfego intra-cluster também passará pelo proxy externo, o que quebrará a interação entre os serviços. Em NO_PROXY, sempre inclua os intervalos RFC-1918 e o sufixo .cluster.local.
Configuração de proxy no Traefik Ingress Controller
Traefik é uma alternativa popular ao NGINX Ingress, especialmente em conjunto com Helm e em clusters gerenciados (k3s, Docker Swarm, Nomad). O Traefik possui seu próprio sistema de configuração através de CRD (Custom Resource Definitions) e configurações estáticas/dinâmicas.
Configuração estática do Traefik com proxy
apiVersion: v1
kind: ConfigMap
metadata:
name: traefik-config
namespace: traefik
data:
traefik.yaml: |
# Configuração estática do Traefik
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
# Configurações para operação atrás de um proxy
serversTransport:
insecureSkipVerify: false
maxIdleConnsPerHost: 200
dialTimeout: 10s
responseHeaderTimeout: 30s
# Registro para diagnóstico de proxy
log:
level: INFO
accessLog:
fields:
headers:
defaultMode: keep
names:
X-Forwarded-For: keep
X-Real-IP: keep
Middleware para adicionar cabeçalhos de proxy
No Traefik, você pode criar um Middleware que adiciona ou modifica cabeçalhos ao passar solicitações. Isso é útil para transmitir corretamente o IP real do cliente através da cadeia de proxies:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: proxy-headers
namespace: production
spec:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
# Remover cabeçalhos que podem revelar a infraestrutura
customResponseHeaders:
X-Powered-By: ""
Server: ""
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: my-app-route
namespace: production
spec:
entryPoints:
- websecure
routes:
- match: Host(`myapp.example.com`)
kind: Rule
middlewares:
- name: proxy-headers
services:
- name: my-service
port: 80
Variáveis de ambiente para o Deployment do Traefik
Assim como no NGINX, para o Traefik definimos variáveis de ambiente através de valores do Helm ou diretamente no Deployment. Ao usar o Helm Chart, isso é feito através do values.yaml:
# values.yaml para o Helm chart do Traefik
deployment:
enabled: true
kind: Deployment
env:
- name: HTTP_PROXY
valueFrom:
secretKeyRef:
name: proxy-credentials
key: http-proxy-url
- name: HTTPS_PROXY
valueFrom:
secretKeyRef:
name: proxy-credentials
key: https-proxy-url
- name: NO_PROXY
value: "localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/16,.cluster.local,.svc"
Proxy através de variáveis de ambiente nos pods
A maneira mais versátil de configurar um proxy de saída para qualquer pod é através de variáveis de ambiente padrão. Este método funciona independentemente da linguagem de programação e do framework: Python requests, Go net/http, Node.js axios, Java HttpClient — todos eles leem HTTP_PROXY e HTTPS_PROXY automaticamente.
Opção 1: Diretamente no Pod Spec
apiVersion: v1
kind: Pod
metadata:
name: scraper-pod
namespace: production
spec:
containers:
- name: scraper
image: mycompany/scraper:latest
env:
- name: HTTP_PROXY
value: "http://username:[email protected]:8080"
- name: HTTPS_PROXY
value: "http://username:[email protected]:8080"
- name: NO_PROXY
value: "localhost,127.0.0.1,10.0.0.0/8,.cluster.local"
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
⚠️ Não armazene credenciais em texto claro!
O exemplo acima é mostrado para fins ilustrativos. Em produção, as credenciais do proxy sempre devem ser armazenadas em Kubernetes Secret e passadas através de secretKeyRef. Mais detalhes — na seção sobre Secrets abaixo.
Opção 2: Através de ConfigMap para vários pods
Se o proxy for utilizado por vários Deployments, é conveniente extrair as configurações para um ConfigMap e conectá-lo através de envFrom:
apiVersion: v1
kind: ConfigMap
metadata:
name: proxy-config
namespace: production
data:
NO_PROXY: "localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,.cluster.local,.svc.cluster.local"
PROXY_TIMEOUT: "30"
PROXY_MAX_RETRIES: "3"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: price-monitor
namespace: production
spec:
replicas: 5
selector:
matchLabels:
app: price-monitor
template:
metadata:
labels:
app: price-monitor
spec:
containers:
- name: monitor
image: mycompany/price-monitor:v2.1
envFrom:
- configMapRef:
name: proxy-config
- secretRef:
name: proxy-credentials
ports:
- containerPort: 8080
Opção 3: Mutating Webhook Admission Controller
Para clusters corporativos, onde todos os pods são obrigados a usar proxy, pode-se configurar um webhook de admissão mutante que adiciona automaticamente as variáveis de ambiente do proxy a todos os pods criados. Esta solução é utilizada em infraestruturas empresariais, onde a conformidade exige que todo o tráfego de saída passe por um proxy corporativo. A implementação de tal webhook está além do escopo deste artigo, mas vale a pena saber de sua existência.
Rotação de IP e gerenciamento do pool de proxies no K8s
Um proxy estático é bom para conformidade corporativa, mas ruim para tarefas onde é necessário evitar bloqueios. Se 50 dos seus pods enviam solicitações através do mesmo IP, esse IP será bloqueado muito rapidamente. A solução é a rotação de proxies.
Esquema com Proxy Sidecar
Um dos padrões é executar um agente proxy como um contêiner sidecar ao lado do aplicativo principal. O sidecar aceita solicitações em localhost:8080 e as reencaminha através de um pool rotativo de proxies externos:
apiVersion: apps/v1
kind: Deployment
metadata:
name: scraper-with-proxy-sidecar
namespace: production
spec:
replicas: 10
selector:
matchLabels:
app: scraper
template:
metadata:
labels:
app: scraper
spec:
containers:
# Aplicativo principal
- name: scraper
image: mycompany/scraper:latest
env:
- name: HTTP_PROXY
value: "http://localhost:8080"
- name: HTTPS_PROXY
value: "http://localhost:8080"
- name: NO_PROXY
value: "localhost,127.0.0.1,.cluster.local"
# Sidecar: agente proxy local com rotação
- name: proxy-rotator
image: mycompany/proxy-rotator:latest
ports:
- containerPort: 8080
env:
- name: PROXY_LIST_URL
valueFrom:
secretKeyRef:
name: proxy-credentials
key: api-endpoint
- name: ROTATION_INTERVAL
value: "60" # rotação a cada 60 segundos
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "200m"
Esquema com Proxy Service centralizado
Uma abordagem alternativa é ter um único Proxy Service dentro do cluster, ao qual todos os pods se conectam. Isso é mais fácil de gerenciar: basta atualizar um Secret com as credenciais do proxy, e todos os pods começarão automaticamente a usar os novos dados.
apiVersion: v1
kind: Service
metadata:
name: proxy-gateway
namespace: proxy-system
spec:
selector:
app: proxy-gateway
ports:
- name: http
port: 8080
targetPort: 8080
- name: socks5
port: 1080
targetPort: 1080
type: ClusterIP
---
# Os pods usam proxy através do DNS interno
# HTTP_PROXY=http://proxy-gateway.proxy-system.svc.cluster.local:8080
Para tarefas onde a anonimidade e o risco mínimo de bloqueios são críticos (por exemplo, raspagem de marketplaces ou trabalho com APIs de publicidade), recomendamos usar proxies residenciais com rotação — eles fornecem IPs reais de usuários domésticos, tornando o tráfego do seu cluster indistinguível do tráfego de um navegador comum.
Armazenamento de credenciais de proxy em Kubernetes Secrets
O armazenamento seguro de credenciais é um requisito obrigatório para qualquer cluster de produção. Nunca insira login/senha do proxy diretamente nos manifestos YAML que são armazenados em repositórios Git.
Criação de Secret para proxy
# Criação através do kubectl (os valores são codificados em base64 automaticamente)
kubectl create secret generic proxy-credentials \
--namespace=production \
--from-literal=http-proxy-url='http://user:[email protected]:8080' \
--from-literal=https-proxy-url='http://user:[email protected]:8080' \
--from-literal=socks5-proxy-url='socks5://user:[email protected]:1080'
# Verificação do Secret criado
kubectl get secret proxy-credentials -n production -o yaml
Manifesto YAML do Secret
apiVersion: v1
kind: Secret
metadata:
name: proxy-credentials
namespace: production
labels:
app: proxy-config
managed-by: ops-team
type: Opaque
# Valores codificados em base64
# echo -n 'http://user:pass@proxy:8080' | base64
stringData:
# stringData permite especificar valores em texto claro
# Kubernetes os codifica automaticamente em base64
http-proxy-url: "http://user:[email protected]:8080"
https-proxy-url: "http://user:[email protected]:8080"
proxy-host: "gate.proxycove.com"
proxy-port: "8080"
proxy-username: "user"
proxy-password: "password"
Uso do Secret no Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-worker
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: api-worker
template:
metadata:
labels:
app: api-worker
spec:
containers:
- name: worker
image: mycompany/api-worker:latest
env:
- name: HTTP_PROXY
valueFrom:
secretKeyRef:
name: proxy-credentials
key: http-proxy-url
- name: HTTPS_PROXY
valueFrom:
secretKeyRef:
name: proxy-credentials
key: https-proxy-url
- name: NO_PROXY
value: "localhost,127.0.0.1,10.0.0.0/8,.cluster.local"
# Para aplicativos que leem host/porta separadamente
- name: PROXY_HOST
valueFrom:
secretKeyRef:
name: proxy-credentials
key: proxy-host
- name: PROXY_PORT
valueFrom:
secretKeyRef:
name: proxy-credentials
key: proxy-port
Integração com armazenamentos externos de segredos
Em um ambiente corporativo, é recomendável usar o External Secrets Operator para sincronizar segredos do HashiCorp Vault, AWS Secrets Manager ou Azure Key Vault. Isso permite atualizar automaticamente as credenciais do proxy sem intervenção manual e reinicialização dos pods:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: proxy-credentials-ext
namespace: production
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: ClusterSecretStore
target:
name: proxy-credentials
creationPolicy: Owner
data:
- secretKey: http-proxy-url
remoteRef:
key: secret/proxy/proxycove
property: http_proxy_url
- secretKey: https-proxy-url
remoteRef:
key: secret/proxy/proxycove
property: https_proxy_url
Diagnóstico e erros comuns ao configurar proxy no K8s
Mesmo com a configuração correta, podem surgir problemas. Vamos analisar os mais comuns e as formas de diagnóstico.
Problema 1: O tráfego intra-cluster passa pelo proxy
Sintoma: os pods param de se ver, a resolução DNS dentro do cluster falha, os serviços não respondem. A causa — a variável NO_PROXY não está configurada.
O valor mínimo necessário para NO_PROXY para um cluster K8s padrão:
NO_PROXY=localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.cluster.local,.svc,.svc.cluster.local,kubernetes.default.svc
Problema 2: O proxy não é aplicado a um pod específico
Diagnóstico: entre no pod e verifique as variáveis de ambiente:
# Verificar variáveis de ambiente no pod
kubectl exec -it <pod-name> -n production -- env | grep -i proxy
# Testar conexão através do proxy a partir do pod
kubectl exec -it <pod-name> -n production -- curl -v --proxy http://proxy:8080 https://httpbin.org/ip
# Verificar se o Secret está montado corretamente
kubectl exec -it <pod-name> -n production -- env | grep PROXY
Problema 3: Erros TLS ao usar proxy HTTPS
Se o proxy usa um certificado autoassinado ou CA corporativa, os aplicativos receberão erros de verificação TLS. A solução — adicionar o certificado CA do proxy aos confiáveis:
# Criar ConfigMap com o certificado CA
kubectl create configmap proxy-ca-cert \
--from-file=proxy-ca.crt=./proxy-ca.crt \
-n production
# Montar no pod
spec:
containers:
- name: app
volumeMounts:
- name: proxy-ca
mountPath: /etc/ssl/certs/proxy-ca.crt
subPath: proxy-ca.crt
volumes:
- name: proxy-ca
configMap:
name: proxy-ca-cert
Problema 4: Solicitações lentas através do proxy
Se as solicitações através do proxy são significativamente mais lentas do que as diretas — verifique:
- Resolução DNS: certifique-se de que as solicitações DNS não estão passando pelo proxy (adicione ao
NO_PROXY) - Conexões Keep-alive: configure o pool de conexões para o servidor proxy
- Localização geográfica: o servidor proxy deve estar fisicamente próximo ao recurso de destino
- Tipo de proxy: para tarefas de alta velocidade, considere proxies de data center — eles oferecem a menor latência
Comandos úteis para diagnóstico
# Verificar logs do Ingress Controller
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=100
# Verificar eventos do pod
kubectl describe pod <pod-name> -n production
# Testar conexão proxy a partir do pod
kubectl run test-proxy --image=curlimages/curl --rm -it --restart=Never -- \
curl -x http://user:pass@proxy:8080 -v https://httpbin.org/ip
# Verificar se o Secret existe e contém as chaves necessárias
kubectl get secret proxy-credentials -n production -o jsonpath='{.data}' | python3 -c "
import sys, json, base64
data = json.load(sys.stdin)
for k, v in data.items():
print(f'{k}: {base64.b64decode(v).decode()[:20]}...')
"
Conclusão e recomendações
Configurar um proxy no Kubernetes não é uma tarefa única, mas parte da arquitetura de segurança da rede do cluster. Vamos resumir:
- Para NGINX Ingress Controller — use anotações para configurar os parâmetros do proxy no nível de recursos Ingress individuais, e variáveis de ambiente no Deployment para configurações globais de tráfego de saída.
- Para Traefik — combine configuração estática através de ConfigMap com Middleware para gerenciar cabeçalhos.
- Para pods — as variáveis padrão
HTTP_PROXY/HTTPS_PROXYatravés de Secrets — é a abordagem mais versátil e segura. - Sempre configure NO_PROXY — caso contrário, o tráfego intra-cluster será quebrado.
- Nunca armazene credenciais do proxy em texto claro em manifestos ou no Git.
- Para produção — use o External Secrets Operator para rotação automática de credenciais.
Se o seu cluster K8s executa tarefas onde a estabilidade do IP e o risco mínimo de bloqueios são críticos — raspagem, trabalho com APIs de publicidade, geoteste — recomendamos usar proxies residenciais. Eles fornecem IPs reais de usuários domésticos, que os algoritmos de proteção percebem como tráfego legítimo. Para tarefas com altas exigências de velocidade e riscos mínimos de bloqueios por parte de plataformas móveis, os proxies móveis são uma excelente opção — eles operam através de redes reais 4G/5G de operadoras.
```