Orquestração de microsserviços com Kubernetes e service mesh

1. Fundamentos da Orquestração com Kubernetes

A orquestração de microsserviços com Kubernetes resolve o problema fundamental de gerenciar dezenas ou centenas de contêineres em produção. Quando um sistema monolítico é decomposto em microsserviços, surgem desafios imediatos: como cada serviço descobre os outros? Como distribuir o tráfego? Como garantir atualizações sem downtime?

Kubernetes oferece primitivas essenciais para isso:

  • Pods: a unidade mínima de computação, que encapsula um ou mais contêineres
  • Services: um ponto de entrada estável para um conjunto de Pods, com balanceamento round-robin
  • Deployments: controlam o estado desejado dos Pods (réplicas, estratégias de rollout)
  • Namespaces: isolamento lógico entre ambientes (dev, staging, production)

Exemplo de um Deployment e Service básicos:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pedidos-api
  namespace: producao
spec:
  replicas: 3
  selector:
    matchLabels:
      app: pedidos
  template:
    metadata:
      labels:
        app: pedidos
    spec:
      containers:
      - name: pedidos
        image: pedidos:v1.2
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: pedidos-svc
  namespace: producao
spec:
  selector:
    app: pedidos
  ports:
  - port: 80
    targetPort: 8080

O Service Discovery funciona via DNS interno: pedidos-svc.producao.svc.cluster.local resolve para os IPs dos Pods ativos.

2. Limitações do Kubernetes para Tráfego de Microsserviços

Apesar de sólido para orquestração básica, o Kubernetes nativo apresenta lacunas críticas quando o tráfego entre microsserviços se torna complexo:

  • Sem gerenciamento avançado de tráfego: não há retry automático, circuit breaker ou timeouts configuráveis por requisição
  • Observabilidade limitada: métricas L4 (conexões TCP) mas sem visibilidade L7 (latência por endpoint, taxa de erro por método HTTP)
  • Segurança no plano de dados: sem mTLS automático entre Pods; políticas de acesso exigem Network Policies manuais e não cobrem identidade de serviço

Exemplo de problema: se o serviço pagamentos falha intermitentemente, o cliente pedidos precisa implementar retry e circuit breaker no código da aplicação — o que viola o princípio de separação de responsabilidades.

3. Introdução ao Service Mesh: Camada de Infraestrutura para Microsserviços

Um service mesh é uma camada de infraestrutura dedicada a gerenciar a comunicação entre serviços. Ele opera em dois planos:

  • Plano de dados: composto por proxies sidecar (Envoy, Linkerd-proxy) que interceptam todo o tráfego de entrada e saída de cada Pod
  • Plano de controle: gerencia a configuração dos proxies (Istiod, Linkerd-controller, Consul-server)

As soluções mais conhecidas são Istio, Linkerd e Consul Connect. Todas seguem o padrão sidecar: um contêiner proxy é injetado automaticamente em cada Pod, sem alterar o código da aplicação.

# Exemplo de Pod com sidecar (Istio)
apiVersion: v1
kind: Pod
metadata:
  annotations:
    sidecar.istio.io/inject: "true"
spec:
  containers:
  - name: pedidos
    image: pedidos:v1.2
  - name: istio-proxy
    image: proxyv2:1.20

A separação de preocupações é clara: o desenvolvedor escreve lógica de negócio; o operador define políticas de tráfego, segurança e observabilidade no mesh.

4. Roteamento Inteligente e Resiliência com Service Mesh

Com o service mesh, é possível implementar estratégias avançadas de roteamento sem tocar no código:

Canary release com roteamento baseado em peso:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: pedidos-vs
spec:
  hosts:
  - pedidos-svc
  http:
  - route:
    - destination:
        host: pedidos-svc
        subset: v1
      weight: 90
    - destination:
        host: pedidos-svc
        subset: v2
      weight: 10
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: pedidos-dr
spec:
  host: pedidos-svc
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

Circuit breaker e retry com backoff:

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: pagamentos-dr
spec:
  host: pagamentos-svc
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100
      http:
        http1MaxPendingRequests: 50
    outlierDetection:
      consecutive5xxErrors: 5
      interval: 30s
      baseEjectionTime: 60s
    retries:
      attempts: 3
      perTryTimeout: 2s
      retryOn: connect-failure,refused-stream,unavailable

Fault injection para testes de resiliência:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: pagamentos-fault
spec:
  hosts:
  - pagamentos-svc
  http:
  - fault:
      delay:
        percentage:
          value: 10
        fixedDelay: 5s
      abort:
        percentage:
          value: 5
        httpStatus: 500
    route:
    - destination:
        host: pagamentos-svc

5. Observabilidade e Segurança no Plano de Dados

O service mesh fornece observabilidade rica sem instrumentação manual:

  • Métricas L7: taxa de requisições, latência (P50, P95, P99), erros HTTP por serviço
  • Tracing distribuído: integração nativa com Jaeger ou Zipkin — cada proxy adiciona headers de tracing automaticamente
# Configuração de tracing no Istio
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    enableTracing: true
    defaultConfig:
      tracing:
        zipkin:
          address: zipkin.istio-system:9411

Segurança automática com mTLS:

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: producao
spec:
  mtls:
    mode: STRICT

Com isso, todo o tráfego entre serviços é criptografado e autenticado. Políticas de autorização baseadas em identidade do serviço:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: pagamentos-policy
spec:
  selector:
    matchLabels:
      app: pagamentos
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/producao/sa/pedidos-sa"]
    to:
    - operation:
        methods: ["POST"]
        paths: ["/api/pagamentos"]

6. Estratégias de Implantação e Gerenciamento em Produção

Para gerenciar o mesh em produção, a abordagem GitOps é recomendada:

# Exemplo de Application ArgoCD para o mesh
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: istio-control-plane
spec:
  destination:
    namespace: istio-system
    server: https://kubernetes.default.svc
  project: default
  source:
    repoURL: https://github.com/empresa/infra-gitops
    path: clusters/producao/istio
    targetRevision: HEAD
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Atualizações graduais do plano de controle: Istio permite upgrade canary do plano de controle, onde uma versão nova do Istiod é implantada ao lado da antiga, com migração gradual dos proxies.

Monitoramento de custos: cada sidecar consome ~50MB de RAM e ~0.5 vCPU por Pod. Em clusters com milhares de Pods, o overhead pode chegar a dezenas de vCPUs. É essencial monitorar com ferramentas como Kiali e Grafana.

7. Casos de Uso Avançados e Considerações Finais

Multi-cluster mesh: conecta serviços em diferentes clusters Kubernetes através de gateways dedicados, permitindo failover geográfico e isolamento de falhas.

Integração com gateways de API: o Istio Ingress Gateway pode atuar como borda externa, combinando roteamento de API com políticas do mesh.

Quando evitar service mesh:
- Sistemas com menos de 10 microsserviços
- Cenários de latência ultra-baixa (sub-milissegundo) onde o overhead do proxy (1-3ms) é significativo
- Equipes pequenas sem capacidade operacional para gerenciar a complexidade adicional

O service mesh não é uma bala de prata, mas para organizações que operam dezenas ou centenas de microsserviços em Kubernetes, ele oferece o nível de controle, segurança e observabilidade que o Kubernetes nativo não consegue entregar sozinho.

Referências