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天,故障自动恢复

目录

  1. 架构规划与设计

  2. 服务器资源规划

  3. 环境准备与基础配置

  4. Consul集群高可用部署

  5. 批量部署Consul客户端与Node Exporter

  6. 服务自动注册与健康检查

  7. 基于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 设计原则

  1. 高可用优先:所有核心组件无单点故障

  2. 水平扩展:支持从1000台平滑扩展到10000台

  3. 自动化:服务注册、发现、注销全自动化

  4. 性能可控:单台Prometheus最大支持2000台服务器监控

  5. 运维友好:所有组件均为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 服务发现工作流程

  1. Prometheus定期(默认30s)查询Consul的服务目录

  2. Consul返回所有健康的服务实例

  3. Prometheus根据relabel_configs过滤和重命名标签

  4. Prometheus自动添加/删除抓取目标

  5. 整个过程无需重启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'
posted @ 2026-06-08 23:10  kyle_7Qc  阅读(5)  评论(0)    收藏  举报