Network Policies: isolando tráfego entre pods

1. Introdução ao Isolamento de Tráfego em Kubernetes

1.1. Por que o isolamento padrão do Kubernetes é insuficiente

Por padrão, o Kubernetes adota uma topologia de flat network — todos os Pods podem se comunicar com todos os outros Pods, independentemente do namespace. Essa abertura total é conveniente para desenvolvimento, mas representa um risco grave de segurança em produção. Um atacante que comprometa um Pod pode se mover lateralmente para qualquer serviço interno, acessar bancos de dados ou até mesmo exfiltrar dados.

1.2. O papel das Network Policies na segurança de microsserviços

As Network Policies atuam como firewalls virtuais no nível do Pod, definindo regras de tráfego baseadas em labels, namespaces e IP blocks. Elas implementam o princípio do menor privilégio: um Pod deve se comunicar apenas com os serviços estritamente necessários para sua função.

1.3. Pré-requisitos: CNI plugins compatíveis

Network Policies não funcionam com todos os CNI plugins. É necessário que o plugin suporte o recurso. Os mais comuns são:

  • Calico (padrão em muitos clusters gerenciados)
  • Cilium (baseado em eBPF, alta performance)
  • Weave Net
  • Antrea
  • Flannel (não suporta Network Policies nativamente — requer extensão)

Verifique seu CNI com:

kubectl get pods -n kube-system | grep -E "calico|cilium|weave|antrea"

2. Anatomia de uma Network Policy

2.1. Estrutura YAML

Toda Network Policy segue esta estrutura básica:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080

2.2. Seletores de pods e namespaces

Labels são o mecanismo de identidade em Kubernetes. Uma Network Policy pode selecionar Pods alvo (podSelector) e Pods origem (from.podSelector). Também é possível selecionar namespaces inteiros:

ingress:
  - from:
      - namespaceSelector:
          matchLabels:
            environment: production

2.3. Regras de entrada e saída

As regras podem especificar:

  • Ingress: tráfego que chega ao Pod
  • Egress: tráfego que sai do Pod
  • Ambos os tipos, com combinações de:
  • podSelector (pods específicos)
  • namespaceSelector (namespaces específicos)
  • ipBlock (faixas CIDR externas)
  • ports (portas e protocolos)

3. Políticas de Ingress: Controlando Tráfego de Entrada

3.1. Permitindo tráfego apenas de pods específicos

Exemplo: apenas Pods com label app: frontend podem acessar Pods app: backend na porta 8080:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-ingress
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080

3.2. Restringindo acesso por namespace de origem

Para isolar ambientes (dev, staging, production):

ingress:
  - from:
      - namespaceSelector:
          matchLabels:
            environment: production
      - podSelector:
          matchLabels:
            app: api-gateway

3.3. Combinando seletores com ipBlock

Para permitir tráfego externo controlado (ex: monitoramento Prometheus):

ingress:
  - from:
      - ipBlock:
          cidr: 10.0.0.0/24
          except:
            - 10.0.0.5/32
    ports:
      - port: 9090

4. Políticas de Egress: Controlando Tráfego de Saída

4.1. Bloqueando comunicação indesejada

Por padrão, um Pod pode acessar qualquer destino. Com política de egress, restringimos:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: app-egress
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
    - Egress
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: database
      ports:
        - port: 5432

4.2. Permitindo acesso seletivo

Para acesso a bancos de dados, caches ou APIs externas:

egress:
  - to:
      - ipBlock:
          cidr: 192.168.1.0/24
    ports:
      - port: 6379  # Redis
  - to:
      - ipBlock:
          cidr: 0.0.0.0/0
    ports:
      - port: 443

4.3. Uso de ports e ipBlock

Restringir saída apenas para DNS e API externa específica:

egress:
  - to:
      - ipBlock:
          cidr: 10.96.0.10/32  # CoreDNS
    ports:
      - port: 53
        protocol: UDP
  - to:
      - ipBlock:
          cidr: 203.0.113.0/24
    ports:
      - port: 443

5. Estratégias de Isolamento por Ambiente e Aplicação

5.1. Abordagem "default deny" vs. "default allow"

Default deny é a prática recomendada para produção:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

Isso bloqueia todo tráfego. Em seguida, crie políticas específicas para liberar o necessário.

Default allow é o comportamento nativo do Kubernetes — inseguro para produção, mas útil para desenvolvimento.

5.2. Políticas por camada

Arquitetura típica de três camadas:

  • Frontend: permite ingress do Ingress Controller, egress para Backend
  • Backend: permite ingress do Frontend, egress para Database
  • Database: permite ingress apenas do Backend na porta 5432

5.3. Isolamento multi-tenant

Para times diferentes no mesmo cluster:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-cross-namespace
  namespace: team-alpha
spec:
  podSelector: {}
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: team-alpha

6. Monitoramento, Depuração e Troubleshooting

6.1. Verificando políticas aplicadas

kubectl get networkpolicy -n <namespace>
kubectl describe networkpolicy <nome> -n <namespace>

6.2. Ferramentas de diagnóstico

Teste conectividade com:

kubectl exec -it <pod-name> -- curl http://<target-service>:<port>
kubectl exec -it <pod-name> -- nc -zv <target-ip> <port>

Para logs detalhados, verifique os logs do CNI:

kubectl logs -n kube-system <calico-node-pod> | grep -i policy

6.3. Problemas comuns

  • Políticas conflitantes: regras mais específicas podem ser sobrescritas por regras mais genéricas
  • Ordem de avaliação: regras são avaliadas em ordem, mas a primeira correspondência vence
  • Falsos positivos: um Pod pode estar sem labels corretas, fazendo a política não se aplicar

Solução: sempre verifique os labels dos Pods e use kubectl get pods --show-labels.

7. Boas Práticas e Integração com o Fluxo DevOps

7.1. Versionamento de Network Policies no Git

Trate Network Policies como código:

infra/
├── namespaces/
│   └── production/
│       └── network-policies/
│           ├── default-deny.yaml
│           ├── frontend.yaml
│           ├── backend.yaml
│           └── database.yaml

7.2. Testes automatizados de conectividade

Em pipelines CI/CD, use ferramentas como k6 ou curl em Pods temporários:

kubectl run test-pod --image=alpine/curl --rm -it --restart=Never -- /bin/sh -c "curl -s http://backend-svc:8080/health"

7.3. Relação com temas vizinhos

Network Policies se integram com:

  • GitOps (ArgoCD, Flux): políticas aplicadas automaticamente
  • External Secrets: senhas de bancos que as políticas protegem
  • Resource Quotas: limite de recursos por namespace
  • Pod Security Standards: políticas de segurança em nível de Pod

Referências