HashiCorp Consul

技术栈
工具链
服务发现配置管理服务网格健康检查微服务

概览

HashiCorp Consul

Consul 是 HashiCorp 开发的服务网格(Service Mesh)解决方案,提供跨分布式系统的服务发现、配置管理、健康检查、服务分段等能力。

核心价值:一站式服务网络基础设施。对比 ZooKeeper/etcd,Consul 原生支持健康检查、DNS/HTTP 服务发现、多数据中心。

关键特性

  • 服务发现(DNS / HTTP API)
  • 健康检查(TCP / HTTP / gRPC / Script)
  • KV Store(配置中心)
  • 多数据中心原生支持(WAN Federation)
  • Service Mesh(Consul Connect)支持 mTLS + 鉴权
  • ACL 访问控制

安装

1. 环境准备

  • 操作系统:Linux、macOS、Windows
  • 端口
    • 8500(HTTP API + UI)
    • 8600(DNS)
    • 8300/8301/8302(集群 RPC / Serf LAN / Serf WAN)
  • 架构:单 Agent 即可开发,生产建议 3-5 节点集群

2. 安装命令

Docker(开发模式)

# 单节点开发
docker run -d --name consul -p 8500:8500 -p 8600:8600/udp \
  consul:latest agent -dev -client=0.0.0.0

# 访问 UI
# http://localhost:8500

Docker Compose 集群

version: '3.8'
services:
  consul1:
    image: consul:latest
    hostname: consul1
    command: agent -server -bootstrap-expect=3 -node=consul1
      -bind=0.0.0.0 -client=0.0.0.0
      -retry-join=consul2 -retry-join=consul3
    ports: ["8501:8500"]
  consul2:
    image: consul:latest
    hostname: consul2
    command: agent -server -node=consul2
      -bind=0.0.0.0 -client=0.0.0.0
      -retry-join=consul1
    ports: ["8502:8500"]
  consul3:
    image: consul:latest
    hostname: consul3
    command: agent -server -node=consul3
      -bind=0.0.0.0 -client=0.0.0.0
      -retry-join=consul1
    ports: ["8503:8500"]

手动安装

# 下载
curl -O https://releases.hashicorp.com/consul/1.18.0/consul_1.18.0_linux_amd64.zip
unzip consul_1.18.0_linux_amd64.zip
sudo mv consul /usr/local/bin/

# 开发模式启动
consul agent -dev

# 生产模式
consul agent -server -bootstrap-expect=3 \
  -data-dir=/var/lib/consul \
  -node=node1 -bind=192.168.1.10 \
  -client=0.0.0.0 \
  -retry-join=192.168.1.11 -retry-join=192.168.1.12

macOS

brew install consul
consul agent -dev

3. 常见安装问题

问题 解决方案
No cluster leader 集群未完成 Bootstrap,检查 bootstrap-expect 和节点数
DNS 查询失败 默认 DNS 端口 8600,测试:dig @localhost -p 8600 service-name.service.consul
Agent 无法加入集群 检查 retry-join 地址、8300-8302 端口是否互通
bind: address already in use 开发模式冲突:已有 Consul 在跑,consul leave && consul agent -dev
KV 数据丢失 -dev 模式数据在内存中,生产务必配置 -data-dir

示例

Consul 服务注册发现与健康检查

目标

使用 Python consul 库注册服务、查询服务、配置健康检查。

环境准备

pip install python-consul
# 确保 Consul 运行中
docker run -d --name consul -p 8500:8500 consul:latest agent -dev -client=0.0.0.0

完整代码

服务注册(register.py)

import consul
import socket
import time

c = consul.Consul(host='localhost', port=8500)

service_id = f"order-service-{socket.gethostname()}"

# 注册服务(含健康检查)
c.agent.service.register(
    name='order-service',
    service_id=service_id,
    address='192.168.1.10',
    port=8080,
    tags=['v1.0', 'production'],
    check=consul.Check.http(
        url='http://192.168.1.10:8080/health',
        interval='10s',
        timeout='3s',
        deregister='30s'  # 故障 30s 后自动注销
    )
)

print(f"✅ 服务已注册: {service_id}")

# 保持运行
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    c.agent.service.deregister(service_id)
    print(f"👋 服务已注销: {service_id}")

服务发现(discover.py)

import consul
import random

c = consul.Consul(host='localhost', port=8500)

# 方式一:HTTP API 查询健康服务
def get_healthy_service(name):
    _, nodes = c.health.service(name, passing=True)
    if not nodes:
        raise Exception(f"没有健康的 {name} 实例")
    
    # 随机选一个(客户端负载均衡)
    node = random.choice(nodes)
    return f"http://{node['Service']['Address']}:{node['Service']['Port']}"

# 方式二:DNS 查询
def dns_discover(name):
    import dns.resolver
    answers = dns.resolver.query(f"{name}.service.consul", 'A')
    for rdata in answers:
        print(f"DNS 解析: {rdata.address}")

# 使用
try:
    url = get_healthy_service('order-service')
    print(f"🔗 发现服务: {url}")
except Exception as e:
    print(f"❌ {e}")

# 列出所有服务
_, services = c.agent.services()
for sid, svc in services.items():
    print(f"  {sid}: {svc['Address']}:{svc['Port']} [{','.join(svc.get('Tags', []))}]")

KV 配置读写(config.py)

import consul

c = consul.Consul(host='localhost', port=8500)

# 写入配置
c.kv.put('app/db/url', 'mysql://localhost:3306/mydb')
c.kv.put('app/db/max_connections', '100')
c.kv.put('app/feature/ai_recommend', 'true')

# 读取配置
_, data = c.kv.get('app/db/url')
print(f"DB URL: {data['Value'].decode()}")

# 递归读取
_, keys = c.kv.get('app/', recurse=True)
for k in keys:
    print(f"  {k['Key']} = {k['Value']}")

# 监听配置变更
index = None
print("👂 监听配置变更...")
while True:
    _, data = c.kv.get('app/db/url', index=index, wait='30s')
    if data:
        index = data['ModifyIndex'] + 1  # 下次从该版本之后监听
        print(f"配置变更: {data['Value'].decode()}")

运行步骤

# 1. 注册服务
python register.py

# 2. 另一个终端,发现服务
python discover.py

# 3. 读写配置
python config.py

预期输出

discover.py 输出已注册的服务实例信息。config.py 能读写 KV 并实时监听变更。

教程

Consul 入门教程:服务网格与多数据中心

1. Consul vs ZooKeeper vs etcd

维度 Consul ZooKeeper etcd
协议 Raft + Gossip ZAB Raft
服务发现 原生 DNS/HTTP API 需框架封装 需框架封装
健康检查 丰富(TCP/HTTP/gRPC/Script) 仅 Session 超时 租约(Lease)
KV Store ❌(弱支持)
多数据中心 ✅ 原生
语言 Go Java Go

2. 健康检查深度

{
  "check": {
    "http": "http://localhost:8080/health",  // HTTP
    "tcp": "localhost:3306",                  // TCP
    "grpc": "localhost:50051",               // gRPC
    "args": ["/usr/local/bin/check.sh"],     // Script
    "interval": "10s",
    "timeout": "3s"
  }
}

健康检查状态:passingwarningcritical。只有 passing 的服务被 DNS/HTTP 返回。

3. DNS 接口

# 查询服务地址
dig @localhost -p 8600 order-service.service.consul

# 按标签过滤
dig @localhost -p 8600 v1.order-service.service.consul

# SRV 记录(含端口)
dig @localhost -p 8600 order-service.service.consul SRV

4. Consul Connect(Service Mesh)

启用 mTLS 和鉴权的服务间通信:

# Envoy Sidecar 代理
service:
  name: order-service
  connect:
    sidecar_service:
      proxy:
        upstreams:
          - destination_name: payment-service
            local_bind_port: 5000

# 意图(Intentions):访问控制
consul intention create order-service payment-service allow

5. 多数据中心架构

Datacenter "us-east"  ←→  WAN Gossip  ←→  Datacenter "eu-west"
     │                                       │
  [Service A]                            [Service A]
# 加入 WAN
consul join -wan <;remote-server-ip>

# 查询远程服务
curl http://localhost:8500/v1/catalog/service/service-a?dc=eu-west

6. 思考题

  1. Consul 的 Raft 和 Gossip 协议分别负责什么?
  2. Consul Connect 和 Istio 的架构有何不同?各自优劣?
  3. 多数据中心环境下如何保证配置最终一致性?

参考资料

暂无参考文献