TL;DR — Resumo Rápido

Domine HashiCorp Consul para service discovery e service mesh: arquitetura, health checks, ACLs, proxies Envoy sidecar e federação multi-datacenter.

HashiCorp Consul é uma plataforma de rede de serviços distribuída e de alta disponibilidade que resolve um dos problemas mais difíceis dos microsserviços: como os serviços se encontram, verificam a saúde uns dos outros e se comunicam com segurança em uma infraestrutura dinâmica onde endereços IP mudam constantemente? O Consul responde as três perguntas através de um plano de controle unificado que combina service discovery, health checking, armazenamento KV e um service mesh completo com aplicação de TLS mútuo. Este guia cobre todas as principais capacidades do Consul, desde a configuração de um cluster de três nós até proxies sidecar Envoy e federação multi-datacenter.

Pré-requisitos

Antes de prosseguir, certifique-se de que os seguintes recursos estejam disponíveis:

  • Host Linux ou macOS — o Consul funciona em qualquer sistema tipo Unix e Windows; os exemplos usam Linux.
  • Docker 24+ — para o exemplo de produção com Docker Compose ao final deste guia.
  • curl e dig — para testar respostas DNS e da API HTTP.
  • Compreensão básica de microsserviços — familiaridade com conceitos como balanceamento de carga, health checks e TLS.
  • Binário Consul 1.17+ — instale via repositório APT/YUM da HashiCorp ou baixe em releases.hashicorp.com.

Instalação no Ubuntu/Debian:

wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install consul
consul version
# Consul v1.20.2

Arquitetura do Consul

Agentes: Servidores vs Clientes

Cada nó em um cluster Consul executa um agente Consul em um de dois modos:

Os agentes servidor formam o plano de controle. Participam no algoritmo de consenso Raft para eleger um líder, armazenam o estado autorizado do cluster e replicam esse estado. Use sempre um número ímpar: 3 servidores toleram 1 falha; 5 servidores toleram 2 falhas.

Os agentes cliente executam em cada nó não servidor. Registram serviços e health checks locais, encaminham consultas aos servidores e participam na rede gossip. Clientes são leves — não armazenam estado do cluster.

Protocolo Gossip (Serf)

O Consul usa Serf, uma implementação do protocolo gossip SWIM, para associação ao cluster e detecção de falhas. Todos os agentes participam em dois pools gossip:

  • Pool gossip LAN — agentes dentro do mesmo datacenter.
  • Pool gossip WAN — servidores entre datacenters. Habilita a federação multi-datacenter.

Consenso Raft

O Raft é usado apenas entre servidores do Consul para consistência forte do estado do cluster. O líder aceita todas as operações de escrita e replica as entradas de log nos seguidores antes de confirmar.

Modelo de Datacenter

Um datacenter Consul é uma unidade isolada: um conjunto de servidores compartilhando um pool gossip LAN. Múltiplos datacenters se comunicam via gossip WAN ou mesh gateways.

Métodos de Instalação

Instalação do Binário

CONSUL_VERSION="1.20.2"
wget "https://releases.hashicorp.com/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_linux_amd64.zip"
unzip consul_${CONSUL_VERSION}_linux_amd64.zip
sudo install consul /usr/local/bin/
consul version

Docker

docker run -d \
  --name consul-dev \
  -p 8500:8500 \
  -p 8600:8600/udp \
  hashicorp/consul:1.20 agent -dev -client=0.0.0.0

Helm Chart para Kubernetes

helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
helm install consul hashicorp/consul \
  --namespace consul \
  --create-namespace \
  --values consul-values.yaml

consul-values.yaml mínimo:

global:
  name: consul
  datacenter: dc1
  tls:
    enabled: true
  acls:
    manageSystemACLs: true
server:
  replicas: 3
  bootstrapExpect: 3
connectInject:
  enabled: true

Configuração do Cluster de Servidores

Crie /etc/consul.d/consul.hcl em cada nó servidor:

datacenter  = "dc1"
data_dir    = "/opt/consul"
log_level   = "INFO"
node_name   = "consul-server-01"
server      = true
bootstrap_expect = 3

retry_join = [
  "10.0.1.11",
  "10.0.1.12",
  "10.0.1.13"
]

encrypt = "CHAVE_GOSSIP_BASE64_AQUI"

ui_config {
  enabled = true
}
client_addr    = "0.0.0.0"
bind_addr      = "{{ GetPrivateIP }}"
advertise_addr = "{{ GetPrivateIP }}"

Gere a chave gossip uma vez e use em todos os nós:

consul keygen
# Saída: j5Y3fIFjQKs2b9s9rG2ufA==

Inicie o cluster:

sudo systemctl enable consul && sudo systemctl start consul
consul members
consul operator raft list-peers

Registro de Serviços

Arquivos de Definição de Serviço

Crie um arquivo JSON em /etc/consul.d/ no agente cliente:

{
  "service": {
    "id":   "web-01",
    "name": "web",
    "port": 8080,
    "tags": ["v2", "primary"],
    "check": {
      "http":     "http://localhost:8080/health",
      "interval": "10s",
      "timeout":  "3s",
      "deregister_critical_service_after": "90s"
    }
  }
}

Registro via API HTTP

curl -s -X PUT http://localhost:8500/v1/agent/service/register \
  -H "Content-Type: application/json" \
  -d '{
    "ID":   "api-01",
    "Name": "api",
    "Port": 3000,
    "Check": {
      "HTTP":     "http://localhost:3000/healthz",
      "Interval": "15s",
      "Timeout":  "5s"
    }
  }'

Catálogo vs Agente

A API do agente (/v1/agent/service/*) gerencia serviços registrados no agente local. A API do catálogo (/v1/catalog/service/*) consulta o registro global de todos os agentes:

curl http://localhost:8500/v1/agent/services | jq .
curl http://localhost:8500/v1/catalog/service/web | jq '[.[] | {no: .Node, end: .ServiceAddress, porta: .ServicePort}]'

Health Checks

O Consul suporta seis tipos de health checks, todos com parâmetros interval, timeout e deregister_critical_service_after.

HTTP — O Consul executa um GET HTTP; 2xx = passing, 429 = warning, qualquer outro = critical.

TCP — Abre uma conexão TCP ao host:porta especificado.

Script — Executa um comando shell; código de saída 0 = passing, 1 = warning, outro = critical.

TTL — A própria aplicação deve chamar a API do Consul para atualizar seu estado de saúde.

gRPC — Para serviços que implementam o protocolo de saúde gRPC.

Exemplo de check TTL:

curl -X PUT http://localhost:8500/v1/agent/check/pass/service:worker-01 \
  -d "Processando fila normalmente"

Sempre defina deregister_critical_service_after para remover automaticamente serviços com falhas contínuas:

"deregister_critical_service_after": "90s"

Interface DNS

O Consul executa um servidor DNS na porta 8600. Os serviços são resolvidos em <serviço>.service.<datacenter>.consul.

# Resolver todas as instâncias saudáveis de "web"
dig @127.0.0.1 -p 8600 web.service.consul A

# Com registro SRV (inclui porta)
dig @127.0.0.1 -p 8600 web.service.consul SRV

# Por tag
dig @127.0.0.1 -p 8600 primary.web.service.consul A

Encaminhamento DNS com systemd-resolved

# /etc/systemd/resolved.conf.d/consul.conf
[Resolve]
DNS=127.0.0.1:8600
Domains=~consul
sudo systemctl restart systemd-resolved
# Agora você pode usar: curl http://web.service.consul:8080/

Prepared Queries com Failover

curl -X POST http://localhost:8500/v1/query \
  -d '{
    "Name": "web",
    "Service": {
      "Service":     "web",
      "OnlyPassing": true,
      "Failover": {
        "NearestN":    2,
        "Datacenters": ["dc2", "dc3"]
      }
    }
  }'

dig @127.0.0.1 -p 8600 web.query.consul A

Service Mesh / Connect

O Consul Connect usa Envoy como proxy sidecar e emite certificados TLS de curta duração para TLS mútuo entre serviços.

Registro do Sidecar

{
  "service": {
    "name": "web",
    "port": 8080,
    "connect": {
      "sidecar_service": {
        "port": 21000,
        "proxy": {
          "upstreams": [
            {
              "destination_name": "api",
              "local_bind_port":  9191
            }
          ]
        }
      }
    }
  }
}
consul connect envoy -sidecar-for web &

Intenções

# Permitir que web alcance api
consul intention create web api

# Negar uma rota específica
consul intention create -deny payments logging

# Listar todas as intenções
consul intention list

Armazenamento KV

# Escrever um valor
consul kv put config/app/log_level info

# Ler um valor
consul kv get config/app/log_level

# Listar chaves sob um prefixo
consul kv list config/app/

# Excluir uma árvore
consul kv delete -recurse config/app/

consul-template

wget https://releases.hashicorp.com/consul-template/0.39.0/consul-template_0.39.0_linux_amd64.zip
unzip consul-template_0.39.0_linux_amd64.zip
sudo install consul-template /usr/local/bin/

Template nginx.conf.ctmpl:

upstream web_backend {
  {{ range service "web" }}
  server {{ .Address }}:{{ .Port }};
  {{ end }}
}
consul-template \
  -template "nginx.conf.ctmpl:/etc/nginx/conf.d/web.conf:nginx -s reload" \
  -once

Sistema ACL

cat >> /etc/consul.d/consul.hcl <<EOF
acl {
  enabled                  = true
  default_policy           = "deny"
  enable_token_persistence = true
}
EOF

consul acl bootstrap
# SecretID: db14c...   ← este é seu token bootstrap (root)

export CONSUL_HTTP_TOKEN="db14c..."

consul acl policy create \
  -name "leitura-servico-web" \
  -rules 'service "web" { policy = "read" }
node_prefix "" { policy = "read" }'

consul acl token create \
  -description "Token leitura serviço web" \
  -policy-name "leitura-servico-web"

Interface de Usuário do Consul

A UI web do Consul está disponível em http://localhost:8500/ui quando ui_config { enabled = true } está configurado. Seções principais:

  • Serviços — todos os serviços registrados com estado de saúde, tags e contagem de instâncias.
  • Nós — todos os agentes com estado de saúde e serviços registrados.
  • Key/Value — navegador do armazenamento KV com suporte para criar, editar e excluir.
  • Intenções — visualize e gerencie regras de autorização entre serviços.
  • Controles de Acesso — gerencie tokens, políticas e funções.

Federação Multi-Datacenter

Gossip WAN

# Nos servidores do dc2, juntar ao pool WAN do dc1
consul join -wan 10.0.1.11

# Consultar o serviço web no dc2
dig @127.0.0.1 -p 8600 web.service.dc2.consul A
curl "http://localhost:8500/v1/catalog/service/web?dc=dc2"

Mesh Gateways

Mesh gateways são a abordagem moderna — fazem proxy do tráfego entre datacenters sem expor serviços internos à WAN:

consul connect envoy -gateway=mesh -register -address $(hostname -I | awk '{print $1}'):8443

Comparação: Consul vs Alternativas

Recurso Consul etcd ZooKeeper Eureka Istio Linkerd
Service Discovery DNS + API HTTP Apenas API Apenas API API HTTP Via Kubernetes Via Kubernetes
Health Checks Integrado (6 tipos) Nenhum nativo Nenhum nativo Heartbeat cliente Probes Kubernetes Probes Kubernetes
Service Mesh Sim (Connect) Não Não Não Sim (Envoy) Sim (proxy2)
Armazenamento KV Sim Sim (uso primário) Sim Não Não Não
Sistema ACL Sim (rico) Básico SASL/ACL Não RBAC RBAC
Multi-datacenter Nativo Não Não Peers replicados Não Não
Sem Kubernetes Sim Sim Sim Sim Não Não

Implantação em Produção com Docker Compose

name: consul-cluster

services:
  consul-server-1:
    image: hashicorp/consul:1.20
    command: >
      agent -server
      -node=server-1
      -bootstrap-expect=3
      -datacenter=dc1
      -data-dir=/consul/data
      -bind=0.0.0.0
      -client=0.0.0.0
      -retry-join=consul-server-2
      -retry-join=consul-server-3
      -ui
    volumes:
      - consul-server-1-data:/consul/data
      - ./consul-config:/consul/config:ro
    ports:
      - "8500:8500"
      - "8600:8600/udp"
    networks:
      - consul-net
    restart: unless-stopped

  consul-server-2:
    image: hashicorp/consul:1.20
    command: >
      agent -server
      -node=server-2
      -bootstrap-expect=3
      -datacenter=dc1
      -data-dir=/consul/data
      -bind=0.0.0.0
      -client=0.0.0.0
      -retry-join=consul-server-1
      -retry-join=consul-server-3
    volumes:
      - consul-server-2-data:/consul/data
      - ./consul-config:/consul/config:ro
    networks:
      - consul-net
    restart: unless-stopped

  consul-server-3:
    image: hashicorp/consul:1.20
    command: >
      agent -server
      -node=server-3
      -bootstrap-expect=3
      -datacenter=dc1
      -data-dir=/consul/data
      -bind=0.0.0.0
      -client=0.0.0.0
      -retry-join=consul-server-1
      -retry-join=consul-server-2
    volumes:
      - consul-server-3-data:/consul/data
      - ./consul-config:/consul/config:ro
    networks:
      - consul-net
    restart: unless-stopped

  consul-client:
    image: hashicorp/consul:1.20
    command: >
      agent
      -node=client-1
      -datacenter=dc1
      -data-dir=/consul/data
      -bind=0.0.0.0
      -client=0.0.0.0
      -retry-join=consul-server-1
    volumes:
      - consul-client-data:/consul/data
      - ./consul-config:/consul/config:ro
      - ./services:/consul/services:ro
    networks:
      - consul-net
    restart: unless-stopped

volumes:
  consul-server-1-data:
  consul-server-2-data:
  consul-server-3-data:
  consul-client-data:

networks:
  consul-net:
    driver: bridge
GOSSIP_KEY=$(docker run --rm hashicorp/consul:1.20 keygen)
echo "encrypt = \"${GOSSIP_KEY}\"" > consul-config/encryption.hcl
docker compose up -d
sleep 5
docker compose exec consul-server-1 consul members

Armadilhas e Casos Especiais

  • bootstrap_expect inconsistente — todos os servidores devem ter o mesmo valor; uma discrepância impede a formação do cluster.
  • Rotação de chave gossip — use consul keyring para rotacionar; todos os nós devem completar a rotação antes de remover a chave antiga.
  • Distribuição de tokens ACL — evite tokens em arquivos de configuração; use o motor de segredos Consul do Vault ou secrets do Kubernetes.
  • Compatibilidade de versão do Envoy — sempre alinhe a versão do Envoy com a matriz de compatibilidade do Consul.
  • Timeouts de health checks — defina timeout menor que interval para evitar execuções de checks sobrepostas.

Resumo

  • Três ou cinco servidores com consenso Raft formam o plano de controle; use número ímpar para tolerância de quorum.
  • Gossip (Serf) lida com associação ao cluster e detecção de falhas em escala O(log N) em LAN e WAN.
  • Definições de serviço registram serviços com health checks ricos que removem automaticamente instâncias não saudáveis do DNS.
  • A interface DNS na porta 8600 permite resolver serviço.service.consul sem alterações de código.
  • Consul Connect adiciona mTLS entre serviços via sidecars Envoy; intenções aplicam autorização sem tocar no código da aplicação.
  • Prepared queries fornecem failover em nível DNS entre datacenters para alta disponibilidade.
  • O armazenamento KV combinado com consul-template permite gerenciamento dinâmico de configuração.
  • ACLs com default_policy = deny bloqueiam o cluster; use auth methods para emissão de tokens sem segredos.

Artigos Relacionados