Prometheus+Consul 大规模服务发现监控部署文档
文档信息
-
适用规模:1000台服务器及以上生产环境
-
操作系统:Ubuntu 22.04/24.04 LTS
-
软件版本:
-
Consul: 1.20.0(LTS稳定版)
-
Prometheus: 2.53.0(LTS稳定版)
-
Grafana: 11.0.0
-
Node Exporter: 1.8.2
-
-
文档级别:菜鸟级详细教程,复制粘贴即可运行
-
设计目标:支持1000台服务器稳定监控,数据保留30天,故障自动恢复
目录
-
架构规划与设计
-
服务器资源规划
-
环境准备与基础配置
-
Consul集群高可用部署
-
批量部署Consul客户端与Node Exporter
-
服务自动注册与健康检查
-
基于Consul的服务发现配置
1. 架构规划与设计
1.1 整体架构图
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Consul Server 1 │ │ Consul Server 2 │ │ Consul Server 3 │
│ (10.0.0.91) │◄───┤ (10.0.0.93) │◄───┤ (10.0.0.94) │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
│ │ │
└──────────────────────┼──────────────────────┘
│
┌───────────────┼───────────────┐
│ │ │
┌───────────▼───┐ ┌───────▼─────┐ ┌─────▼─────────┐
│ Consul Client │ │ Consul Client│ │ Consul Client │
│ + Node Exporter│ │ + Node Exporter││ + Node Exporter │
│ (10.0.0.1-255)│ │ (10.0.0.2-255)│ │ (10.0.0.3-255)│
└───────────────┘ └─────────────┘ └─────────────┘
│ │ │
└───────────────┼───────────────┘
│
┌───────────▼───────────┐
│ Prometheus Master │
│ (10.0.0.95) │
└───────────┬───────────┘
│
┌───────────▼───────────┐
│ Prometheus Slave │
│ (10.0.0.96) │
└───────────┬───────────┘
│
┌───────────▼───────────┐
│ Grafana │
│ (10.0.0.97) │
└───────────────────────┘
1.2 设计原则
-
高可用优先:所有核心组件无单点故障
-
水平扩展:支持从1000台平滑扩展到10000台
-
自动化:服务注册、发现、注销全自动化
-
性能可控:单台Prometheus最大支持2000台服务器监控
-
运维友好:所有组件均为systemd管理,日志统一收集
1.3 为什么选择Consul服务发现
-
原生支持健康检查,自动剔除故障节点
-
支持服务元数据标签,便于Prometheus过滤和分组
-
轻量级,单Client节点内存占用<100MB
-
支持HTTP/DNS两种查询方式,生态完善
-
成熟稳定,在大规模生产环境广泛验证
2. 服务器资源规划
2.1 核心组件资源配置
| 组件 | 数量 | CPU | 内存 | 磁盘 | 网络 | 说明 |
| Consul Server | 3 | 4核 | 8GB | 100GB SSD | 千兆 | 必须是奇数,3节点支持挂1个 |
| Prometheus Master | 1 | 16核 | 64GB | 2TB SSD | 万兆 | 1000台服务器推荐配置 |
| Prometheus Slave | 1 | 16核 | 64GB | 2TB SSD | 万兆 | 主备模式,故障自动切换 |
| Grafana | 1 | 4核 | 8GB | 100GB SSD | 千兆 | 单独部署避免资源争抢 |
| 合计 | 6 | 48核 | 152GB | 4.5TB SSD | - | 不包含业务服务器 |
2.2 业务服务器资源消耗
-
Consul Client: 0.5核CPU,100MB内存
-
Node Exporter: 0.1核CPU,50MB内存
-
总计:每台业务服务器额外消耗<0.6核CPU,150MB内存
-
对1000台服务器的总资源消耗:600核CPU,150GB内存(分布式,无集中压力)
3. 环境准备与基础配置
3.1 所有服务器统一基础配置
# 更新系统
apt update && apt upgrade -y
# 安装基础工具
apt install -y wget curl vim unzip net-tools telnet dnsutils chrony
# 关闭防火墙(生产环境建议只开放必要端口)
systemctl stop ufw
systemctl disable ufw
# 关闭Swap(必须关闭,否则Prometheus和Consul性能会严重下降)
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab
# 设置时区
timedatectl set-timezone Asia/Shanghai
# 配置NTP时间同步
systemctl enable --now chronyd
chronyc tracking
# 优化内核参数
cat >> /etc/sysctl.conf << EOF
# 网络优化
net.core.somaxconn=65535
net.ipv4.ip_local_port_range=1024 65535
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_keepalive_time=120
net.ipv4.tcp_keepalive_probes=3
net.ipv4.tcp_keepalive_intvl=15
# 文件描述符限制
fs.file-max=655360
vm.max_map_count=262144
EOF
sysctl -p
# 优化文件描述符限制
cat >> /etc/security/limits.conf << EOF
* soft nofile 655360
* hard nofile 655360
root soft nofile 655360
root hard nofile 655360
EOF
# 创建统一的应用目录
mkdir -p /data/consul
3.2 主机名与DNS解析
# 在所有服务器的/etc/hosts中添加
cat >> /etc/hosts << EOF
10.0.0.91 consul-01
10.0.0.93 consul-02
10.0.0.94 consul-03
10.0.0.95 prometheus-master
10.0.0.96 prometheus-slave
10.0.0.97 grafana
EOF
4. Consul集群高可用部署
4.1 Consul二进制安装(所有Server节点执行)
# 下载Consul 1.20.0 LTS
cd /data
wget https://releases.hashicorp.com/consul/1.20.0/consul_1.20.0_linux_amd64.zip
unzip consul_1.20.0_linux_amd64.zip
mv consul /usr/local/bin/
consul --version
# 创建consul用户
useradd -M -s /sbin/nologin consul
chown -R consul:consul /data/consul
4.2 Consul Server配置文件
sudo tee /data/consul/consul.hcl > /dev/null << 'EOF'
# 数据中心名称,同一集群保持一致
datacenter = "dc1"
# 数据存储目录
data_dir = "/data/consul/data"
# 日志级别(可选 trace, debug, info, warn, error)
log_level = "INFO"
server = true
# 集群期望的 server 节点数量,3节点集群设为 3
bootstrap_expect = 3
node_name = "consul1" #每个节点修改为对应主机名
# 绑定内网 IP(用于集群内部通信)
bind_addr = "10.0.0.71"
# 监听所有网络接口(用于 API 访问)
client_addr = "0.0.0.0"
# 启用 Web UI
ui = true
# 集群自动加入成员列表(填写所有 server 的 IP 和端口 8301)
retry_join = ["10.0.0.71:8301", "10.0.0.72:8301", "10.0.0.73:8301"]
# 性能优化(生产推荐)
performance = {
raft_multiplier = 1
}
# 端口配置
ports = {
dns = 8600 # DNS 接口
http = 8500 # HTTP API
https = -1 # 禁用 HTTPS(如需启用需配置证书)
grpc = -1
serf_lan = 8301 # LAN 内 gossip 通信
serf_wan = 8302 # WAN 跨数据中心 gossip
server = 8300 # RPC 通信
}
EOF
4.3 创建systemd服务文件
cat > /etc/systemd/system/consul.service << EOF
[Unit]
Description=Consul Service Discovery Agent
Documentation=https://www.consul.io/
After=network-online.target
Wants=network-online.target
[Service]
User=consul
Group=consul
Type=simple
ExecStart=/usr/local/bin/consul agent -config-file=/data/consul/consul.hcl
ExecReload=/bin/kill -HUP \$MAINPID
Restart=on-failure
RestartSec=5
LimitNOFILE=655360
[Install]
WantedBy=multi-user.target
EOF
4.4 启动Consul集群
# 在三个节点上依次执行
systemctl daemon-reload
systemctl enable --now consul
# 检查集群状态
consul members
consul operator raft list-peers
# 访问UI: http://10.0.0.71:8500
5. 批量部署Consul客户端与Node Exporter
5.1 Ansible批量部署准备
在控制节点(10.0.0.71)执行
# 安装Ansible
apt install -y ansible
# 创建主机清单
cat > /etc/ansible/hosts << EOF
[consul_clients]
10.0.0.[1:255]
[consul_clients:vars]
ansible_user=root
ansible_ssh_pass=your_root_password
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
EOF
5.2 创建Ansible Playbook
cat > deploy_consul_client.yml << EOF
- name: Deploy Consul Client and Node Exporter
hosts: consul_clients
gather_facts: yes
tasks:
- name: Create directories
file:
path: "{{ item }}"
state: directory
mode: '0755'
loop:
- /data/consul
- /data/node_exporter
- name: Download Consul binary
get_url:
url: https://releases.hashicorp.com/consul/1.20.0/consul_1.20.0_linux_amd64.zip
dest: /tmp/consul.zip
mode: '0644'
- name: Unzip Consul
unarchive:
src: /tmp/consul.zip
dest: /usr/local/bin/
remote_src: yes
creates: /usr/local/bin/consul
- name: Create consul user
user:
name: consul
shell: /sbin/nologin
create_home: no
state: present
- name: Set permissions
file:
path: "{{ item }}"
owner: consul
group: consul
recurse: yes
loop:
- /data/consul
- /data/consul/data
- name: Generate Consul client config
copy:
content: |
datacenter = "dc1"
data_dir = "/data/consul/data"
bind_addr = "{{ ansible_default_ipv4.address }}"
client_addr = "127.0.0.1"
advertise_addr = "{{ ansible_default_ipv4.address }}"
server = false
retry_join = ["10.0.0.71", "10.0.0.72", "10.0.0.73"]
log_level = "WARN"
enable_syslog = true
leave_on_terminate = true
rejoin_after_leave = true
dest: /data/consul/consul.hcl
mode: '0644'
- name: Create Consul systemd service
copy:
content: |
[Unit]
Description=Consul Client Agent
After=network-online.target
Wants=network-online.target
[Service]
User=consul
Group=consul
Type=simple
ExecStart=/usr/local/bin/consul agent -config-file=/data/consul/consul.hcl
ExecReload=/bin/kill -HUP \$MAINPID
Restart=on-failure
RestartSec=5
LimitNOFILE=655360
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/consul.service
mode: '0644'
- name: Start and enable Consul
systemd:
name: consul
daemon_reload: yes
state: started
enabled: yes
- name: Download Node Exporter
get_url:
url: https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz
dest: /tmp/node_exporter.tar.gz
mode: '0644'
- name: Unzip Node Exporter
unarchive:
src: /tmp/node_exporter.tar.gz
dest: /data/node_exporter/
remote_src: yes
extra_opts: [--strip-components=1]
creates: /data/node_exporter/node_exporter
- name: Create node_exporter user
user:
name: node_exporter
shell: /sbin/nologin
create_home: no
state: present
- name: Create Node Exporter systemd service
copy:
content: |
[Unit]
Description=Prometheus Node Exporter
After=network-online.target
[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/data/node_exporter/node_exporter \
--web.listen-address=:9100 \
--collector.systemd \
--collector.processes \
--collector.filesystem.ignored-mount-points="^/(sys|proc|dev|run)($|/)"
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/node_exporter.service
mode: '0644'
- name: Start and enable Node Exporter
systemd:
name: node_exporter
daemon_reload: yes
state: started
enabled: yes
- name: Create Node Exporter service registration file
copy:
content: |
{
"service": {
"id": "node_exporter-{{ ansible_default_ipv4.address }}",
"name": "node_exporter",
"address": "{{ ansible_default_ipv4.address }}",
"port": 9100,
"tags": ["node", "linux"],
"checks": [
{
"http": "http://{{ ansible_default_ipv4.address }}:9100/metrics",
"interval": "10s",
"timeout": "5s"
}
]
}
}
dest: /opt/consul/node_exporter.json
mode: '0644'
- name: Reload Consul to register service
systemd:
name: consul
state: reloaded
EOF
5.3 执行批量部署
# 先测试连接
ansible consul_clients -m ping
# 执行部署(分批执行,避免网络拥塞)
ansible-playbook deploy_consul_client.yml --forks=50
# 验证部署结果
consul catalog services | grep node_exporter
consul catalog nodes | wc -l # 应该显示1003个节点(3个Server+1000个Client)
6. 服务自动注册与健康检查
6.1 服务注册原理
-
每个Consul Client本地维护一个服务注册目录
/opt/consul/ -
以
.json结尾的文件会被Consul自动加载 -
服务注册包含:服务ID、名称、地址、端口、标签、健康检查
-
健康检查失败的服务会被自动标记为不健康,Prometheus会自动停止抓取
6.2 服务注销机制
# 手动注销单个服务
consul services deregister node_exporter-10.0.0.1
# 批量注销不健康的服务
curl -s http://10.0.0.71:8500/v1/health/state/critical | jq -r '.[].ServiceID' | xargs -I {} consul services deregister {}
6.3 自动注销故障节点
# 创建自动清理脚本
cat > /usr/local/bin/cleanup_consul_services.sh << EOF
#!/bin/bash
# 自动注销超过24小时不健康的服务
CONSUL_ADDR="http://10.0.0.91:8500"
CRITICAL_THRESHOLD=86400 # 24小时,单位秒
# 获取所有临界状态的服务
CRITICAL_SERVICES=$(curl -s \$CONSUL_ADDR/v1/health/state/critical)
# 遍历并注销超时的服务
echo "\$CRITICAL_SERVICES" | jq -c '.[]' | while read -r service; do
SERVICE_ID=$(echo "\$service" | jq -r '.ServiceID')
NODE=$(echo "\$service" | jq -r '.Node')
CHECK_ID=$(echo "\$service" | jq -r '.CheckID')
# 获取最后一次检查时间
LAST_CHECK=$(curl -s "\$CONSUL_ADDR/v1/health/node/\$NODE" | jq -r ".[] | select(.CheckID == \"\$CHECK_ID\") | .Output" | grep -oP 'Last checked: \K[0-9-:.TZ]+')
if [ -n "\$LAST_CHECK" ]; then
# 转换为时间戳
LAST_CHECK_TS=$(date -d "\$LAST_CHECK" +%s 2>/dev/null)
CURRENT_TS=$(date +%s)
DIFF=\$((CURRENT_TS - LAST_CHECK_TS))
if [ \$DIFF -gt \$CRITICAL_THRESHOLD ]; then
echo "注销超时服务: \$SERVICE_ID (最后检查: \$LAST_CHECK, 超时: \$DIFF秒)"
curl -X PUT "\$CONSUL_ADDR/v1/agent/service/deregister/\$SERVICE_ID"
fi
fi
done
EOF
# 设置定时任务
chmod +x /usr/local/bin/cleanup_consul_services.sh
echo "0 3 * * * root /usr/local/bin/cleanup_consul_services.sh >> /var/log/consul_cleanup.log 2>&1" >> /etc/crontab
7. 基于Consul的服务发现配置
7.1 服务发现工作流程
-
Prometheus定期(默认30s)查询Consul的服务目录
-
Consul返回所有健康的服务实例
-
Prometheus根据relabel_configs过滤和重命名标签
-
Prometheus自动添加/删除抓取目标
-
整个过程无需重启Prometheus
7.2 高级服务发现配置
scrape_configs:
- job_name: 'consul-services'
consul_sd_configs:
- server: '10.0.0.71:8500'
datacenter: 'dc1'
refresh_interval: 30s
token: '' # 如果Consul启用了ACL
scheme: 'http'
services: []
tags: []
node_meta: {}
service_meta: {}
allow_stale: true # 允许从非Leader节点查询,提高性能
limit: 0
relabel_configs:
# 保留指定服务
- source_labels: [__meta_consul_service]
regex: (node_exporter|mysql_exporter|redis_exporter)
action: keep
# 排除不健康的服务
- source_labels: [__meta_consul_health]
regex: passing
action: keep
# 自定义标签
- source_labels: [__meta_consul_service]
target_label: job
- source_labels: [__meta_consul_node]
target_label: instance
- source_labels: [__meta_consul_datacenter]
target_label: datacenter
# 重写抓取地址
- source_labels: [__meta_consul_service_address, __meta_consul_service_port]
separator: ':'
target_label: __address__
7.3 验证服务发现
# 查看Prometheus发现的目标
curl -s http://10.0.0.42:9090/api/v1/targets | jq '.data.activeTargets | length'
# 应该显示1004个目标(1个prometheus+3个consul+1000个node_exporter)
# 查看Consul中的服务数量
curl -s http://10.0.0.71:8500/v1/catalog/service/node_exporter | jq '. | length'

浙公网安备 33010602011771号