Prometheus 基于 Consul 的服务发现完全指南:从原理到实战
前言
Prometheus 基于 Consul 的服务发现完全指南:从原理到实战
在云原生与微服务架构中,服务的动态伸缩、弹性部署已成为常态。面对频繁变化的实例 IP 和端口,无论是静态配置还是基于文件的服务发现,都显得力不从心——前者需要频繁修改配置并重启,后者仍需手动维护目标文件。
Consul 服务发现正是为解决这一痛点而生。 Consul 作为专业的服务注册中心,让服务实例自动注册、自动下线,Prometheus 通过 Consul API 实时感知服务变化,实现监控目标的全自动动态管理。
本文将从零开始,系统讲解 Consul 服务发现的完整工作流程——安装部署、服务注册、Prometheus 配置、脚本自动化以及服务下线管理,并明确标注每个操作涉及的文件及其作用。
一、Consul 服务发现与其他方式的对比
1.1 不同服务发现方式的差异
在开始之前,我们先来理解 Consul 服务发现与其他方式的核心区别:
| 特性 | 静态配置 | 文件服务发现 | Consul 服务发现 |
|---|---|---|---|
| 工作方式 | 手动编辑 prometheus.yml |
手动维护 JSON/YAML 文件 | 服务自动注册到 Consul,无需手动改配置 |
| 服务自动注册/下线 | ❌ 不支持 | ❌ 不支持 | ✅ 支持 |
| 是否需要重启 Prometheus | ✅ 需要 | ❌ 不需要 | ❌ 不需要 |
| 实时性 | 无变化 | 依赖刷新间隔 | 实时同步 Consul 健康状态 |
| 使用场景 | 小型固定环境 | 小型测试环境 | 生产环境、微服务、Docker、K8s、大规模监控平台 |
1.2 适用场景
Consul 服务发现特别适合以下场景:
-
微服务架构:服务实例频繁扩缩容,需要自动发现新实例并移除已下线的实例
-
Docker/Kubernetes 环境:容器动态启停,IP 频繁变化
-
多云/混合云环境:跨云平台统一服务注册与发现
-
大规模监控平台:监控目标数量大、变化频繁,手动维护不可行
1.3 核心工作流程
Consul 服务发现的整体工作流程如下:
text
┌─────────────┐ ①注册服务 ┌──────────────────┐ ②查询服务列表 ┌─────────────┐
│ Exporter │ ───────────────▶ │ Consul │ ◀───────────────── │ Prometheus │
│ /业务服务 │ (HTTP API) │ (注册中心) │ (consul_sd) │ (9090) │
└─────────────┘ └──────────────────┘ └─────────────┘
│ │ │
│ │ │
└──────────────────────────────────┴────────────────────────────────────┘
③ Prometheus 周期性拉取服务列表,
自动生成监控目标并采集指标[reference:10]
二、环境准备
| 项目 | 说明 |
|---|---|
| 操作系统 | Linux(CentOS 7/8 或 Ubuntu 20.04+) |
| Consul | 待安装,默认端口 8500 |
| Prometheus | 已安装并正常运行(参考本系列之前的文章) |
| Node Exporter | 已安装并运行(用于演示服务注册) |
三、Consul 安装
3.1 方式一:二进制安装(推荐生产环境)
步骤一:下载 Consul 二进制包
bash
# 下载 Consul(以 v1.15.0 为例)
wget https://releases.hashicorp.com/consul/1.15.0/consul_1.15.0_linux_amd64.zip
# 解压
unzip consul_1.15.0_linux_amd64.zip
# 移动到系统路径
sudo mv consul /usr/local/bin/
该文件的作用:/usr/local/bin/consul 是 Consul 的可执行二进制文件,用于启动 Consul 服务和管理 Consul 集群。
步骤二:验证安装
bash
consul --version
步骤三:创建专用系统用户
bash
sudo useradd --no-create-home --shell /bin/false consul
步骤四:创建配置文件
操作文件:/etc/consul.d/consul.hcl(Consul 核心配置文件)
bash
sudo mkdir -p /etc/consul.d
sudo tee /etc/consul.d/consul.hcl <<'EOF'
# 数据存储目录
data_dir = "/opt/consul"
# 绑定地址(生产环境改为实际 IP)
bind_addr = "0.0.0.0"
# 客户端地址(允许外部访问 UI 和 API)
client_addr = "0.0.0.0"
# 数据中心名称
datacenter = "dc1"
# 启用 UI 界面
ui = true
# 服务注册配置文件目录
config_entries {
config_dir = "/etc/consul.d/services"
}
EOF
该文件的作用:定义 Consul 的核心运行参数,包括数据存储路径、网络绑定地址、是否启用 UI 界面等。
步骤五:创建 Systemd 服务文件
操作文件:/etc/systemd/system/consul.service
bash
sudo tee /etc/systemd/system/consul.service <<'EOF'
[Unit]
Description=Consul Service Discovery
After=network.target
[Service]
User=consul
Group=consul
Type=simple
ExecStart=/usr/local/bin/consul agent -config-dir=/etc/consul.d
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
[Install]
WantedBy=multi-user.target
EOF
该文件的作用:将 Consul 注册为 Systemd 服务,实现开机自启和进程守护。
步骤六:启动 Consul
bash
# 创建数据目录
sudo mkdir -p /opt/consul
sudo chown consul:consul /opt/consul
# 重新加载 systemd
sudo systemctl daemon-reload
# 启动 Consul
sudo systemctl start consul
# 设置开机自启
sudo systemctl enable consul
# 查看状态
sudo systemctl status consul
步骤七:验证 Consul
bash
# 查看 Consul 集群成员
consul members
# 通过浏览器访问 Consul UI
# http://<服务器IP>:8500
Consul 默认监听 8500 端口,提供服务注册、发现和 UI 访问。
步骤八:配置防火墙
bash
# CentOS 7
sudo firewall-cmd --permanent --add-port=8500/tcp
sudo firewall-cmd --reload
# Ubuntu
sudo ufw allow 8500/tcp
3.2 方式二:Docker 安装(推荐快速体验)
操作文件:docker-compose.yml
yaml
version: '3'
services:
consul:
image: hashicorp/consul:latest
container_name: consul
restart: always
ports:
- "8500:8500"
volumes:
- ./consul/data:/consul/data
- ./consul/config:/consul/config
command: agent -server -bootstrap-expect=1 -ui -client=0.0.0.0
启动:
bash
docker-compose up -d
或直接使用 Docker 命令:
bash
docker run -d --name consul -p 8500:8500 hashicorp/consul agent -dev -client=0.0.0.0
注意:
-dev模式仅适用于开发测试环境,生产环境请使用完整的集群配置。
四、Consul HTTP API 访问方式
Consul 提供了完善的 RESTful HTTP API,用于服务注册、查询和管理。
4.1 API 端点概览
| API 端点 | 方法 | 说明 |
|---|---|---|
/v1/agent/service/register |
PUT | 注册服务到本地 Agent |
/v1/agent/service/deregister/:service_id |
PUT | 从本地 Agent 注销服务 |
/v1/catalog/services |
GET | 获取所有已注册的服务列表 |
/v1/health/service/:service_name |
GET | 获取指定服务的健康实例列表 |
/v1/kv/:key |
GET/PUT/DELETE | 键值存储操作 |
4.2 基础 API 测试
bash
# 查看 Consul 集群状态
curl http://localhost:8500/v1/agent/self
# 查看所有已注册的服务
curl http://localhost:8500/v1/catalog/services
# 查看所有节点
curl http://localhost:8500/v1/catalog/nodes
五、通过 API 注册服务到 Consul
5.1 临时注册(测试用)
通过 curl 直接向 Consul API 发送注册请求:
bash
curl -X PUT \
-H "Content-Type: application/json" \
-d '{
"ID": "node_exporter-1",
"Name": "node_exporter",
"Tags": ["prometheus", "node"],
"Address": "192.168.1.101",
"Port": 9100,
"Check": {
"HTTP": "http://192.168.1.101:9100/metrics",
"Interval": "10s",
"Timeout": "3s"
}
}' \
http://localhost:8500/v1/agent/service/register
该命令的作用:将一个 Node Exporter 实例注册到 Consul,并配置健康检查。Consul 会定期检查 /metrics 端点是否可达,如果不可达则标记该服务为不健康。
5.2 持久化注册(推荐)
将服务定义写入 JSON 文件,通过 Consul 的配置目录自动加载。
操作文件:/etc/consul.d/services/node_exporter.json
json
{
"service": {
"id": "node_exporter-192.168.1.101",
"name": "node_exporter",
"tags": ["prometheus", "node", "production"],
"address": "192.168.1.101",
"port": 9100,
"check": {
"http": "http://192.168.1.101:9100/metrics",
"interval": "10s",
"timeout": "3s",
"deregister_critical_service_after": "30s"
}
}
}
该文件的作用:定义服务注册的完整信息,包括服务 ID、名称、标签、地址、端口和健康检查配置。Consul 启动时会自动加载 config_entries.config_dir 目录下的所有服务定义文件。
重新加载配置:
bash
# 重载 Consul 配置(不重启服务)
consul reload
# 或使用 systemctl
sudo systemctl reload consul
5.3 注册多个 Exporter
操作文件:/etc/consul.d/services/mysql_exporter.json
json
{
"service": {
"id": "mysql_exporter-192.168.1.101",
"name": "mysql_exporter",
"tags": ["prometheus", "mysql", "production"],
"address": "192.168.1.101",
"port": 9104,
"check": {
"http": "http://192.168.1.101:9104/metrics",
"interval": "10s",
"timeout": "3s"
}
}
}
操作文件:/etc/consul.d/services/redis_exporter.json
json
{
"service": {
"id": "redis_exporter-192.168.1.101",
"name": "redis_exporter",
"tags": ["prometheus", "redis", "production"],
"address": "192.168.1.101",
"port": 9121,
"check": {
"http": "http://192.168.1.101:9121/metrics",
"interval": "10s",
"timeout": "3s"
}
}
}
六、配置 Prometheus 对接 Consul
6.1 修改 Prometheus 配置文件
操作文件:/etc/prometheus/prometheus.yml
在 scrape_configs 部分添加 Consul 服务发现配置:
yaml
scrape_configs:
# ... 其他 job 配置 ...
# ============================================
# 基于 Consul 的服务发现
# ============================================
- job_name: 'consul_services'
consul_sd_configs:
# Consul 服务器地址[reference:26]
- server: 'localhost:8500'
# 可选:按标签过滤服务[reference:27]
tags:
- 'prometheus'
# 刷新间隔[reference:28]
refresh_interval: 30s
# 重标签配置:将 Consul 元数据转换为 Prometheus 标签[reference:29]
relabel_configs:
# 使用 Consul 中的服务名作为 job 标签
- source_labels: [__meta_consul_service]
target_label: job
# 使用服务地址作为 instance 标签
- source_labels: [__meta_consul_service_address]
target_label: instance
# 保留 Consul 中的服务标签
- source_labels: [__meta_consul_tags]
target_label: consul_tags
# 仅抓取健康的服务实例
- source_labels: [__meta_consul_service_health]
regex: passing
action: keep
配置项说明:
| 配置项 | 说明 |
|---|---|
server |
Consul 服务器的地址和端口 |
tags |
可选,只发现带有指定标签的服务 |
refresh_interval |
从 Consul 刷新目标列表的频率 |
relabel_configs |
将 Consul 元数据标签转换为 Prometheus 标签 |
该文件的作用:定义 Prometheus 如何从 Consul 获取监控目标。consul_sd_configs 告诉 Prometheus 去哪个 Consul 服务器查询服务列表,relabel_configs 负责将 Consul 返回的元数据转换为 Prometheus 可用的标签。
6.2 更多配置示例
按服务名过滤:
yaml
consul_sd_configs:
- server: 'localhost:8500'
services: ['node_exporter', 'mysql_exporter'] # 只发现指定服务
使用 Consul 的元数据标签:
Consul 会为每个服务生成以下元数据标签:
| 元数据标签 | 说明 |
|---|---|
__meta_consul_service |
服务名称 |
__meta_consul_service_address |
服务地址 |
__meta_consul_service_port |
服务端口 |
__meta_consul_tags |
服务标签列表 |
__meta_consul_service_id |
服务 ID |
__meta_consul_service_health |
服务健康状态 |
6.3 使配置生效
bash
# 检查配置语法
promtool check config /etc/prometheus/prometheus.yml
# 热加载配置(推荐,不中断服务)
sudo systemctl reload prometheus
# 或使用 API 热加载(需启用 --web.enable-lifecycle)
curl -X POST http://localhost:9090/-/reload[reference:37]
6.4 验证服务发现
-
访问
http://<Prometheus_IP>:9090/targets,查看consul_services作业下的目标 -
访问
http://<Prometheus_IP>:9090/service-discovery,查看 Consul 发现的所有目标 -
在 Consul UI(
http://<Consul_IP>:8500)中查看已注册的服务
七、创建自动注册脚本
在生产环境中,通常需要编写脚本实现服务的自动注册与注销。
7.1 Shell 注册脚本
操作文件:/opt/scripts/register_to_consul.sh
bash
#!/bin/bash
# 功能:将服务注册到 Consul
# 用法:./register_to_consul.sh <service_name> <service_port> <service_ip>
SERVICE_NAME=${1:-"node_exporter"}
SERVICE_PORT=${2:-9100}
SERVICE_IP=${3:-$(hostname -I | awk '{print $1}')}
CONSUL_URL="http://localhost:8500/v1/agent/service/register"
# 构建服务注册 JSON
SERVICE_JSON=$(cat <<EOF
{
"ID": "${SERVICE_NAME}-${SERVICE_IP}",
"Name": "${SERVICE_NAME}",
"Tags": ["prometheus", "production"],
"Address": "${SERVICE_IP}",
"Port": ${SERVICE_PORT},
"Check": {
"HTTP": "http://${SERVICE_IP}:${SERVICE_PORT}/metrics",
"Interval": "10s",
"Timeout": "3s",
"DeregisterCriticalServiceAfter": "30s"
}
}
EOF
)
# 发送注册请求
curl -X PUT -H "Content-Type: application/json" -d "${SERVICE_JSON}" ${CONSUL_URL}
if [ $? -eq 0 ]; then
echo "Service ${SERVICE_NAME} registered successfully at ${SERVICE_IP}:${SERVICE_PORT}"
else
echo "Failed to register service ${SERVICE_NAME}"
exit 1
fi
该文件的作用:通过脚本自动将指定服务注册到 Consul,支持传入服务名、端口和 IP 参数。
使用示例:
bash
chmod +x /opt/scripts/register_to_consul.sh
# 注册 Node Exporter
./register_to_consul.sh node_exporter 9100 192.168.1.101
# 注册 MySQL Exporter
./register_to_consul.sh mysql_exporter 9104 192.168.1.101
7.2 Python 注册脚本
操作文件:/opt/scripts/register_to_consul.py
python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 功能:通过 Python 将服务注册到 Consul
import json
import requests
import socket
import sys
CONSUL_URL = "http://localhost:8500/v1/agent/service/register"
def register_service(service_name, service_port, service_ip=None):
"""注册服务到 Consul"""
if service_ip is None:
service_ip = socket.gethostbyname(socket.gethostname())
service_id = f"{service_name}-{service_ip}"
payload = {
"ID": service_id,
"Name": service_name,
"Tags": ["prometheus", "production"],
"Address": service_ip,
"Port": service_port,
"Check": {
"HTTP": f"http://{service_ip}:{service_port}/metrics",
"Interval": "10s",
"Timeout": "3s",
"DeregisterCriticalServiceAfter": "30s"
}
}
response = requests.put(
CONSUL_URL,
data=json.dumps(payload),
headers={"Content-Type": "application/json"}
)
if response.status_code == 200:
print(f"✅ Service {service_name} registered at {service_ip}:{service_port}")
else:
print(f"❌ Failed to register: {response.text}")
sys.exit(1)
if __name__ == "__main__":
if len(sys.argv) < 3:
print("Usage: python3 register_to_consul.py <service_name> <port> [ip]")
sys.exit(1)
service_name = sys.argv[1]
service_port = int(sys.argv[2])
service_ip = sys.argv[3] if len(sys.argv) > 3 else None
register_service(service_name, service_port, service_ip)
该文件的作用:Python 版本的服务注册脚本,功能与 Shell 版本相同,适合集成到 Python 应用或运维平台中。
使用示例:
bash
python3 /opt/scripts/register_to_consul.py node_exporter 9100 192.168.1.101
7.3 服务发现脚本(查询已注册服务)
操作文件:/opt/scripts/discover_services.sh
bash
#!/bin/bash # 功能:查询 Consul 中已注册的服务列表
curl -s http://localhost:8500/v1/catalog/services | jq '.'
该文件的作用:快速查询 Consul 中所有已注册的服务,用于验证注册是否成功。
八、Consul 删除/注销服务
8.1 通过 API 删除服务
bash
# 删除指定服务(通过服务 ID)
curl -X PUT http://localhost:8500/v1/agent/service/deregister/<service_id>
# 示例:删除 node_exporter
curl -X PUT http://localhost:8500/v1/agent/service/deregister/node_exporter-192.168.1.101
8.2 通过 Consul 命令删除
bash
# 使用 consul 命令注销服务[reference:38]
consul services deregister /etc/consul.d/services/node_exporter.json
8.3 删除脚本
操作文件:/opt/scripts/deregister_from_consul.sh
bash
#!/bin/bash
# 功能:从 Consul 注销服务
# 用法:./deregister_from_consul.sh <service_id>
SERVICE_ID=${1}
CONSUL_URL="http://localhost:8500/v1/agent/service/deregister/${SERVICE_ID}"
if [ -z "${SERVICE_ID}" ]; then
echo "Usage: $0 <service_id>"
echo "Example: $0 node_exporter-192.168.1.101"
exit 1
fi
curl -X PUT ${CONSUL_URL}
if [ $? -eq 0 ]; then
echo "Service ${SERVICE_ID} deregistered successfully"
else
echo "Failed to deregister service ${SERVICE_ID}"
exit 1
fi
该文件的作用:通过脚本快速注销 Consul 中的服务,适用于服务下线或维护场景。
使用示例:
bash
chmod +x /opt/scripts/deregister_from_consul.sh
./deregister_from_consul.sh node_exporter-192.168.1.101
8.4 服务退出时自动注销
在生产环境中,服务进程退出时应自动从 Consul 注销,避免产生“僵尸服务”。
在服务的停止脚本中添加:
bash
# 在服务停止时执行
curl -X PUT http://localhost:8500/v1/agent/service/deregister/node_exporter-192.168.1.101
九、ConsulManager 简介
在生产环境中,手动编写 JSON 文件或 curl 命令来管理服务注册既繁琐又容易出错。ConsulManager 正是为解决这一问题而生的 Web 管理工具。
9.1 什么是 ConsulManager
ConsulManager 是一个使用 Flask + Vue 开发的 Consul Web 管理工具,比官方自带的 Web UI 实现了更多的功能。它弥补了 Consul 官方 UI 对 Services 管理的不足。
主要功能:
-
Consul Web Manager:支持 Services 的增删改查、批量删除,直观查看服务实例信息和健康状态,便捷配置 Tags、Meta 和健康检查
-
ECS Manager:支持同步阿里云、腾讯云、华为云、AWS 的 ECS 主机信息到 Consul,实现 Prometheus 监控目标的自动发现
-
Blackbox Manager:基于 Blackbox Exporter 实现站点与接口监控,通过 Web 界面即可对监控目标增删改查,支持批量删除和分类管理
9.2 部署方式
使用 Docker Compose 一键部署:
bash
# 一键安装脚本
curl -s https://starsl.cn/static/img/all_install.sh | sudo bash
安装路径为 /opt/tensuns。安装完成后,通过浏览器访问 http://<服务器IP>:1026 即可登录 ConsulManager 管理界面。
使用 ConsulManager 的优势:
不用写 JSON、不用重启 Consul,批量增删、改标签、改健康检查等等,一切都可以在 Web 界面上完成。
十、操作文件速查表
| 文件路径 | 作用 |
|---|---|
/usr/local/bin/consul |
Consul 可执行二进制文件 |
/etc/consul.d/consul.hcl |
Consul 核心配置文件 |
/etc/consul.d/services/*.json |
服务注册定义文件目录 |
/etc/systemd/system/consul.service |
Consul Systemd 服务文件 |
/opt/consul/ |
Consul 数据存储目录 |
/etc/prometheus/prometheus.yml |
Prometheus 主配置文件,添加 consul_sd_configs |
/opt/scripts/register_to_consul.sh |
Shell 服务注册脚本 |
/opt/scripts/register_to_consul.py |
Python 服务注册脚本 |
/opt/scripts/deregister_from_consul.sh |
Shell 服务注销脚本 |
/opt/scripts/discover_services.sh |
服务查询脚本 |
十一、总结
本文系统介绍了 Prometheus 基于 Consul 的服务发现的完整知识体系:
-
与其他方式的区别:Consul 服务发现实现了服务自动注册与下线,无需手动维护配置文件,是生产环境和大规模监控的首选方案
-
适用场景:微服务架构、容器环境、多云环境、大规模监控平台
-
安装部署:支持二进制安装(生产推荐)和 Docker 安装(快速体验)
-
Consul HTTP API:提供了完整的 RESTful API,支持服务注册、查询、注销等操作
-
服务注册:支持通过 API 临时注册和 JSON 文件持久化注册两种方式
-
Prometheus 配置:通过
consul_sd_configs对接 Consul,实现监控目标的自动发现 -
脚本自动化:提供了 Shell 和 Python 两种注册/注销脚本,便于集成到自动化运维体系
-
ConsulManager:Web 管理工具,无需写 JSON 和重启 Consul,即可在界面上完成服务的增删改查
一句话总结:Consul 服务发现让 Prometheus 的监控目标管理从“手动维护”进化到“全自动感知”——服务注册到 Consul 即被 Prometheus 自动发现并开始监控,服务下线即自动停止抓取,全程无需人工干预。
更多推荐


所有评论(0)