Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

02 - Ambassador Pattern (Proxy sidecar)

#ambassador#kubernetes#proxy#resiliencia#sidecar
video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

Ambassador Pattern (Proxy sidecar)

O Ambassador Pattern coloca um processo acompanhante ao lado de cada instância de aplicação, responsável por intermediar toda a comunicação de rede dela com o mundo externo. Em vez de cada serviço implementar retry, timeout, TLS, coleta de métricas e log de requisições, essas responsabilidades cruzam para um proxy co-localizado que a aplicação sequer precisa conhecer, pois ele escuta em localhost e repassa o tráfego. O nome vem do papel de embaixador: o proxy representa a aplicação perante a rede e traduz as políticas de infraestrutura em comportamento de conexão. O padrão nasceu da constatação de que implementações de resiliência em bibliotecas de cliente se multiplicam por linguagem, por versão e por time, e nunca ficam consistentes. Em produção, ele é a base técnica do sidecar em Kubernetes e a unidade de construção do service mesh. Dominar o padrão é entender por que plataformas modernas movem cada vez mais lógica de rede para fora do código de negócio.

Conceito

O ambassador é um processo auxiliar que vive no mesmo host ou no mesmo pod da aplicação e atua como intermediário de rede em uma direção específica. Um ambassador de saída recebe as conexões que a aplicação faz para serviços externos e as encaminha aplicando políticas; um ambassador de entrada recebe conexões de clientes e as entrega à aplicação com as mesmas garantias. A aplicação fala com o ambassador em protocolo simples, geralmente HTTP ou TCP plano, e o ambassador fala com o mundo em protocolo rico, com mTLS, retries e telemetria.

A co-localização é o detalhe que define o padrão. Como o ambassador rota por localhost ou por interface local, a latência de rede adicional é mínima e a falha do nó derruba aplicação e proxy juntos, o que simplifica a semântica de vida dos dois. No Kubernetes, essa co-localização materializa-se no pod: múltiplos contêineres compartilham namespaces de rede e volumes, e o contêiner acompanhante recebe o nome de sidecar.

  • Sidecar de saída (outbound): intercepta chamadas da aplicação a outros serviços e a APIs externas, aplicando resiliência e segurança.
  • Sidecar de entrada (inbound): termina TLS, valida autenticação e expõe métricas do tráfego que chega à aplicação.
  • Ambassador de serviço: variação que roda como deployment compartilhado por vários pods de um nó, trocando densidade por isolamento.

O problema que resolve

Resiliência de rede escrita dentro da aplicação apodrece de três formas. Primeiro, por fragmentação: cada linguagem tem sua biblioteca, cada time sua versão, e a política de retry que vale para o serviço Java não existe no serviço Python legado. Segundo, por acoplamento: mudar a política exige novo build e novo deploy da aplicação, o que transforma ajuste operacional em projeto de desenvolvimento. Terceiro, por omissão: serviços esquecidos nunca ganham retry nem TLS, e descobrem isso em produção, durante um incidente.

O ambassador centraliza essas preocupações em um componente operado pela equipe de plataforma, com configuração versionada e aplicação uniforme. O desenvolvedor de negócio passa a escrever apenas lógica de domínio e confia que toda saída de rede passará pelo mesmo funil de políticas. A diferença aparece com clareza em eventos de failover: quando um banco muda de endpoint, um ambassador recarrega a nova resolução sem que nenhuma aplicação seja recompilada ou reiniciada.

Funcionamento interno

O ciclo de uma chamada com sidecar de saída tem quatro estágios. A aplicação abre conexão para um endereço local de aparência comum, como localhost:15001. O sidecar recebe a conexão e consulta a configuração, que define destino real, política de retry, timeout por rota e política de TLS. O sidecar aplica as políticas na sequência correta, resolvendo DNS, negociando mTLS e escolhendo um endpoint saudável do pool. Por fim, ele registra a observabilidade da requisição, com duração, bytes, códigos e rótulos de destino, e encaminha a resposta de volta à aplicação.

A interceptação em Kubernetes normalmente usa iptables ou eBPF para redirecionar tráfego transparentemente, o que explica por que a aplicação não precisa de mudança nenhuma. Em ambientes sem mesh, o padrão também funciona de forma explícita: a aplicação aponta para um endereço local fixo e o ambassador resolve o destino, como um proxy sidecar para um banco gerenciado que centraliza conexão, credencial e controle de falha.

# Pod Kubernetes com sidecar ambassador para chamadas a serviço externo
apiVersion: v1
kind: Pod
metadata:
  name: pedidos-api
  labels:
    app: pedidos
spec:
  containers:
    - name: app                        # aplicação de negócio, sem lógica de rede
      image: registry/pedidos:2.4.1
      env:
        - name: PAGAMENTOS_ENDPOINT    # aponta para o localhost do sidecar
          value: "http://localhost:15001"
    - name: ambassador                 # proxy acompanhante com políticas
      image: envoyproxy/envoy:v1.30.0
      ports:
        - containerPort: 15001
      volumeMounts:
        - name: envoy-config           # configuração declarativa de políticas
          mountPath: /etc/envoy
  volumes:
    - name: envoy-config
      configMap:
        name: ambassador-pedidos

A política de resiliência vive no configMap do sidecar e muda sem rebuild da aplicação:

# Trecho de configuração do ambassador: retry e timeout fora do código
route:
  cluster: pagamentos_cluster
  retry_policy:
    retry_on: "5xx,connect-failure,reset"   # tenta de novo nesses cenários
    num_retries: 3                            # no máximo três tentativas
    per_try_timeout: 2s                       # cada tentativa tem teto próprio
  timeout: 8s                                 # teto total da requisição

Aplicação prática: ambassador para banco de dados

A variação mais útil em produção é o ambassador na frente de um banco de dados gerenciado, por exemplo um contêiner de pgbouncer ou ProxySQL rodando como sidecar de cada pod da aplicação. O sidecar concentra o pool de conexões por instância, o que protege o banco do erro clássico de cada réplica da aplicação abrir seu próprio pool e multiplicar conexões até esgotar o limite do servidor. Em failover do banco, o ambassador detecta a troca de endpoint e reconecta ao novo primário, e a aplicação apenas espera a chamada seguinte, sem código de descoberta de topologia.

O mesmo desenho serve para caches e filas. Um sidecar na frente do Redis pode centralizar sharding por chave, autenticação por ACL e coleta de comandos lentos, sem que cada cliente da aplicação implemente a mesma lógica. A regra é a mesma do padrão geral: tudo que é política de rede, e não decisão de negócio, pertence ao acompanhante.

# Sidecar de pool de conexões na frente do banco gerenciado
containers:
  - name: app
    image: registry/pedidos:2.4.1
    env:
      - name: DATABASE_URL                # aplicação fala só com localhost
        value: "postgres://app@localhost:6432/pedidos"
  - name: pgbouncer-ambassador
    image: edoburu/pgbouncer:latest
    env:
      - name: DB_HOST                     # destino real resolvido pelo proxy
        value: "pedidos.cluster-xyz.rds.amazonaws.com"
      - name: POOL_MODE
        value: "transaction"              # pool transacional, máxima reutilização
      - name: MAX_CLIENT_CONN
        value: "200"                      # teto local que protege o banco

Ambassador versus biblioteca cliente

A alternativa clássica ao ambassador é encapsular resiliência em bibliotecas, como clientes HTTP com retry embutido ou drivers que fazem reconexão automática. As duas abordagens competem diretamente, e a escolha afeta linguagens suportadas, custo operacional e latência.

Critério Ambassador (sidecar) Biblioteca cliente
Consistência entre times Uniforme, uma configuração Variável por linguagem e versão
Mudança de política Reload do proxy, sem deploy Novo build e rollout completo
Custo de runtime CPU e memória extra por pod Dentro do processo da aplicação
Latência adicional Um salto local por chamada Praticamente nula
Depuração Rede observável como componente Misturada no stack da aplicação
Requisito de plataforma Orquestrador ou processo gerenciado Nenhum, só dependência no build

A regra prática de escolha é a escala da frota. Com poucos serviços e uma única linguagem, a biblioteca é mais simples e barata. Com dezenas de serviços, várias linguagens e times independentes, o custo de manter consistência por biblioteca supera o custo de recursos do sidecar, e o ambassador vence no ciclo completo de operação.

Service mesh como generalização

Um service mesh é, na essência, uma frota de ambassadors gerenciada centralmente. Cada pod recebe seu sidecar injetado automaticamente, e um plano de controle distribui configuração de roteamento, mTLS e telemetria para todos eles. O Istio com Envoy, o Linkerd e o AWS App Mesh são implementações desse desenho, e o próprio conceito de sidecar do Kubernetes foi popularizado por essa combinação.

A generalização adiciona três capacidades que um ambassador artesanal raramente oferece. A descoberta de serviço com health checking contínuo mantém o pool de endpoints sempre atualizado. A emissão e rotação de certificados mTLS por identidade de workload elimina gestão manual de credenciais. O controle de tráfego declarativo, com split por peso, mirroring e circuit breaking, transforma operações de release em mudança de configuração auditável. O custo é complexidade de plataforma, e a decisão de adotar mesh deve considerar se a frota realmente precisa dessas garantias.

A evolução recente do modelo ataca justamente o custo de densidade do sidecar. Projetos de ambient mesh e o modo sidecar-less do Istio movem as políticas para proxies por nó ou para captura em eBPF no kernel, reduzindo o número de processos por pod e a sobra de memória ociosa. A promessa é manter as garantias do padrão com menos recursos, e acompanhar essa evolução é relevante porque o custo por pod do sidecar clássico é a principal objeção técnica à adoção de mesh em frotas grandes.

Custos de recursos e latência

O sidecar não é gratuito e o preço aparece em três medidas. Em recursos, cada pod passa a hospedar um segundo contêiner que consome dezenas a centenas de megabytes de memória e fração de um vCPU ocioso, o que multiplica por toda a frota; em clusters de milhares de pods, o custo agregado de sidecars torna-se parte relevante da conta. Em latência, cada salto por localhost adiciona tipicamente menos de um milissegundo, mas chamadas em cadeia com muitos saltos acumulam o custo em cada hop, inclusive no caminho de resposta. Em operação, o sidecar entra no caminho crítico, e um proxy mal configurado ou esgotado derruba a aplicação saudável junto, o que exige monitorar o componente acompanhante com o mesmo rigor do negócio.

Erros comuns

  • Tráfego furando o sidecar: chamadas que não passam pela interceptação deixam de ter política e telemetria sem que ninguém perceba; audite a cobertura de mTLS por workload.
  • Sidecar sem limites de recurso: contêiner acompanhante sem requests e limits compete com a aplicação por CPU e memória no mesmo nó.
  • Retry sem budget: o ambassador reprocessa falhas e amplifica tempestades de erro no destino; combine retries com limites globais e circuit breaking.
  • Configuração divergente: sidecars editados à mão em pods específicos criam comportamento inconsistente; toda política deve nascer no repositório de plataforma.
  • Health check errado: sonda apontando para o sidecar em vez da aplicação, o que mantém pods doentes recebendo tráfego ou derruba pods saudáveis.

Boas práticas

Versione toda configuração de ambassador em infraestrutura como código e trate mudança de política como mudança de produção, com revisão e rollout gradual. Padronize timeouts por classe de dependência, mais agressivos para chamadas síncronas de usuário e mais folgados para processamento em lote, e documente a decisão. Monitore o próprio sidecar com métricas dedicadas, incluindo taxa de retries, tempo de resolução DNS e uso de memória do proxy. Em migrar para service mesh, comece com mTLS em modo permissivo e avance para estrito depois de validar cobertura, pois o caminho reverso tende a gerar incidentes de conectividade difíceis de diagnosticar.