Introdução ao Cilium: rede e observabilidade com eBPF no Kubernetes

1. O que é o Cilium e por que eBPF?

O Kubernetes revolucionou a orquestração de contêineres, mas sua camada de rede tradicional sempre foi um ponto de estrangulamento. O kube-proxy e as regras iptables criavam problemas de desempenho, especialmente em clusters com alta rotatividade de pods. Cada nova regra de rede exigia iterações lineares sobre a cadeia de iptables, causando latência crescente à medida que o cluster escalava.

O eBPF (extended Berkeley Packet Filter) surgiu como uma tecnologia transformadora. Diferentemente dos módulos de kernel tradicionais, o eBPF permite executar código sandboxed no kernel Linux sem a necessidade de recompilá-lo ou arriscar travamentos do sistema. O verificador de eBPF analisa o código antes da execução, garantindo segurança e estabilidade.

O Cilium é uma CNI (Container Network Interface) que aproveita o eBPF para fornecer três capacidades essenciais:

  • Rede de alto desempenho: substitui o kube-proxy por redirecionamento direto via eBPF
  • Segurança granular: políticas de rede baseadas em identidade, não apenas em IPs
  • Observabilidade profunda: Hubble oferece visibilidade de fluxos de rede no nível de aplicação

2. Arquitetura do Cilium no cluster Kubernetes

A arquitetura do Cilium é composta por componentes que trabalham em harmonia:

Cilium Agent: roda em cada nó do cluster e gerencia:
- Programas eBPF anexados a interfaces de rede
- Mapas BPF compartilhados entre processos
- Resolução de identidade de pods via labels

Cilium Operator: responsável por tarefas globais do cluster:
- Gerenciamento de identidades (CiliumIdentity)
- Sincronização de endpoints entre nós
- Migração de políticas quando nós se juntam ou saem

Hubble Relay: agrega fluxos de todos os nós e fornece uma API unificada para consultas.

O Cilium substitui o kube-proxy ao inserir programas eBPF diretamente nos hooks de rede do kernel. Quando um pod tenta se comunicar com um Service, o eBPF intercepta a chamada e realiza o balanceamento de carga sem passar pelo espaço do usuário.

A identidade de pod é gerenciada através de labels. Cada combinação única de labels recebe um identificador numérico (CiliumIdentity), que é usado nas políticas de rede em vez de endereços IP voláteis.

3. Configuração básica e instalação do Cilium

Pré-requisitos: kernel Linux versão 5.10 ou superior com suporte a eBPF. Verifique com:

uname -r
cat /boot/config-$(uname -r) | grep BPF

Instalação via Helm:

helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium --namespace kube-system \
  --set kubeProxyReplacement=true \
  --set hubble.relay.enabled=true \
  --set hubble.ui.enabled=true

Verificação da instalação:

kubectl -n kube-system exec daemonset/cilium -- cilium status
kubectl -n kube-system exec daemonset/cilium -- cilium connectivity test

A saída do cilium status mostra informações sobre o estado do agente, número de endpoints gerenciados e a versão do eBPF em uso. O teste de conectividade valida a comunicação entre pods em diferentes nós.

4. Políticas de rede com CiliumNetworkPolicy

As políticas padrão do Kubernetes (NetworkPolicy) são limitadas a endereços IP e portas. O CiliumNetworkPolicy expande isso para incluir identidade, protocolos de aplicação e até mesmo nomes de domínio.

Exemplo básico: permitir tráfego HTTP apenas do frontend para o backend:

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: production
spec:
  endpointSelector:
    matchLabels:
      app: backend
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: frontend
    toPorts:
    - ports:
      - port: "8080"
        protocol: TCP

Política avançada com FQDN: permitir acesso apenas a domínios específicos:

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-api-external
spec:
  endpointSelector:
    matchLabels:
      app: api-server
  egress:
  - toFQDNs:
    - matchName: "api.external-service.com"
    toPorts:
    - ports:
      - port: "443"
        protocol: TCP

Política HTTP: filtrar por método HTTP e caminho:

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: http-restrict
spec:
  endpointSelector:
    matchLabels:
      app: web
  ingress:
  - fromEndpoints:
    - matchLabels:
        role: frontend
    toPorts:
    - ports:
      - port: "80"
        protocol: TCP
      rules:
        http:
        - method: "GET"
          path: "/api/v1/.*"

5. Observabilidade com Hubble

O Hubble é a camada de observabilidade do Cilium, fornecendo visibilidade em tempo real dos fluxos de rede.

Comandos fundamentais:

# Observar todo o tráfego em um namespace
hubble observe --namespace production

# Filtrar por pod específico
hubble observe --pod backend-7f8b9c

# Filtrar por label
hubble observe --label app=frontend

# Ver fluxos HTTP
hubble observe --protocol HTTP

Exportação para Prometheus: o Cilium expõe métricas no formato Prometheus. Configure o values.yaml:

prometheus:
  enabled: true
  serviceMonitor:
    enabled: true

No Grafana, importe o dashboard oficial do Cilium (ID 12239) para visualizar:
- Taxa de pacotes por segundo
- Latência de rede entre pods
- Número de políticas aplicadas
- Tráfego por protocolo

6. Melhores práticas de desempenho e troubleshooting

Impacto no desempenho: estudos mostram que o Cilium com eBPF reduz a latência de rede em até 60% comparado ao kube-proxy com iptables. O motivo é a eliminação de saltos entre espaço do usuário e kernel.

Depuração de problemas:

# Monitorar eventos em tempo real
cilium monitor --type drop

# Ver mapas BPF
cilium bpf nat list
cilium bpf lb list

# Logs do agente
kubectl -n kube-system logs -l k8s-app=cilium --tail=100

Ajustes de kernel recomendados:

# Aumentar limites de memória para mapas BPF
sysctl -w net.core.bpf_jit_enable=1
sysctl -w kernel.bpf_stats_enabled=1

# Configurar limites de recursos no Helm
--set resources.limits.cpu=1000m
--set resources.limits.memory=1Gi

7. Casos de uso reais e próximos passos

Clusters com alta rotatividade de pods: em ambientes serverless ou CI/CD, onde pods são criados e destruídos constantemente, o Cilium mantém o desempenho porque as políticas são baseadas em identidade, não em IPs.

Ambientes multi-tenancy: com CiliumClusterwideNetworkPolicy, é possível aplicar políticas que abrangem múltiplos namespaces, garantindo isolamento entre tenants.

Integração com service mesh: o Cilium pode atuar como a camada de rede subjacente para Istio e Linkerd, substituindo o sidecar proxy Envoy por programas eBPF mais eficientes.

Próximos passos: o Cilium Mesh promete transformar o Cilium em uma malha de serviço nativa, eliminando a necessidade de sidecars e reduzindo ainda mais a latência. A versão 1.15 já oferece suporte experimental para isso.

Referências