Instalación de Consul y Descubrimiento de Servicios

HashiCorp Consul es una herramienta de descubrimiento de servicios, comprobación de salud y almacenamiento de clave-valor distribuido que permite a los servicios encontrarse y comunicarse de forma dinámica sin configuración manual. Su integración con DNS nativo facilita la adopción en entornos existentes, y su soporte para service mesh lo convierte en una pieza clave de infraestructuras microservicios. Esta guía cubre la instalación de un clúster Consul en Linux, registro de servicios, interfaz DNS y almacén KV.

Requisitos Previos

  • 3 o más servidores Linux para clúster de producción (Ubuntu 22.04, Debian 12, CentOS 9 o Rocky 9)
  • Mínimo 2 GB de RAM por nodo servidor
  • Conectividad de red entre todos los nodos en los puertos 8300, 8301, 8302, 8500, 8600
  • NTP sincronizado en todos los nodos

Instalación de Consul

# Añadir el repositorio oficial de HashiCorp (Ubuntu/Debian)
wget -O- https://apt.releases.hashicorp.com/gpg | \
  gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
  https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
  tee /etc/apt/sources.list.d/hashicorp.list

apt-get update && apt-get install -y consul

# CentOS/Rocky Linux
dnf install -y dnf-plugins-core
dnf config-manager --add-repo \
  https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
dnf install -y consul

# Verificar la instalación
consul version

# Crear usuario de sistema para Consul
useradd -r -d /var/lib/consul -s /bin/false consul
mkdir -p /var/lib/consul /etc/consul.d
chown consul:consul /var/lib/consul /etc/consul.d

Configuración del Clúster

Genera el token de encriptación para las comunicaciones del clúster:

# Generar clave de encriptación (ejecutar UNA vez, usar en todos los nodos)
consul keygen
# Guarda la salida: ej. pUqJrVyVRj5jsiYEkM/tFQYfWyJIv4s3XkvDwy7Cu5s=

Configuración para los nodos servidor (ejecutar en los 3 servidores con IPs adecuadas):

# En el servidor 1 (consul-server-01, IP: 10.0.1.10)
cat > /etc/consul.d/consul.hcl << 'EOF'
# Identificador del datacenter
datacenter = "dc1"

# Directorio de datos persistentes
data_dir = "/var/lib/consul"

# Dirección de binding (escuchar en todas las interfaces)
bind_addr = "10.0.1.10"
client_addr = "0.0.0.0"

# Este nodo actúa como servidor del clúster
server = true

# Número de servidores para formar quórum (para 3 servidores usar 3)
bootstrap_expect = 3

# Claves de encriptación (usar la generada con consul keygen)
encrypt = "pUqJrVyVRj5jsiYEkM/tFQYfWyJIv4s3XkvDwy7Cu5s="

# IPs de los otros nodos servidor para bootstrap del clúster
retry_join = ["10.0.1.10", "10.0.1.11", "10.0.1.12"]

# Habilitar la UI web
ui_config {
    enabled = true
}

# Configuración de logs
log_level = "INFO"
log_file = "/var/log/consul/consul.log"

# Habilitar comprobaciones de salud mediante scripts
enable_script_checks = false
enable_local_script_checks = true
EOF

# Crear directorio de logs
mkdir -p /var/log/consul
chown consul:consul /var/log/consul

Crea el servicio systemd:

cat > /etc/systemd/system/consul.service << 'EOF'
[Unit]
Description=HashiCorp Consul - Service Discovery
Documentation=https://www.consul.io/
Requires=network-online.target
After=network-online.target
ConditionFileNotEmpty=/etc/consul.d/consul.hcl

[Service]
Type=notify
User=consul
Group=consul
ExecStart=/usr/bin/consul agent -config-dir=/etc/consul.d/
ExecReload=/bin/kill --signal HUP $MAINPID
KillMode=process
KillSignal=SIGTERM
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now consul

Verifica el estado del clúster:

# Ver miembros del clúster
consul members

# Ver el líder actual
consul operator raft list-peers

# Estado general del clúster
consul info

Registro de Servicios

Registra servicios mediante archivos de definición:

# Crear definición de servicio para una aplicación web
cat > /etc/consul.d/webapp.hcl << 'EOF'
service {
    id      = "webapp-01"
    name    = "webapp"
    tags    = ["production", "v2"]
    port    = 8080
    address = "10.0.2.10"

    check {
        id       = "webapp-http"
        name     = "HTTP health check"
        http     = "http://10.0.2.10:8080/health"
        interval = "10s"
        timeout  = "3s"
    }
}
EOF

# Recargar la configuración sin reiniciar
consul reload

# Verificar que el servicio está registrado
consul catalog services
consul catalog nodes -service=webapp

También puedes registrar servicios via API HTTP:

# Registro via API REST
curl -X PUT http://localhost:8500/v1/agent/service/register \
  -H "Content-Type: application/json" \
  -d '{
    "ID": "redis-01",
    "Name": "redis",
    "Tags": ["cache"],
    "Address": "10.0.2.20",
    "Port": 6379,
    "Check": {
      "TCP": "10.0.2.20:6379",
      "Interval": "10s"
    }
  }'

Interfaz DNS

Consul expone una interfaz DNS en el puerto 8600 para resolución de servicios:

# Consultar un servicio via DNS (formato: <servicio>.service.consul)
dig @127.0.0.1 -p 8600 webapp.service.consul

# Consultar con filtro de tag
dig @127.0.0.1 -p 8600 production.webapp.service.consul

# Obtener registros SRV (incluyen puerto)
dig @127.0.0.1 -p 8600 webapp.service.consul SRV

# Integrar con el resolver del sistema (Ubuntu/systemd-resolved)
cat > /etc/systemd/resolved.conf.d/consul.conf << 'EOF'
[Resolve]
DNS=127.0.0.1:8600
Domains=~consul
EOF

systemctl restart systemd-resolved
# Ahora puedes resolver: dig webapp.service.consul

Almacén de Clave-Valor (KV)

El KV store de Consul es útil para configuración dinámica:

# Escribir un valor en el KV store
consul kv put config/webapp/database_url "postgresql://db:5432/webapp"
consul kv put config/webapp/max_connections "100"

# Leer valores
consul kv get config/webapp/database_url
consul kv get -recurse config/webapp/

# Listar claves
consul kv export config/ > backup-config.json

# Via API REST
curl http://localhost:8500/v1/kv/config/webapp/database_url
# Devuelve el valor en base64, decodificar con:
curl http://localhost:8500/v1/kv/config/webapp/database_url | \
  python3 -c "import sys,json,base64; data=json.load(sys.stdin); print(base64.b64decode(data[0]['Value']).decode())"

Comprobaciones de Salud

# Ver estado de salud de todos los servicios
consul health services
consul health state passing
consul health state critical

# Ver salud de un servicio específico
consul health service webapp

# Comprobación de salud via script (requiere enable_local_script_checks = true)
cat > /etc/consul.d/check-disk.hcl << 'EOF'
check {
    id       = "disk-usage"
    name     = "Uso de disco"
    script   = "/usr/local/bin/check-disk.sh"
    interval = "60s"
}
EOF

Integración con Balanceadores de Carga

# Obtener todos los nodos saludables de un servicio para balanceo
consul catalog nodes -service=webapp -healthy

# Via API para integración con HAProxy o Nginx
curl "http://localhost:8500/v1/health/service/webapp?passing=true" | \
  python3 -m json.tool

# Template para Nginx con consul-template (instalar por separado)
# upstream webapp_servers {
#   {{range service "webapp"}}
#   server {{.Address}}:{{.Port}};
#   {{end}}
# }

Solución de Problemas

# Ver logs del agente Consul
journalctl -u consul -f

# Verificar conectividad entre nodos
consul members -status=alive

# Comprobar el estado del consenso Raft
consul operator raft list-peers

# Forzar salida de un nodo del clúster (si está caído)
consul force-leave nombre-nodo

# Validar archivos de configuración
consul validate /etc/consul.d/

# Ver eventos recientes
consul watch -type=services

# Depurar problemas de DNS
dig @127.0.0.1 -p 8600 consul.service.consul
# Debe devolver las IPs de los servidores del clúster

Conclusión

Consul proporciona una base sólida para arquitecturas de microservicios con su combinación de descubrimiento de servicios, comprobaciones de salud y almacén de configuración distribuido. La interfaz DNS nativa permite una adopción gradual sin modificar aplicaciones existentes, mientras que la API HTTP ofrece integración programática completa para orquestadores y herramientas de infraestructura como código.