HashiCorp Consul es una herramienta de descubrimiento de servicios: cada servicio se registra en el catálogo de Consul con su dirección, su puerto y una comprobación de salud, y el resto de la infraestructura lo encuentra por DNS o por la API HTTP. Además incluye un almacén clave-valor (KV) para configuración compartida. En este tutorial montarás un clúster de tres servidores Consul en Ubuntu 24.04, registrarás un servicio web con un health check y lo resolverás por DNS desde el propio sistema.
Requisitos previos
Para seguir esta guía necesitas:
- Tres servidores con Ubuntu 24.04 LTS, por ejemplo tres VPS de CubePath, con al menos 2 GB de RAM cada uno.
- Un usuario no root con privilegios
sudoen cada servidor. - Una red privada entre los tres servidores. En los ejemplos se usan estas direcciones, sustitúyelas por las tuyas:
| Nombre | IP privada |
|---|---|
| consul-01 | 10.0.1.10 |
| consul-02 | 10.0.1.11 |
| consul-03 | 10.0.1.12 |
- Relojes sincronizados (Ubuntu 24.04 trae
systemd-timesyncdactivo por defecto; compruébalo contimedatectl).
Salvo que se indique lo contrario, ejecuta cada paso en los tres servidores.
Paso 1: Instalar Consul desde el repositorio de HashiCorp
HashiCorp publica paquetes firmados para Ubuntu. Instala las herramientas necesarias y descarga la clave del repositorio en /etc/apt/keyrings:
sudo apt update
sudo apt install -y wget gpg lsb-release
sudo install -m 0755 -d /etc/apt/keyrings
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/hashicorp-archive-keyring.gpg
Añade el repositorio:
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
Instala Consul:
sudo apt update
sudo apt install -y consul
El paquete crea el usuario de sistema consul, el directorio de datos /opt/consul, la configuración en /etc/consul.d/ y la unidad systemd consul.service, así que no tienes que crear nada de eso a mano. Comprueba la versión instalada:
consul version
Consul v1.x.x
Revision ...
Paso 2: Generar la clave de cifrado gossip
Los agentes Consul se comunican entre sí con un protocolo gossip que conviene cifrar. Genera la clave solo una vez, en consul-01:
consul keygen
pUqJrVyVRj5jsiYEkM/tFQYfWyJIv4s3XkvDwy7Cu5s=
Copia el valor que obtengas: lo usarás en el archivo de configuración de los tres servidores. Trátalo como un secreto.
Paso 3: Configurar los servidores Consul
Abre el archivo de configuración que instaló el paquete:
sudo nano /etc/consul.d/consul.hcl
Sustituye su contenido por el siguiente bloque. Cambia node_name y bind_addr en cada servidor, y pon en encrypt la clave del paso anterior:
datacenter = "dc1"
node_name = "consul-01"
data_dir = "/opt/consul"
server = true
bootstrap_expect = 3
bind_addr = "10.0.1.10"
client_addr = "127.0.0.1"
retry_join = ["10.0.1.10", "10.0.1.11", "10.0.1.12"]
encrypt = "pUqJrVyVRj5jsiYEkM/tFQYfWyJIv4s3XkvDwy7Cu5s="
ui_config {
enabled = true
}
log_level = "INFO"
Qué hace cada ajuste:
serverybootstrap_expect = 3: el nodo actúa como servidor y el clúster no elige líder hasta que haya tres servidores unidos.bind_addr: la IP privada por la que el nodo habla con el resto del clúster.client_addr = "127.0.0.1": la API HTTP (puerto 8500), la interfaz web y el DNS (puerto 8600) solo escuchan en local. Sin ACLs activadas, exponer la API a otras máquinas permite a cualquiera modificar el catálogo.retry_join: lista de servidores a los que el nodo intenta unirse hasta conseguirlo, sin importar el orden de arranque.
Valida la sintaxis antes de arrancar:
sudo consul validate /etc/consul.d/
Configuration is valid!
Paso 4: Abrir los puertos en el firewall
Consul usa estos puertos entre servidores: 8300/tcp (RPC), 8301/tcp y udp (gossip LAN) y 8302/tcp y udp (gossip WAN). Permite el tráfico solo desde la red privada. Si UFW aún no está activo, permite antes SSH para no perder el acceso:
sudo ufw allow OpenSSH
sudo ufw allow from 10.0.1.0/24 to any port 8300:8302 proto tcp
sudo ufw allow from 10.0.1.0/24 to any port 8301:8302 proto udp
sudo ufw enable
Comprueba las reglas:
sudo ufw status
Paso 5: Arrancar el clúster
Habilita e inicia el servicio en los tres servidores:
sudo systemctl enable --now consul
Comprueba que el servicio está activo:
sudo systemctl status consul
Cuando los tres nodos estén en marcha, lista los miembros del clúster desde cualquiera de ellos:
consul members
Node Address Status Type Build Protocol DC Partition Segment
consul-01 10.0.1.10:8301 alive server 1.x.x 2 dc1 default <all>
consul-02 10.0.1.11:8301 alive server 1.x.x 2 dc1 default <all>
consul-03 10.0.1.12:8301 alive server 1.x.x 2 dc1 default <all>
Comprueba que se ha elegido un líder de Raft:
consul operator raft list-peers
Node ID Address State Voter RaftProtocol
consul-01 8f3a... 10.0.1.10:8300 leader true 3
consul-02 1c7e... 10.0.1.11:8300 follower true 3
consul-03 a42d... 10.0.1.12:8300 follower true 3
Si un nodo no aparece, revisa sus logs con sudo journalctl -u consul -e.
Paso 6: Registrar un servicio con health check
Como ejemplo, registrarás un servidor web Nginx en consul-01. Instálalo:
sudo apt install -y nginx
Crea el archivo de definición del servicio:
sudo nano /etc/consul.d/web.hcl
service {
name = "web"
port = 80
tags = ["nginx"]
check {
id = "web-http"
name = "HTTP en el puerto 80"
http = "http://127.0.0.1:80/"
interval = "10s"
timeout = "2s"
}
}
El health check hace una petición HTTP cada 10 segundos. Mientras responda con un código 2xx el servicio figura como sano; si falla, Consul deja de devolverlo en las consultas DNS.
Ajusta el propietario del archivo y recarga la configuración del agente sin reiniciarlo:
sudo chown consul:consul /etc/consul.d/web.hcl
consul reload
Configuration reload triggered
Comprueba que el servicio aparece en el catálogo y qué nodos lo ofrecen:
consul catalog services
consul catalog nodes -service=web
consul
web
Node ID Address DC
consul-01 8f3a... 10.0.1.10 dc1
Consulta el estado del health check a través de la API HTTP. El parámetro passing filtra solo las instancias sanas:
curl -s "http://127.0.0.1:8500/v1/health/service/web?passing" | python3 -m json.tool | grep -E '"(Status|ServiceName)"'
"Status": "passing",
"ServiceName": "web",
Para registrar el mismo servicio en otras máquinas, repite este paso en cada una. En producción, las máquinas que ejecutan aplicaciones no son servidores Consul, sino agentes cliente (misma instalación con server = false y sin bootstrap_expect).
Paso 7: Resolver servicios por DNS
Consul responde consultas DNS en el puerto 8600 con el formato <servicio>.service.consul. Pruébalo con dig:
dig @127.0.0.1 -p 8600 web.service.consul +short
10.0.1.10
Los registros SRV incluyen también el puerto:
dig @127.0.0.1 -p 8600 web.service.consul SRV +short
1 1 80 consul-01.node.dc1.consul.
Para que cualquier programa resuelva nombres .consul sin indicar el puerto, reenvía ese dominio a Consul desde systemd-resolved. Crea el directorio de configuración adicional y el archivo:
sudo mkdir -p /etc/systemd/resolved.conf.d
sudo nano /etc/systemd/resolved.conf.d/consul.conf
[Resolve]
DNS=127.0.0.1:8600
Domains=~consul
Domains=~consul hace que solo las consultas del dominio consul vayan a ese servidor; el resto sigue usando tus DNS habituales. Reinicia el servicio y prueba la resolución normal:
sudo systemctl restart systemd-resolved
resolvectl query web.service.consul
web.service.consul: 10.0.1.10
Ahora cualquier aplicación del servidor puede conectarse a web.service.consul y recibirá solo instancias sanas.
Paso 8: Guardar configuración en el almacén KV
El almacén clave-valor sirve para configuración que comparten varios servicios. Escribe un par de claves:
consul kv put config/web/max_connections 100
consul kv put config/web/log_level info
Success! Data written to: config/web/max_connections
Success! Data written to: config/web/log_level
Léelas de forma individual o por prefijo:
consul kv get config/web/max_connections
consul kv get -recurse config/web/
100
config/web/log_level:info
config/web/max_connections:100
Los datos se replican a los tres servidores, así que puedes leerlos desde cualquiera. Para una copia de seguridad de un prefijo en JSON:
consul kv export config/ > consul-kv-config.json
Para una copia completa del estado del clúster (catálogo, KV y demás), usa un snapshot:
consul snapshot save consul-$(date +%F).snap
Paso 9: Acceder a la interfaz web
La interfaz web escucha en 127.0.0.1:8500, así que no está expuesta a Internet. Accede a ella con un túnel SSH desde tu equipo:
ssh -L 8500:127.0.0.1:8500 your_user@your_server_ip
Con el túnel abierto, visita http://localhost:8500/ui en tu navegador. Verás los servicios, los nodos, el estado de los health checks y el almacén KV.
Solución de problemas
consul memberssolo muestra un nodo: los servidores no se ven entre sí. Comprueba que el puerto 8301 (tcp y udp) está permitido en UFW y quebind_addres la IP privada correcta. Prueba la conectividad connc -zv 10.0.1.11 8301.- Errores
No cluster leader: todavía no hay tres servidores unidos, porquebootstrap_expect = 3. Revisa que los tres servicios están activos. - Errores de gossip con
encrypt: la clave no es la misma en todos los nodos. Copia exactamente el mismo valor en los tres y reinicia consudo systemctl restart consul. - El servicio no aparece en DNS: el health check está fallando. Mira el estado con la consulta a
/v1/health/service/websin?passingy revisa que la URL del check responde concurl -I http://127.0.0.1/. - Nodo caído que sigue en la lista: si un servidor se ha eliminado definitivamente, sácalo del clúster con
consul force-leave consul-03.
Conclusión
Tienes un clúster Consul de tres servidores con cifrado gossip, un servicio registrado con health check, resolución DNS integrada en systemd-resolved y un almacén KV replicado. Como siguientes pasos, activa el sistema de ACLs para proteger la API antes de exponerla fuera de 127.0.0.1, instala agentes cliente en las máquinas que ejecutan tus aplicaciones y usa consul-template para generar configuraciones de Nginx o HAProxy a partir del catálogo.
