TL;DR — Résumé Rapide

Maîtrisez HashiCorp Consul pour le service discovery et service mesh : architecture, health checks, ACL, proxies Envoy sidecar et fédération multi-datacenter.

HashiCorp Consul est une plateforme de réseau de services distribuée et hautement disponible qui résout l’un des problèmes les plus difficiles des microservices : comment les services se trouvent-ils, vérifient-ils la santé les uns des autres et communiquent-ils de manière sécurisée dans une infrastructure dynamique où les adresses IP changent constamment ? Consul répond aux trois questions à travers un plan de contrôle unifié combinant service discovery, health checking, stockage KV et un service mesh complet avec application du TLS mutuel. Ce guide couvre toutes les capacités principales de Consul, de la configuration d’un cluster à trois nœuds aux proxies sidecar Envoy et à la fédération multi-datacenter.

Prérequis

Avant de continuer, assurez-vous que les éléments suivants sont disponibles :

  • Hôte Linux ou macOS — Consul fonctionne sur tout système de type Unix et Windows ; les exemples utilisent Linux.
  • Docker 24+ — pour l’exemple de production avec Docker Compose en fin de guide.
  • curl et dig — pour tester les réponses DNS et de l’API HTTP.
  • Compréhension basique des microservices — familiarité avec l’équilibrage de charge, les health checks et TLS.
  • Binaire Consul 1.17+ — installez via le dépôt APT/YUM HashiCorp ou téléchargez depuis releases.hashicorp.com.

Installation sur 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

Architecture de Consul

Agents : Serveurs vs Clients

Chaque nœud d’un cluster Consul exécute un agent Consul dans l’un des deux modes :

Les agents serveurs forment le plan de contrôle. Ils participent à l’algorithme de consensus Raft pour élire un leader, stockent l’état autorité du cluster et répliquent cet état. Utilisez toujours un nombre impair : 3 serveurs tolèrent 1 panne ; 5 serveurs tolèrent 2 pannes.

Les agents clients s’exécutent sur chaque nœud non-serveur. Ils enregistrent les services et health checks locaux, transfèrent les requêtes aux serveurs et participent au réseau gossip. Les clients sont légers — ils ne stockent aucun état du cluster.

Protocole Gossip (Serf)

Consul utilise Serf, une implémentation du protocole gossip SWIM, pour l’appartenance au cluster et la détection des pannes. Tous les agents participent à deux pools gossip :

  • Pool gossip LAN — agents au sein du même datacenter.
  • Pool gossip WAN — serveurs entre datacenters. Active la fédération multi-datacenter.

Consensus Raft

Raft est utilisé uniquement entre les serveurs Consul pour la cohérence forte de l’état du cluster. Le leader accepte toutes les opérations d’écriture et réplique les entrées de log sur les suiveurs avant de valider.

Modèle de Datacenter

Un datacenter Consul est une unité isolée : un ensemble de serveurs partageant un pool gossip LAN. Plusieurs datacenters communiquent via gossip WAN ou mesh gateways.

Méthodes d’Installation

Installation du Binaire

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 pour 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 minimal :

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

Configuration du Cluster de Serveurs

Créez /etc/consul.d/consul.hcl sur chaque nœud serveur :

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 = "CLE_GOSSIP_BASE64_ICI"

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

Générez la clé gossip une fois et utilisez-la sur tous les nœuds :

consul keygen
# Sortie : j5Y3fIFjQKs2b9s9rG2ufA==

Démarrez le cluster :

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

Enregistrement des Services

Fichiers de Définition de Service

Créez un fichier JSON dans /etc/consul.d/ sur l’agent client :

{
  "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"
    }
  }
}

Enregistrement via l’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"
    }
  }'

Catalogue vs Agent

L’API d’agent (/v1/agent/service/*) gère les services enregistrés sur l’agent local. L’API de catalogue (/v1/catalog/service/*) interroge le registre global agrégé de tous les agents :

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

Health Checks

Consul supporte six types de health checks, tous avec les paramètres interval, timeout et deregister_critical_service_after.

HTTP — Consul effectue un GET HTTP ; 2xx = passing, 429 = warning, tout autre = critical.

TCP — Ouvre une connexion TCP vers le host:port spécifié.

Script — Exécute une commande shell ; code de sortie 0 = passing, 1 = warning, autre = critical.

TTL — L’application elle-même doit appeler l’API Consul pour mettre à jour son état de santé.

gRPC — Pour les services implémentant le protocole de santé gRPC.

Exemple de check TTL :

curl -X PUT http://localhost:8500/v1/agent/check/pass/service:worker-01 \
  -d "Traitement de file normal"

Définissez toujours deregister_critical_service_after pour supprimer automatiquement les services en échec continu :

"deregister_critical_service_after": "90s"

Interface DNS

Consul exécute un serveur DNS sur le port 8600. Les services sont résolus à <service>.service.<datacenter>.consul.

# Résoudre toutes les instances saines de "web"
dig @127.0.0.1 -p 8600 web.service.consul A

# Avec enregistrement SRV (inclut le port)
dig @127.0.0.1 -p 8600 web.service.consul SRV

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

Transfert DNS avec systemd-resolved

# /etc/systemd/resolved.conf.d/consul.conf
[Resolve]
DNS=127.0.0.1:8600
Domains=~consul
sudo systemctl restart systemd-resolved
# Vous pouvez maintenant utiliser : curl http://web.service.consul:8080/

Prepared Queries avec 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 utilise Envoy comme proxy sidecar et émet des certificats TLS de courte durée pour le TLS mutuel entre services.

Enregistrement du 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 &

Intentions

# Autoriser web à atteindre api
consul intention create web api

# Refuser une route spécifique
consul intention create -deny payments logging

# Lister toutes les intentions
consul intention list

Stockage KV

# Écrire une valeur
consul kv put config/app/log_level info

# Lire une valeur
consul kv get config/app/log_level

# Lister les clés sous un préfixe
consul kv list config/app/

# Supprimer une arborescence
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

Système ACL

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

consul acl bootstrap
# SecretID: db14c...   ← votre token bootstrap (root)

export CONSUL_HTTP_TOKEN="db14c..."

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

consul acl token create \
  -description "Token lecture service web" \
  -policy-name "lecture-service-web"

Interface Utilisateur Consul

L’interface web Consul est disponible sur http://localhost:8500/ui quand ui_config { enabled = true } est configuré. Sections principales :

  • Services — tous les services enregistrés avec état de santé, tags et nombre d’instances.
  • Nœuds — tous les agents avec leur état de santé et services enregistrés.
  • Key/Value — navigateur du stockage KV avec support pour créer, modifier et supprimer.
  • Intentions — visualisez et gérez les règles d’autorisation entre services.
  • Contrôles d’accès — gérez les tokens, politiques et rôles.

Fédération Multi-Datacenter

Gossip WAN

# Sur les serveurs dc2, rejoindre le pool WAN de dc1
consul join -wan 10.0.1.11

# Interroger le service web dans 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

Les mesh gateways sont l’approche moderne — ils font proxy du trafic entre datacenters sans exposer les services internes au WAN :

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

Comparaison : Consul vs Alternatives

FonctionnalitéConsuletcdZooKeeperEurekaIstioLinkerd
Service DiscoveryDNS + API HTTPAPI uniquementAPI uniquementAPI HTTPVia KubernetesVia Kubernetes
Health ChecksIntégré (6 types)Aucun natifAucun natifHeartbeat clientProbes KubernetesProbes Kubernetes
Service MeshOui (Connect)NonNonNonOui (Envoy)Oui (proxy2)
Stockage KVOuiOui (usage primaire)OuiNonNonNon
Système ACLOui (riche)BasiqueSASL/ACLNonRBACRBAC
Multi-datacenterNatifNonNonPairs répliquésNonNon
Sans KubernetesOuiOuiOuiOuiNonNon

Déploiement en Production avec 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

Pièges et Cas Limites

  • bootstrap_expect incohérent — tous les serveurs doivent avoir la même valeur ; une discordance empêche la formation du cluster.
  • Rotation de clé gossip — utilisez consul keyring pour effectuer la rotation ; tous les nœuds doivent terminer la rotation avant de supprimer l’ancienne clé.
  • Distribution des tokens ACL — évitez les tokens dans les fichiers de configuration ; utilisez le moteur de secrets Consul de Vault ou les secrets Kubernetes.
  • Compatibilité de version Envoy — alignez toujours la version d’Envoy avec la matrice de compatibilité Consul.
  • Délais d’expiration des health checks — définissez timeout inférieur à interval pour éviter les exécutions de checks qui se chevauchent.

Résumé

  • Trois ou cinq serveurs avec consensus Raft forment le plan de contrôle ; utilisez un nombre impair pour la tolérance au quorum.
  • Gossip (Serf) gère l’appartenance au cluster et la détection des pannes à l’échelle O(log N) en LAN et WAN.
  • Les définitions de service enregistrent les services avec des health checks riches qui suppriment automatiquement les instances non saines du DNS.
  • L’interface DNS sur le port 8600 permet de résoudre service.service.consul sans changement de code.
  • Consul Connect ajoute mTLS entre services via sidecars Envoy ; les intentions appliquent l’autorisation sans toucher au code applicatif.
  • Les prepared queries fournissent un failover au niveau DNS entre datacenters pour la haute disponibilité.
  • Le stockage KV combiné avec consul-template permet la gestion dynamique de la configuration.
  • Les ACL avec default_policy = deny verrouillent le cluster ; utilisez les méthodes d’authentification pour l’émission de tokens sans secrets.

Articles Associés