TL;DR — Resumen Rápido
Domina HashiCorp Consul para service discovery y service mesh: arquitectura, health checks, ACLs, proxies Envoy y federación multi-datacenter.
HashiCorp Consul es una plataforma de red de servicios distribuida y de alta disponibilidad que resuelve uno de los problemas más difíciles de los microservicios: ¿cómo se encuentran los servicios entre sí, verifican que el otro está sano y se comunican de forma segura en una infraestructura dinámica donde las IPs cambian constantemente? Consul responde las tres preguntas mediante un plano de control unificado que combina service discovery, health checking, almacén KV y un service mesh completo con aplicación de TLS mutuo. Esta guía cubre todas las capacidades principales de Consul, desde la configuración de un clúster de tres nodos hasta los proxies sidecar Envoy y la federación multi-datacenter.
Prerrequisitos
Antes de continuar, asegúrate de tener disponible lo siguiente:
- Host Linux o macOS — Consul funciona en cualquier sistema tipo Unix y Windows; los ejemplos usan Linux.
- Docker 24+ — para el ejemplo de producción con Docker Compose al final de esta guía.
- curl y dig — para probar las respuestas DNS y de la API HTTP.
- Comprensión básica de microservicios — familiaridad con conceptos como balanceo de carga, health checks y TLS.
- Binario Consul 1.17+ — instala vía el repositorio APT/YUM de HashiCorp o descarga desde
releases.hashicorp.com.
Instalación en 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
Arquitectura de Consul
Agentes: Servidores vs Clientes
Cada nodo en un clúster Consul ejecuta un agente Consul en uno de dos modos:
Los agentes servidor forman el plano de control. Participan en el algoritmo de consenso Raft para elegir un líder, almacenan el estado autorizado del clúster (servicios, resultados de health checks, datos KV, políticas ACL) y replican ese estado. Debes ejecutar un número impar de servidores: 3 servidores toleran 1 fallo; 5 servidores toleran 2 fallos.
Los agentes cliente se ejecutan en cada nodo no servidor (tus hosts de aplicación). Registran servicios y health checks locales, reenvían consultas a los servidores y participan en la red gossip. Los clientes son livianos — no almacenan estado del clúster.
Protocolo Gossip (Serf)
Consul usa Serf, una implementación del protocolo gossip SWIM, para la membresía del clúster y la detección de fallos. Todos los agentes participan en dos pools de gossip:
- Pool gossip LAN — agentes dentro del mismo datacenter. Usado para el descubrimiento de miembros, propagación de estado de salud y difusión de eventos.
- Pool gossip WAN — servidores entre datacenters. Habilita la federación multi-datacenter.
Consenso Raft
Raft se usa solo entre servidores Consul para la consistencia fuerte del estado del clúster. El líder acepta todas las operaciones de escritura y replica las entradas de log en los seguidores antes de confirmar.
Modelo de Datacenter
Un datacenter Consul es una unidad aislada: un conjunto de servidores que comparten un pool gossip LAN. Múltiples datacenters se comunican vía gossip WAN o mesh gateways.
Métodos de Instalación
Instalación del Binario
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
Configuración del Clúster de Servidores
Crea /etc/consul.d/consul.hcl en cada nodo 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 = "CLAVE_GOSSIP_BASE64_AQUI"
ui_config {
enabled = true
}
client_addr = "0.0.0.0"
bind_addr = "{{ GetPrivateIP }}"
advertise_addr = "{{ GetPrivateIP }}"
Genera la clave gossip una vez y úsala en todos los nodos:
consul keygen
# Salida: j5Y3fIFjQKs2b9s9rG2ufA==
Inicia el clúster:
sudo systemctl enable consul && sudo systemctl start consul
consul members
consul operator raft list-peers
Registro de Servicios
Archivos de Definición de Servicio
Crea un archivo JSON en /etc/consul.d/ en el 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 vía 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
La API de agente (/v1/agent/service/*) gestiona los servicios registrados en el agente local. La API de catálogo (/v1/catalog/service/*) consulta el registro global agregado de todos los agentes:
# Vista del agente — solo nodo local
curl http://localhost:8500/v1/agent/services | jq .
# Vista del catálogo — todos los nodos
curl http://localhost:8500/v1/catalog/service/web | jq '[.[] | {nodo: .Node, dir: .ServiceAddress, puerto: .ServicePort}]'
Health Checks
Consul soporta seis tipos de health checks, todos con parámetros interval, timeout y deregister_critical_service_after.
HTTP — Consul realiza un GET HTTP; 2xx = passing, 429 = warning, cualquier otro = critical.
TCP — Abre una conexión TCP al host:puerto especificado.
Script — Ejecuta un comando de shell; código de salida 0 = passing, 1 = warning, otro = critical.
TTL — La aplicación misma debe llamar a la API de Consul para actualizar su estado de salud.
gRPC — Para servicios que implementan el protocolo de salud gRPC.
Ejemplo de check TTL:
# Reportar passing
curl -X PUT http://localhost:8500/v1/agent/check/pass/service:worker-01 \
-d "Procesando cola normalmente"
Establece siempre deregister_critical_service_after para eliminar automáticamente servicios con fallos continuos:
"deregister_critical_service_after": "90s"
Interfaz DNS
Consul ejecuta un servidor DNS en el puerto 8600. Los servicios se resuelven en <servicio>.service.<datacenter>.consul.
# Resolver todas las instancias sanas de "web"
dig @127.0.0.1 -p 8600 web.service.consul A
# Con registro SRV (incluye puerto)
dig @127.0.0.1 -p 8600 web.service.consul SRV
# Por etiqueta
dig @127.0.0.1 -p 8600 primary.web.service.consul A
Reenvío DNS con systemd-resolved
# /etc/systemd/resolved.conf.d/consul.conf
[Resolve]
DNS=127.0.0.1:8600
Domains=~consul
sudo systemctl restart systemd-resolved
# Ahora puedes usar: curl http://web.service.consul:8080/
Prepared Queries con 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
Consul Connect usa Envoy como proxy sidecar y emite certificados TLS de corta duración para TLS mutuo entre servicios.
Registro del 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 &
Intenciones
# Permitir que web llegue a api
consul intention create web api
# Denegar una ruta específica
consul intention create -deny payments logging
# Listar todas las intenciones
consul intention list
Almacén KV
# Escribir un valor
consul kv put config/app/log_level info
# Leer un valor
consul kv get config/app/log_level
# Listar claves bajo un prefijo
consul kv list config/app/
# Eliminar un árbol
consul kv delete -recurse config/app/
consul-template
# Instalar
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/
Plantilla 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
# Habilitar ACLs en consul.hcl
cat >> /etc/consul.d/consul.hcl <<EOF
acl {
enabled = true
default_policy = "deny"
enable_token_persistence = true
}
EOF
# Inicializar — hazlo una sola vez y guarda la salida
consul acl bootstrap
# SecretID: db14c... ← este es tu token bootstrap (root)
export CONSUL_HTTP_TOKEN="db14c..."
# Crear una política
consul acl policy create \
-name "lectura-servicio-web" \
-rules 'service "web" { policy = "read" }
node_prefix "" { policy = "read" }'
# Crear un token con esta política
consul acl token create \
-description "Token lectura servicio web" \
-policy-name "lectura-servicio-web"
IU de Consul
La IU web de Consul está disponible en http://localhost:8500/ui cuando ui_config { enabled = true } está configurado. Secciones principales:
- Servicios — todos los servicios registrados con estado de salud, etiquetas y conteo de instancias.
- Nodos — todos los agentes con su estado de salud y servicios registrados.
- Key/Value — navegador del almacén KV con soporte para crear, editar y eliminar.
- Intenciones — visualiza y gestiona las reglas de autorización entre servicios.
- Controles de acceso — gestiona tokens, políticas y roles (visible solo cuando los ACLs están habilitados).
Federación Multi-Datacenter
Gossip WAN
# En los servidores de dc2, unirse al pool WAN de dc1
consul join -wan 10.0.1.11
# Consultar el servicio web en 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
Los mesh gateways son el enfoque moderno — hacen proxy del tráfico entre datacenters sin exponer los servicios internos a la WAN:
consul connect envoy -gateway=mesh -register -address $(hostname -I | awk '{print $1}'):8443
Comparación: Consul vs Alternativas
| Característica | Consul | etcd | ZooKeeper | Eureka | Istio | Linkerd |
|---|---|---|---|---|---|---|
| Service Discovery | DNS + API HTTP | Solo API | Solo API | API HTTP | Vía Kubernetes | Vía Kubernetes |
| Health Checks | Integrado (6 tipos) | Sin native | Sin native | Heartbeat cliente | Probes Kubernetes | Probes Kubernetes |
| Service Mesh | Sí (Connect) | No | No | No | Sí (Envoy) | Sí (proxy2) |
| Almacén KV | Sí | Sí (uso primario) | Sí | No | No | No |
| Sistema ACL | Sí (rico) | Básico | SASL/ACL | No | RBAC | RBAC |
| Multi-datacenter | Nativo | No | No | Peers replicados | No | No |
| Consenso | Raft | Raft | ZAB | Eventual | N/A | N/A |
| Sin Kubernetes | Sí | Sí | Sí | Sí | No | No |
Despliegue en Producción con 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
Problemas Comunes y Casos Límite
bootstrap_expectinconsistente — todos los servidores deben tener el mismo valor; una discrepancia impide la formación del clúster.- Rotación de clave gossip — usa
consul keyringpara rotar; todos los nodos deben completar la rotación antes de eliminar la clave anterior. - Distribución de tokens ACL — evita tokens en archivos de configuración; usa el motor de secretos Consul de Vault o Kubernetes secrets.
- Compatibilidad de versiones Envoy — siempre alinea la versión de Envoy con la matriz de compatibilidad de Consul; una versión no soportada causa fallos silenciosos en el proxy.
- Timeouts en health checks — establece
timeoutmenor queintervalpara evitar ejecuciones de checks superpuestas.
Resumen
- Tres o cinco servidores con consenso Raft forman el plano de control; usa un número impar para tolerancia de quórum.
- Gossip (Serf) maneja la membresía del clúster y la detección de fallos a escala O(log N) en LAN y WAN.
- Las definiciones de servicio registran servicios con health checks ricos que eliminan automáticamente instancias no saludables del DNS.
- La interfaz DNS en el puerto 8600 permite resolver
servicio.service.consulsin cambios de código. - Consul Connect agrega mTLS entre servicios vía sidecars Envoy; las intenciones aplican autorización sin tocar el código de la aplicación.
- Las prepared queries proporcionan failover a nivel DNS entre datacenters para alta disponibilidad.
- El almacén KV combinado con consul-template permite gestión dinámica de configuración.
- Los ACLs con
default_policy = denybloquean el clúster; usa auth methods para emisión de tokens sin secretos.