Network Policies em Kubernetes: Isolamento de Rede entre Pods
Network Policies são recursos fundamentais do Kubernetes que permitem controlar o tráfego de rede entre pods, implementando segurança em nível de microsserviços. Por padrão, o Kubernetes permite comunicação irrestrita entre todos os pods em um cluster, o que viola o princípio do menor privilégio. Com Network Policies, você define regras explícitas de entrada (ingress) e saída (egress) de tráfego, criando um modelo de segurança robusto e granular.
Neste artigo, vamos explorar como as Network Policies funcionam, quando e por que utilizá-las, e como implementá-las de forma prática em seus clusters. Entender esse conceito é essencial para qualquer engenheiro que trabalha com Kubernetes em ambientes de produção.
O que é uma Network Policy e Como Funciona
Entendendo o Conceito Fundamental
Uma Network Policy é um objeto Kubernetes que define regras de firewall para pods. Ela atua no nível de rede, controlando quais pods podem se comunicar entre si através de seletores de labels. Quando uma Network Policy é criada, o controlador de rede do cluster (como Calico, Weave ou Cilium) implementa essas regras no sistema operacional do nó, geralmente através de iptables ou eBPF.
A grande diferença entre Network Policy e um firewall tradicional é que ela trabalha com abstrações do Kubernetes (labels, namespaces) ao invés de endereços IP. Isso torna as regras portáveis e dinâmicas: mesmo que um pod seja recriado com um novo IP, a política continua aplicável porque se baseia em labels.
Componentes de uma Network Policy
Uma Network Policy consiste em quatro elementos principais:
- podSelector: Define quais pods a política se aplica (usando labels)
- policyTypes: Especifica se a política controla tráfego de Ingress, Egress ou ambos
- ingress: Lista de regras que permitem tráfego de entrada
- egress: Lista de regras que permitem tráfego de saída
Quando uma Network Policy é aplicada a um pod através do podSelector, esse pod entra em modo restritivo: por padrão, todo tráfego é bloqueado, exceto o explicitamente permitido pelas regras. Isso é importante: ausência de regra significa negação.
Implementando Network Policies na Prática
Exemplo 1: Bloqueio Total com Permissão Seletiva
Vamos começar com um caso simples: bloquear todo o tráfego de entrada e permitir apenas de pods específicos. Este é um padrão muito comum em produção.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
Essa política aplica-se a todos os pods no namespace (porque podSelector: {} está vazio) e nega todo tráfego de entrada. Agora, vamos permitir tráfego apenas de pods com label role: frontend:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-frontend
namespace: default
spec:
podSelector:
matchLabels:
role: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 8080
Aqui, apenas pods com role: backend são afetados. Eles receberão tráfego TCP na porta 8080 vindo de pods com role: frontend. Qualquer outro tráfego é bloqueado.
Exemplo 2: Controle de Egress (Saída)
Nem sempre pensamos em bloquear tráfego de saída, mas é igualmente importante. Vamos criar uma política que permite que um pod de aplicação acesse apenas um banco de dados específico:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-app-to-db
namespace: production
spec:
podSelector:
matchLabels:
app: myapp
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: TCP
port: 53
- protocol: UDP
port: 53
Neste exemplo, o pod myapp pode fazer requisições saintes para:
1. Pods postgres na mesma rede na porta 5432
2. Qualquer pod no namespace kube-system nas portas 53 (DNS)
Observe que adicionamos uma regra DNS. Sem ela, o pod não conseguiria resolver nomes de domínio, mesmo podendo fazer conexões.
Exemplo 3: Política com Múltiplos Critérios
Políticas complexas precisam de múltiplos seletores. Vamos permitir tráfego de múltiplas origens:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: complex-policy
namespace: default
spec:
podSelector:
matchLabels:
tier: api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
- namespaceSelector:
matchLabels:
environment: staging
ports:
- protocol: TCP
port: 8080
- from:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 443
egress:
- to:
- podSelector:
matchLabels:
tier: database
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 443
- protocol: TCP
port: 80
Nesta política:
- Pods com tier: api recebem tráfego na porta 8080 de pods frontend OU de qualquer pod em namespaces com label environment: staging
- Recebem tráfego na porta 443 de qualquer namespace
- Enviam tráfego apenas para pods database na porta 5432 e para qualquer destino nas portas 80 e 443
Estratégias e Melhores Práticas
Começar Restritivo e Evoluir
A abordagem mais segura é começar com uma "deny-all" policy em todos os namespaces e depois adicionar permissões conforme necessário. Muitos engenheiros fazem o oposto e perdem o controle rapidamente.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Quando essa política está em vigor, nenhum pod consegue comunicar. A partir daí, você adiciona exceções necessárias. Essa abordagem garante que você está explicitamente permitindo o que precisa, não tentando negar tudo que não deveria.
Usar Namespaces como Barreira
Namespaces fornecem um isolamento organizacional natural. Combine-os com Network Policies para criar zonas de segurança:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: isolate-namespace
namespace: sensitive-data
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: sensitive-data
egress:
- to:
- namespaceSelector:
matchLabels:
name: sensitive-data
- to:
- podSelector:
matchLabels:
role: external-api
Isso isola um namespace inteiro, permitindo comunicação apenas interna e com serviços externos aprovados.
Debugging e Validação
Para verificar se suas políticas estão funcionando, você pode testar conectividade entre pods:
# Execute um pod de teste
kubectl run -it --rm debug --image=busybox --restart=Never -- sh
# Dentro do pod, teste conectividade
wget -O- http://service-name:port
# Verifique logs de iptables (se disponível)
kubectl exec -it pod-name -- iptables -L -n
Uma ferramenta excelente é o kube-networkpolicy-viewer ou usar logs do seu CNI plugin (Calico, Cilium) para auditoria.
Considerações Técnicas Importantes
Requisitos de Infraestrutura
Network Policies só funcionam com CNI plugins que as suportam. Kubernetes com kubenet (padrão em alguns casos) não funciona com Network Policies. Você precisa de:
- Calico: Excelente suporte, usa iptables/eBPF
- Cilium: Suporte avançado com eBPF, ideal para produção
- Weave: Funciona bem, bom para ambientes menores
- Kube-router: Alternativa leve
Se está usando um serviço gerenciado (EKS, GKE, AKS), o provedor já oferece um CNI compatível.
Performance e Impacto
Network Policies baseadas em iptables podem impactar performance em clusters muito grandes com mudanças frequentes de pods. Cilium com eBPF é mais eficiente. Porém, para a maioria dos casos, o impacto é negligenciável.
Teste em staging antes de rollout em produção. Identifique os padrões de comunicação real:
# Use ferramentas como Cilium CLI para mapear tráfego
cilium connectivity test
# Ou verifique logs do seu observability stack
# (Prometheus, ELK, Jaeger, etc)
Conclusão
Network Policies são um componente essencial de uma arquitetura Kubernetes segura. Os três pontos principais que você deve levar deste artigo são:
-
Princípio do Menor Privilégio: Comece negando tudo e permita apenas o necessário. Isso previne vazamentos de dados e movimentação lateral de ataques.
-
Abstrações Kubernetes: Use labels e seletores, não endereços IP. Isso torna suas políticas resilientes a mudanças dinâmicas de pods e fáceis de manter.
-
Validação Contínua: Network Policies não funcionam isoladas. Combine com observability, auditoria de logs e testes regulares para garantir que estão tendo o efeito desejado.
A implementação de Network Policies não é opcional em ambientes de produção, especialmente quando múltiplas equipes compartilham um cluster. Invista tempo compreendendo os padrões de comunicação reais da sua aplicação antes de implementar as políticas.