服务发现中间件ConSul的操作指南

1.ConSul的基本概念

Consul 是一个由 HashiCorp 公司开发的开源工具,用于实现服务发现、 配置管理 和服务网格功能。它是现代分布式系统的核心基础设施组件,以下是其核心特性和工作原理的全面解析:

1.1 核心功能

  1. 服务发现(Service Discovery)

    1. 自动注册和发现服务(如Kubernetes中的服务)

    2. 示例:前端服务自动发现后端API的IP和端口

  2. 健康检查( Health Checking)

    1. 主动监控服务状态(HTTP/TCP/脚本检查)

    2. 自动从服务目录中移除不健康节点

  3. 键值存储 KV Store)

    1. 分布式键值数据库(类似ZooKeeper/etcd)

    2. 用于动态配置和特征开关

  4. 多数据中心支持

    1. 原生支持跨地域的集群联动

    2. 通过WAN Gossip协议实现

  5. 服务网格(Service Mesh)

    1. 通过内置代理(Connect)实现mTLS加密通信

    2. 支持L7流量管理(如HTTP路由)

1.2 架构组成

|--------|----------------------------|
| 组件 | 作用 |
| Server | 维护集群状态,处理写操作(Raft共识算法) |
| Client | 轻量级代理,转发请求到Server,维护本地缓存 |
| Agent | 每个节点运行的服务,处理健康检查和服务注册 |
| Gossip | 基于SWIM协议的自愈型通信层(UDP端口8301) |

1.3 关键协议

Raft协议

  • 用于Server间的领导选举和数据一致性

  • 典型部署:3或5个Server节点避免脑裂

Gossip协议

  • 随机节点间传播状态信息(感染扩散模型)

  • 两种类型:

    • LAN Gossip:同一数据中心通信

    • WAN Gossip:跨数据中心通信

HTTP/ DNS 接口

  • 默认端口:8500(HTTP)、8600(DNS)

  • 支持多种服务发现方式:

  • dig @127.0.0.1 -p 8600 web.service.consul SRV

1.4 工作流程示例(服务注册)

1.5 同类技术对比

|-------|--------------|-----------|--------------|----------|
| 特性 | Consul | etcd | ZooKeeper | Eureka |
| 服务发现 | ✅ 内置DNS/HTTP | ❌ 需配合其他组件 | ❌ 需配合其他组件 | ✅ 专为发现设计 |
| 健康检查 | ✅ 多类型支持 | ❌ 基本心跳 | ❌ 基本心跳 | ✅ 客户端上报 |
| 配置管理 | ✅ 强一致性KV | ✅ 强一致性KV | ✅ 强一致性ZKNode | ❌ 不支持 |
| 多数据中心 | ✅ 原生支持 | ❌ 需自定义 | ❌ 需自定义 | ❌ 需二次开发 |
| 服务网格 | ✅ 内置Connect | ❌ 不支持 | ❌ 不支持 | ❌ 不支持 |

1.6 典型应用场景

Consul有大量应用场景,但是在本文档中主要讲解与Prometheus进行配合应用. 通过ConSul的服务发现来动态调整监控内容,极大的提高了运维效率

2.ConSul的基本部署

2.1 安装部署

官方文档: https://developer.hashicorp.com/consul/install

2.1.1 软件源安装
bash 复制代码
# wget -O - https://apt.releases.hashicorp.com/gpg | gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
# echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/hashicorp.list
# apt update && apt install consul
2.1.2 二进制安装
bash 复制代码
# wget https://releases.hashicorp.com/consul/1.16.1/consul_1.16.1_linux_amd64.zip
# unzip consul_1.16.1_linux_amd64.zip
# mv consul /usr/local/bin/
# consul version
2.1.3 Docker安装
bash 复制代码
# vim docker-compose.yml
version: '3.8'

services:
  consul:
    container_name: consul_server
    image: consul:1.15
    volumes:
      - ./consul/data:/consul/data
      - ./consul/config.json:/consul/config/config.json
    ports:
      - "8500:8500"
    networks:
      - app_network
    restart: always

networks:
  app_network:
    driver: bridge
# docker-compose up -d

由于Docker较好管理和配置, 且与服务器相对环境隔离. 所以下文所有配置都使用Docker进行演示

2.2 注册示例服务

bash 复制代码
# vim service.json
{
  "ID": "web1",
  "Name": "web",
  "Port": 80,
  "Check": {
    "HTTP": "http://localhost:80/health",
    "Interval": "10s"
  }
}
# curl --request PUT --data @service.json http://localhost:8500/v1/agent/service/register
# 查询服务
# curl http://localhost:8500/v1/catalog/service/web

2.3 ConSul工作原理

Consul 的工作原理是一个典型的分布式系统设计,融合了多种协议和机制来实现服务发现、健康监测和配置管理。以下是其核心工作原理的深度解析

2.3.1 核心架构组成

1.Agent(代理)

  • 每个节点(物理机/容器)运行的守护进程

  • 两种模式(可以看下面的Prometheus接入Consul的系统架构图)

    • Clent: 轻量级代理, 转发请求到Server(无状态)

    • Server: 参数Raft选举, 存储集群状态(有状态)

2.数据中心(Datacenter)

  • 通过WAN Gossip互联的独立集群

  • 典型部署: 每个物理数据中心部署一个Consul集群

3.服务抽象

2.3.2 核心工作机制

1.服务注册与发现

流程:

关键点:

  • 注册方式:

    • 静态配置:通过配置文件注册

    • 动态 API/v1/agent/service/register

    • Sidecar自动注册(如K8s Pod)

  • 发现接口:

    • HTTP API:/v1/catalog/service/<name>

    • DNS查询:web.service.consul → SRV记录

2.检查检查机制

检查类型:

|--------|----------|------------------|
| 类型 | 协议 | 示例 |
| Script | 本地脚本 | check.sh返回退出码0/1 |
| HTTP | HTTP GET | 检查/health返回200 |
| TCP | 端口探测 | 验证6379端口是否开放 |
| TTL | 心跳上报 | 服务主动续期(类似租约) |

故障处理流程:

  1. Agent检测到服务异常

  2. 通过Gossip协议广播状态

  3. Server更新目录并标记服务为critical

  4. 从DNS/API结果中过滤掉故障节点

还有其他高级工作机制. 但是作为入门暂时只需要知道这些简单工作原理即可

3.Prometheus接入ConSul

3.1 系统架构图

3.1.1 架构关键组件说明

服务注册层(绿色节点)

  • Service 1..N: 业务服务实例

  • 通过ConSul Agent API 自动注册

    bash 复制代码
    # curl -X PUT -d @service.json http://localhost:8500/v1/agent/service/register

Consul基础设施层(蓝色/橙色节点)

  • Consul Clent: 每个节点运行的轻量级代理

    • 默认端口: 8500(HTTP), 8600(DNS)
  • Consul Server: 3-5个节点组成的Raft集群

    • 数据同步流程

Prometheus监控层(红色节点)

  • 核心配置

    bash 复制代码
    // prometheus.yml
    scrape_configs:
      - job_name: 'consul-services'
        consul_sd_configs:
          - server: 'consul-server:8500'
            token: '{{CONSUL_TOKEN}}'
            services: ['web', 'api'] # 可选服务过滤
        relabel_configs:
          - source_labels: [__meta_consul_tags]
            regex: ',(production|canary),'
            action: keep
3.1.2 数据流动时序
3.1.3 关键配置要点

Consul侧准备

bash 复制代码
# 创建Prometheus 专用ACL策略 --- 后续会专门讲解如何配置
consul acl policy create -name prometheus -rules @-
<<EOF
agent_prefix "" { policy = "read" }
node_prefix "" { policy = "read" }
service_prefix "" { policy = "read" }
EOF

Prometheus服务发现规则

  • 元数据标签示例:

|----------------------------|--------|
| 标签名称 | 示例值 |
| __meta_consul_service | redis |
| __meta_consul_node | node-1 |
| __meta_consul_service_port | 6379 |
| __meta_consul_dc | dc1 |

TLS 加密配置(后续有专门章节讲解如何配置)

bash 复制代码
consul_sd_configs:
server: 'consul-server:8501'
scheme: https
tls_config:
  ca_file: /ssl/consul-ca.pem
  cert_file: /ssl/prometheus.crt
  key_file: /ssl/prometheus.key

3.2 实践操作

当前线上部署了两个监控服务:

  • a 服务:运行在 6061 端口,服务名为 a_service

  • b 服务:运行在 6062 端口,服务名为 b_service

这两个服务的指标采集都需要通过 HTTP Header 携带鉴权信息 METRIC-KEY: avcscbgb。但由于 Prometheus 不支持直接在 scrape_configs 中设置自定义请求头(headers),因此无法直接完成鉴权

为解决此问题,采用 Nginx 反向代理的方式,在 Nginx 层面统一添加鉴权 Header,并限制仅允许 Prometheus 服务器访问监控接口,其他 IP 访问将返回 403 错误

Nginx配置可以参考以下配置

bash 复制代码
server {
    listen 8080;
    # 限制访问 IP
    allow <Prometheus_IP>;  # 允许的 IP 地址, 主要是Prometheus服务器
    deny all;             # 拒绝其他所有 IP

    location /metrics {
        proxy_pass http://127.0.0.1:6061/metrics;
        proxy_set_header METRIC-KEY "avcscbgb";
    }
    location /b/metrics {
        proxy_pass http://127.0.0.1:6062/metrics;
        proxy_set_header METRIC-KEY "avcscbgb";
    }
    access_log /data/log/nginx/access.log;
}

此外,由于 Consul 注册的服务端口为 60616062,需要在 Prometheus 配置中使用 relabel_configs 将其映射到 Nginx 的统一入口端口(例如 8081)并转发至对应的路径 /metrics/b/metrics

prometheus配置如下:

bash 复制代码
 ** 本配置文件的注释只是为了方便理解配置文件的内容, 真正上线了时候需要把注释注释掉, 避免因为格式问题导致无法解析 **
# 全局配置
global:
  scrape_interval: 15s # 每15秒抓取一次指标
  evaluation_interval: 15s # 每15秒评估告警规则

# 抓取任务列表
scrape_configs:
  - job_name: "b" # 第一个任务: 监控b服务
    scheme: http # 抓取协议: http
    
    consul_sd_configs:
      - server: "<Consul_ip:port>" # Consul服务器地址
        services: ["relay"] # 只发现relay服务
        # 每15秒查询Consul的/v1/catalog/service/b接口, 自动获取所有健康示例的IP:Port列表
    relabel_configs:
      # 对于6062端口的服务,修改metrics路径为/b/metrics,并且将端口改为8080
      - source_labels: [__address__, __meta_consul_service_port]
        separator: ;
        regex: ([^:]+)(?::(\d+))?;6062$ # 匹配IP:6062样式
        target_label: __address__
        replacement: $1:8080 # 替换端口为8080
        action: replace
      - source_labels: [__meta_consul_service_port]
        regex: 6062$
        target_label: __metrics_path__
        replacement: /b/metrics # 修改指标路径
        action: replace
        
  - job_name: "a" # 第二个任务: 监控a任务
    scheme: http
    consul_sd_configs:
      - server: "<Consul_ip:port>"
        services: ["a"]
    relabel_configs:
      # 对于6061端口的服务,修改metrics路径为/metrics,并且将端口改为8080
      - source_labels: [__address__, __meta_consul_service_port]
        separator: ;
        regex: ([^:]+)(?::(\d+))?;6061$
        target_label: __address__
        replacement: $1:8080
        action: replace
      - source_labels: [__meta_consul_service_port]
        regex: 6061$
        target_label: __metrics_path__
        replacement: /metrics
        action: replace

配置好相关配置文件, 重载Prometheus服务

bash 复制代码
配置好相关配置文件, 重载Prometheus服务
# curl -X POST http://36.151.192.231:9090/-/reload
# 这里不要直接重启Prometheus, 避免配置文件写错了导致Prometheus宕机
# 访问: http://PrometheusIP地址:9090/targets

3.3 监控ConSul自身

可以修改Prometheus的编辑文件进行采集, 也可以使用categraf采集ConSul信息让Prometheus监控. 为了方便, 这里就直接使用夜莺的categraf进行采集信息

bash 复制代码
# vim /opt/categraf/conf/input.consul/consul.toml
# # collect interval
interval = 15 # 采集频率

[[instances]]
  ## Consul server address
  address = "localhost:8500"

  ## URI scheme for the Consul server, one of "http", "https"
  scheme = "http"

  ## ACL token used in every request
  # token = ""

  ## HTTP Basic Authentication username and password.
  # username = ""
  # password = ""

  ## Data center to query the health checks from
  # datacenter = ""

  ## Allows any Consul server (non-leader) to service a read.
  ## Default is true
  # allow_stale = true

  ## Forces the read to be fully consistent.
  ## Default is false
  # require_consistent = false

  ## Prefix from which to expose key/value pairs.
  # kv_prefix = ""

  ## Regex that determines which keys to expose.
  ## Default is ".*"
  # kv_filter = ".*"

  ## Optional TLS Config
  # tls_ca = "/etc/categraf/ca.pem"
  # tls_cert = "/etc/categraf/cert.pem"
  # tls_key = "/etc/categraf/key.pem"
  ## Use TLS but skip chain & host verification
  # insecure_skip_verify = true
# systemctl restart categraf.service
3.3.1 配置文件配置项说明

核心配置项

  • interval = 15

    • 作用 :采集频率为每 15 秒 一次。

    • 意义:定期从 Consul 收集监控数据。

  • [[instances]]

    • 作用:定义一个监控实例(即需要监控的 Consul 服务)。

Consul 连接配置

  • address = "localhost:8500"

    • 作用:指定 Consul 服务器的地址和端口。**

    • 默认值 :本地 Consul(8500 为默认 HTTP API 端口)。

  • scheme = "http"

    • 作用 :使用 HTTP 协议(未启用 HTTPS)。**

    • 生产建议 :若需加密通信,应改为 https

  • token username password

    • 状态:被注释,表示未启用认证。**

    • 用途:若 Consul 启用 ACL 或 HTTP 认证,需填写对应凭证。


数据查询参数

  • datacenter

    • 状态:未指定,默认采集当前数据中心的数据
  • allow_stale = true

    • 作用:允许从非 Leader 节点读取数据(提高可用性,但可能读到旧数据)
  • require_consistent = false

    • 作用:不强制要求强一致性读取(降低延迟,但数据可能不一致)

键值存储(KV)监控

  • kv_prefixkv_filter

    • 作用:监控 Consul KV 存储中的键值对。
  • 示例:

    • kv_prefix = "app/config":仅监控该前缀下的键。

    • kv_filter = ".*"(默认):监控所有键值。


TLS 安全配置

  • tls_ca tls_cert tls_key

    • 状态:被注释,表示未启用 TLS 加密。

    • 用途:若需 HTTPS 安全连接,需配置证书路径。

  • insecure_skip_verify = true

    • *作用**:跳过 TLS 证书校验(仅测试环境建议启用)。

适用场景

  • 测试环境:当前配置适合本地开发或测试(HTTP + 无认证)。

  • 生产调整:

    • 启用 scheme = "https" 和 TLS 证书。

    • 配置 tokenusername/password 认证。

    • 按需设置 kv_prefix 过滤关键配置。


监控数据类型

  • 默认采集:Consul 节点健康状态、服务检查、Leader 选举信息等。

  • KV 数据 :若启用 kv_prefix,会额外收集键值存储的元数据(如修改时间、版本)。

通过此配置,采集器可定期获取 Consul 的运行状态,帮助运维人员监控集群健康度和配置信息

3.3.2 相关监控项查询

1.API HTTP请求性能

这些指标反映 Consul 的 HTTP API 接口性能,用于监控 API 的调用情况:

bash 复制代码
# consul_api_http_count --> HTTP API 请求总次数(请求频率)
# consul_api_http_max --> 单次 HTTP 请求的最大耗时(单位通常为毫秒)
# consul_api_http_mean --> HTTP请求的平均耗时
# consul_api_http_min --> 单次HTTP 请求的最小耗时(单位通常为毫秒)
# consul_api_http_stdev --> 请求耗时的标准差(反映请求耗时的波动性,值越大越不稳定)
# consul_api_http_sum --> 所有 HTTP 请求的耗时总和

2.自动导航(Autopilot)健康状态

Consul 的 Autopilot 模块负责集群自动化管理,以下指标监控其健康状态:

bash 复制代码
# consul_autopilot_failure_tolerance --> 集群可容忍的最大节点故障数量(反映集群容错能力)
# consul_autopilot_healthy --> 集群整体健康状态(1 表示健康,0 表示异常)

3. CA 证书缓存性能

Consul 的 Connect 功能(服务网格)依赖 CA 证书,这些指标监控证书缓存效率:

叶证书(Leaf Certificates)

bash 复制代码
# consul_cache_connect_ca_leaf_fetch_success_count # 成功获取叶证书的次数
# consul_cache_connect_ca_leaf_fetch_success_max # 单次获取叶证书的最大耗时
# consul_cache_connect_ca_leaf_fetch_success_mean # 获取叶证书的平均耗时
# consul_cache_connect_ca_leaf_fetch_success_stdev # 获取耗时的标准差
# consul_cache_connect_ca_leaf_fetch_success_sum # 所有获取操作的总耗时

根证书(Root Certificates)

bash 复制代码
# consul_cache_connect_ca_root_hit_count       --> 根证书缓存命中次数(命中率越高,缓存越有效)
# consul_cache_connect_ca_root_hit_max         --> 单次根证书缓存命中的最大耗时
# consul_cache_connect_ca_root_hit_mean         --> 根证书缓存命中的平均耗时
# consul_cache_connect_ca_root_hit_min         --> 单次根证书缓存命中的最小耗时
# consul_cache_connect_ca_root_hit_stdev       --> 命中耗时的标准差
# consul_cache_connect_ca_root_hit_sum         --> 所有命中操作的总耗时

# consul_cache_connect_ca_root_miss_block_count  --> 根证书缓存未命中导致的阻塞次数
# consul_cache_connect_ca_root_miss_block_max    --> 单次未命中阻塞的最大耗时
# consul_cache_connect_ca_root_miss_block_mean   --> 未命中阻塞的平均耗时
# consul_cache_connect_ca_root_miss_block_min    --> 单次未命中阻塞的最小耗时
# consul_cache_connect_ca_root_miss_block_stdev  --> 未命中阻塞耗时的标准差
# consul_cache_connect_ca_root_miss_block_sum    --> 所有未命中阻塞的总耗时

# consul_cache_connect_ca_root_fetch_success_count --> 根证书成功获取次数(缓存未命中时从源头获取)
# consul_cache_connect_ca_root_fetch_success_max   --> 单次根证书获取的最大耗时
# consul_cache_connect_ca_root_fetch_success_mean  --> 根证书获取的平均耗时
# consul_cache_connect_ca_root_fetch_success_min   --> 单次根证书获取的最小耗时
# consul_cache_connect_ca_root_fetch_success_stdev --> 获取耗时的标准差
# consul_cache_connect_ca_root_fetch_success_sum   --> 所有根证书获取操作的总耗时

缓存通用指标

bash 复制代码
# consul_cache_entries_count     --> 当前缓存中的条目总数
# consul_cache_fetch_success_count --> 缓存获取操作的总成功次数(通用)
# consul_cache_fetch_success_max   --> 单次缓存获取的最大耗时
# consul_cache_fetch_success_min   --> 单次缓存获取的最小耗时
# consul_cache_fetch_success_stdev --> 缓存获取耗时的标准差
# consul_cache_fetch_success_sum   --> 所有缓存获取操作的总耗时

4.客户端API目录节点统计

监控 Consul 目录(Catalog)中注册的节点数量和健康状态:

bash 复制代码
# consul_client_api_catalog_nodes_count   --> 当前注册的节点总数
# consul_client_api_catalog_nodes_max     --> 节点相关操作(如健康检查)的最大耗时
# consul_client_api_catalog_nodes_mean    --> 节点操作的平均耗时
# consul_client_api_catalog_nodes_min     --> 节点操作的最小耗时
# consul_client_api_catalog_nodes_stddev  --> 节点操作耗时的波动性

5.客户端 API 目录服务统计

监控 Consul 目录中注册的服务数量和性能:

bash 复制代码
# consul_client_api_catalog_services_count    --> 当前注册的服务总数
# consul_client_api_catalog_services_max      --> 服务相关操作(如注册、发现)的最大耗时
# consul_client_api_catalog_services_mean     --> 服务操作的平均耗时
# consul_client_api_catalog_services_min      --> 服务操作的最小耗时
# consul_client_api_catalog_services_stddev   --> 服务操作耗时的波动性

6.服务端状态监控

bash 复制代码
# consul_up --> 运行的consul中间件(这里仅针对接入了监控的consul服务器, 后续可根据这个做相关告警)

以上只描述了部分的监控指标. 其实Categraf内置了很多监控指标项. 后续有需要可以自行google

4.ConSul的ACL系统

4.1 ACL系统概述

Consul的ACL(Access Control List, 访问控制列表) 系统用于控制对Consul资源的访问. 它提供了一种灵活的方法来管理安全性和权限, 确保只有授权用户和节点可以执行特定的操作或访问特定的数据. 以下是Consul ACL 系统的概述:

4.1.1 核心概念
  • Token(令牌): 在Consul中,ACL是通过令牌来实现的。每个令牌都有一个关联的策略,定义了该令牌允许执行哪些操作

  • Policy(策略): 策略是一组规则,它们定义了与之关联的令牌可以访问哪些资源以及如何访问这些资源

  • Roles(角色):为了简化策略管理,Consul允许创建角色,角色可以包含一个或多个策略,然后将这些角色分配给令牌

  • Namespaces(命名空间):在企业版中,支持多租户环境下的资源隔离,通过命名空间来实现不同租户之间的资源划分

4.1.2 功能特性
  1. 分层结构:Consul的ACL系统支持分层策略,这使得管理员能够为不同的团队或应用程序设置细粒度的访问控制

  2. 默认拒绝:除非明确授予访问权限,否则Consul中的所有资源都是不可访问的。这种"默认拒绝"的方式提高了安全性

  3. 动态更新:可以在不停机的情况下添加、修改或删除策略和令牌,使得管理更加灵活

  4. 服务身份验证:除了传统的客户端认证之外,Consul还支持基于服务的身份验证,允许服务之间进行相互认证

  5. 审计日志:记录所有的ACL相关活动,有助于事后审查和问题排查

4.1.3 使用场景
  • 控制对Consul目录的访问,包括服务注册与发现

  • 限制对KV存储的读写权限

  • 管理对健康检查结果的访问

  • 实现跨服务通信的安全性保障

要启用和配置Consul的ACL系统,需要按照官方文档中的说明进行相应的设置,包括生成初始管理令牌、定义策略和令牌等步骤

4.2 ACL系统的构建

以下是在 Docker 环境中部署 Consul 并配置 ACL、以及为 Prometheus 创建只读 Token 的完整流程:

4.2.1 创建Consul的ACL认证

创建配置文件 consul/config/consul.hcl,内容如下:

bash 复制代码
# mkdir -p consul/config
# vim consul/config/consul.hcl
acl {
  enabled = true
  default_policy = "deny"
  down_policy = "extend-cache"
  enable_token_persistence = true
}
4.2.2 修改Docker启动文件
bash 复制代码
services:
  consul-server:
    image: consul:1.15
    container_name: consul-server
    ports:
      - "8500:8500"  # 映射 Consul HTTP API 和 UI 端口
    volumes:
      - ./consul/config:/etc/consul.d  # 挂载配置目录
      - ./consul/data:/consul/data
    command: >
      agent -server
      -bootstrap-expect=1
      -ui
      -bind=0.0.0.0
      -client=0.0.0.0
      -data-dir=/consul/data
      -config-dir=/etc/consul.d
    networks:
      - consul-net

networks:
  consul-net:
    driver: bridge
4.2.3 引导ACL并获取主令牌

执行ACL引导命令以生成主令牌:

bash 复制代码
[root@devops consul]# docker exec consul-server consul acl bootstrap
AccessorID:       b52650bb-eee2-d7d4-a929-3da9f96a3267
SecretID:         b680353d-85f1-b518-af28-5fd4379026d6
Description:      Bootstrap Token (Global Management)
Local:            false
Create Time:      2025-05-09 09:58:46.389350753 +0000 UTC
Policies:
   00000000-0000-0000-0000-000000000001 - global-management

记录输出的 SecretID,例如:

复制代码
b680353d-85f1-b518-af28-5fd4379026d6
4.2.4 设置Agent令牌

将主令牌设置为Agent令牌,使Consul节点拥有必要权限:

bash 复制代码
# docker exec consul-server consul acl set-agent-token agent b680353d-85f1-b518-af28-5fd4379026d6

错误原因分析

错误信息 Permission denied: anonymous token lacks permission 'agent:write' 表明:

  1. ACL 已生效 :Consul 的默认策略 (default_policy = "deny") 已阻止匿名操作

  2. 未授权操作consul acl set-agent-token 命令需要携带有效的管理令牌才能执行,但当前请求未提供令牌,导致 Consul 使用匿名令牌(无权限)

解决方案

通过环境变量传递令牌

bash 复制代码
# docker exec -e CONSUL_HTTP_TOKEN=b680353d-85f1-b518-af28-5fd4379026d6 consul-server consul acl set-agent-token agent b680353d-85f1-b518-af28-5fd4379026d6

ACL token "agent" set successfully
4.2.5 验证ACL配置

检查节点信息,确认ACL生效:

bash 复制代码
# docker exec -e CONSUL_HTTP_TOKEN=b680353d-85f1-b518-af28-5fd4379026d6 consul-server consul members
4.2.6 访问Consul UI

访问 http://localhost:8500,使用主令牌登录

4.2.7 创建Prometheus只读令牌

1.创建专属策略

创建新策略文件 consul/config/prometheus-policy.hcl,定义 Prometheus 所需的最小权限:

bash 复制代码
# vim consul/config/prometheus-policy.hcl
node_prefix "" {
  policy = "read"
}
service_prefix "" {
  policy = "read"
}
key_prefix "" {
  policy = "read"
}

权限说明

  • node_prefix:允许读取所有节点信息

  • service_prefix:允许读取所有服务注册信息

  • key_prefix:允许读取所有 KV 存储数据(如果 Prometheus 需要)

2.创建策略并生成令牌(使用主令牌)

bash 复制代码
# 创建策略
# docker exec -e CONSUL_HTTP_TOKEN=b680353d-85f1-b518-af28-5fd4379026d6 consul-server \
  consul acl policy create \
  -name "prometheus-read-only" \
  -description "Read-only policy for Prometheus monitoring" \
  -rules @/etc/consul.d/prometheus-policy.hcl
  
# 生成关联此策略的令牌
docker exec -e CONSUL_HTTP_TOKEN=b680353d-85f1-b518-af28-5fd4379026d6 consul-server \
  consul acl token create \
  -description "Prometheus Read Token" \
  -policy-name "prometheus-read-only"

记录 SecretID : 43c5fda5-a3e1-1627-3af4-ff8bf72cabc0

3.验证令牌权限

方法1: CLI验证

bash 复制代码
# 查看令牌详情(使用主令牌)
# docker exec -e CONSUL_HTTP_TOKEN=b680353d-85f1-b518-af28-5fd4379026d6 consul-server   consul acl token read -id 1ad60343-ba45-e797-830d-193d57c8edc6
Use the -accessor-id parameter to specify token by Accessor ID
AccessorID:       1ad60343-ba45-e797-830d-193d57c8edc6
SecretID:         43c5fda5-a3e1-1627-3af4-ff8bf72cabc0
Description:      Prometheus Read Token
Local:            false
Create Time:      2025-05-09 10:12:11.531743636 +0000 UTC
Policies:
   9c625973-4ea7-3972-0f9f-4a258fd4ab5b - prometheus-read-only
   
# 尝试读取服务列表(使用新令牌)
# docker exec -e CONSUL_HTTP_TOKEN=43c5fda5-a3e1-1627-3af4-ff8bf72cabc0 consul-server consul catalog services
consul

# 尝试写入操作(应失败)
# docker exec -e CONSUL_HTTP_TOKEN=43c5fda5-a3e1-1627-3af4-ff8bf72cabc0 consul-server consul kv put test/key1 "value"
Error! Failed writing data: Unexpected response code: 403 (Permission denied: token with AccessorID '1ad60343-ba45-e797-830d-193d57c8edc6' lacks permission 'key:write' on "test/key1") ---> 预期错误

方法二:API 验证

bash 复制代码
# 读取节点信息(替换 YOUR_TOKEN)
curl -s -H "X-Consul-Token: 43c5fda5-a3e1-1627-3af4-ff8bf72cabc0" http://localhost:8500/v1/catalog/nodes | jq
bash 复制代码
# 测试写操作
curl -s -X PUT -H "X-Consul-Token: 7a1253ef-8d1e-4b2a-9e34-56789abcdef0" -d '{"value": "test"}' http://localhost:8500/v1/kv/test/key1

4.配置 Prometheus 使用令牌(示例)

在 Prometheus 的 consul_sd_config 中添加 token 字段:

bash 复制代码
scrape_configs:
  - job_name: 'consul-services'
    consul_sd_configs:
      - server: 'consul-server:8500'
        token: '7a1253ef-8d1e-4b2a-9e34-56789abcdef0'  # 使用只读令牌
        services: ['*']
---> 待上真正的线上环境进行测试验证

5.高级验证:检查审计日志

查看 Consul 日志确认令牌使用情况:

bash 复制代码
# docker logs consul-server | grep 'acl.vet'

正常日志应显示类似:

bash 复制代码
[DEBUG] acl.vet: token=7a1253ef-8d1e-4b2a-9e34-56789abcdef0 operation=catalog:listServices result=allow
4.2.8 管理ACL密钥

1.密钥分类和管理策略

  • 根据用途对令牌进行分类管理,简历清晰的权限边界:

|---------------|-------------|----------|----------------|
| 令牌类型 | 权限范围 | 生命周期(建议) | 存储方式(建议) |
| Bootstrap 主令牌 | 全局管理权限 | 永久 | 加密保险柜 + 纸质备份 |
| 服务专用令牌 | 单个服务的读写权限 | 30天轮换 | 密钥管理平台 (Vault) |
| 监控只读令牌 | 跨服务/节点的读权限 | 90天轮换 | 配置中心加密存储 |
| API 网关令牌 | 特定前缀服务的发现权限 | 按需签发 | 动态签发 (短期有效) |

主令牌应仅在紧急情况下使用,日常操作使用次级管理令牌

2.秘密要 全生命周期管理

  • 创建阶段 - 最小权限

在创建的时候应该是只给需要的权限

  • 存储阶段 - 分级加密

    • 主令牌: 使用AWS KMS或HashiCorp Vault 加密存储,禁止明文落地

    • 服务令牌: 注入到应用环境变量(K8s Secrets 或 Consul Template)

    • 临时令牌: 通过Vault动态签发, 存活实践应该小于1小时

  • 轮换阶段 - 无缝过渡

  • 撤销阶段 - 应急响应

3.审计与监控配置

  • 启用 ACL 审计日志

  • 关键指标监控

  • 参考上述3.3 监控Consul自身文档

4.自动化管理实践

  • 使用Vault动态签发Consul令牌
相关推荐
源代码•宸3 小时前
goframe框架签到系统项目开发(用户认证中间件、实现Refresh-token接口)
数据库·经验分享·后端·算法·中间件·跨域·refreshtoken
❀͜͡傀儡师3 小时前
docker部署 DBSyncer数据同步中间件
docker·中间件·容器
@淡 定19 小时前
主流缓存中间件对比:Redis vs Memcached
redis·缓存·中间件
yours_Gabriel1 天前
【kafka】基本概念
分布式·中间件·kafka
思成Codes1 天前
Gin.RouterGroup:分组、中间件与路径组合
中间件·gin
没有bug.的程序员3 天前
Nacos vs Eureka 服务发现深度对比
jvm·微服务·云原生·容器·eureka·服务发现
祁思妙想4 天前
Python中CORS 跨域中间件的配置和作用原理
开发语言·python·中间件
小股虫4 天前
Tair Java实操手册:从零开始的缓存中间件入门指南
java·缓存·中间件