☰
基于Prometheus与Grafana自定义Consul监控面板实践
2026/10/16 9:48:37 网站建设 项目流程

如果只是要“能看出 Consul 在跑”,随便拉一个现成面板就够了;但如果你负责的是一个正在支撑业务的 Consul 集群,一整天最关心的其实是那几个问题:leader 有没有频繁切换?节点健康检查是不是开始飘红?KV 读写量有没有异常上涨?服务注册与注销的频率是不是不对劲?这些需求,模板面板通常给不到,而且各家 Consul 的指标命名、标签习惯、服务场景又不一样,唯一靠谱的路线,就是基于自己的业务逻辑去定制一套 Grafana 面板。

我这次要分享的就是这样一个实践:使用自定义 Grafana 面板监控 Consul。内容会覆盖指标采集链路怎么搭、核心面板怎么设计、PromQL 怎么写、模板变量和告警怎么配,以及我在真实环境里踩过的坑。适合正在用 Consul 做服务注册发现、又在 Grafana 里想搭一套贴合自己业务监控的人参考。

1. 方案设计:为什么是“Prometheus + 自定义 Grafana 面板”

先明确监控对象。Consul 本身有自带的 Web UI 和 API,但那些更适合临时排查问题,不适合长期盯盘。你需要的是一个能存历史数据、能画曲线、能配置告警的统一监控平台。当前主流组合就是 Prometheus 负责采集和存储时序数据,Grafana 负责展示和告警。Consul 正好原生暴露 Prometheus 格式的指标接口,所以整个链路是顺理成章的:Consul agent 输出指标,Prometheus 定期抓取,Grafana 从 Prometheus 数据源查询并绘制仪表盘。

1.1 为什么不用现成模板

一开始我也直接从面板市场导入过现成的“Consul 监控”开源面板。导入之后发现几个问题:

  • 模板里的面板要么太多、很冗余,要么太少、关键维度缺失。我在意的指标没在模板里,我不关心的指标倒是占了一大块。
  • 指标版本对不上。不同 Consul 版本的指标名、标签结构可能不同,空查的图表能堆出半屏。
  • 模板无法适配业务语义。比如我团队里服务健康阈值是按“连续 5 分钟无成功注册”来告警,模板里写的是固定 15 分钟区间,没法直接反映真实问题。

所以“自定义”不是炫技,而是把监控口径拉回业务现场的必选项。

1.2 指标体系的选型思路

Consul 的指标非常多,我最初也试图全部展示,结果面板又乱又慢。后来我按以下维度做了取舍:

维度对应指标类型监控目的
集群全局状态serf 节点数、raft leader快速判断集群是否“活着”
服务健康health node/service status发现节点或服务的不健康状态
集群稳定性raft commit、apply 速率发现 leader 切换和事务堆积
资源消耗runtime alloc、heap objects判断 Consul 进程是否有内存压力
业务操作量kv set、catalog register感知业务对 Consul 的使用强度

这五个维度基本覆盖了“集群自身状态”和“业务使用情况”两端。面板布局我也按这个维度来排,而不是简单地堆图表。

1.3 自定义面板的信息架构

我最终的 dashboard 分四行:

  • 第一行:集群总览。显示节点数、Raft Leader 数量、是否有 leader、当前时间窗口内 Raft 提交速率。
  • 第二行:服务健康。显示通过、警告、宕机节点数,以及服务注册与注销的速率。
  • 第三行:Raft 稳定性。显示 peers、commit 次数、apply 速率、leader 切换趋势。
  • 第四行:资源消耗与 KV 操作。显示内存分配、堆对象数、KV 写入速率等。

这样的布局是为了让“事故发生时第一眼能看到什么”成为主线。有人在跑服务,有人在做域控,把不同关注点分离开,也避免面面俱到反而什么都看不清的问题。

2. 环境准备:从 Consul 指标采集到 Grafana 数据源

这步没有太多花样,但有几个关键配置很容易忽略。

2.1 打开 Consul 的 Prometheus 指标开关

Consul 默认情况下不会把 Prometheus 格式指标原样输出,需要显式开启。修改 Consul 的配置文件(比如/etc/consul/consul.hcl):

telemetry { prometheus_retention_time = "24h" disable_hostname = true }

解释一下:

  • prometheus_retention_time表示 Prometheus 格式指标在 Consul 端的保留时间。这个值不是必须设得很大,因为 Prometheus 抓走后会自己存很久,但设置为24h能防止 Prometheus 在抓取间隙重启时丢失数据。
  • disable_hostname = true是用来避免指标名里带上主机名前缀的,这样 Grafana 里查询指标时名字能保持一致,否则可能变成consul-server-1_consul_runtime_alloc_bytes这种格式,查询会很痛苦。

修改后重启 Consul 进程。验证是否生效可以直接 curl 一下:

curl -s http://127.0.0.1:8500/v1/agent/metrics?format=prometheus | head -20

如果看到# HELP consul_raft_leader这类输出,就说明已经通了。注意?format=prometheus这个参数必须带,否则默认输出的是 JSON。

2.2 Prometheus 抓取配置

在 Prometheus 的prometheus.yml里新增一个 job:

scrape_configs: - job_name: consul honor_labels: true metrics_path: /v1/agent/metrics params: format: ["prometheus"] static_configs: - targets: - 10.0.0.11:8500 - 10.0.0.12:8500 - 10.0.0.13:8500

这里有两个重点。

metrics_path指向/v1/agent/metrics,而不是常见的/metrics。因为 Consul 的指标是挂在 HTTP API 路径上的,所以 Prometheus 抓取路径必须对齐。

params里必须带format=prometheus。如果不带,Consul 默认返回 JSON,Prometheus 会报解析错误,面板就什么都查不到。

抓取目标建议写所有 Consul agent 的地址,包括 server 和 client。因为有些指标是每 agent 独立的,比如节点健康状态,只在对应 agent 上暴露。

如果你的 Consul 启用了 ACL,还要在抓取配置里带上 token,否则/v1/agent/metrics会被拒绝。一般是在params里加token,或者在 Prometheus 的basic_auth配置里处理。

2.3 Grafana 数据源配置

在 Grafana 里添加 Prometheus 数据源时,URL 填 Prometheus 服务地址,比如http://prometheus-server:9090。如果 Grafana 和 Prometheus 部署在不同网段,注意访问方式要选择 Server 而不是 Browser,否则浏览器端访问不到内网地址,面板数据会一直加载不出来。

配置好后,可以先在 Explore 页面验证一下能否查到consul_raft_leader这个指标。如果能搜到,说明链路已经通了。

3. 核心面板实现:关键指标与 PromQL 逐面板拆解

这是我花时间最多的地方。PromQL 的写法直接决定了面板是“能看”还是“好用”。

3.1 集群总览行

我用了四个纯数字面板:

  • 在线节点数:sum(consul_serf_lan_members)
  • Raft Leader 个数:count(consul_raft_leader == 1)
  • 当前是否有主节点:可以用这个查询配合阈值处理
  • Raft 提交速率:rate(consul_raft_commit[5m])

为什么consul_serf_lan_members用sum?因为同一个节点可能会被多个 agent 上报,直接展示原始 series 会看到好几条曲线。用sum聚合后,得到的是集群内实际成员的总数。如果你的集群有多个数据中心,可能还得按dc标签分组:

sum by (dc) (consul_serf_lan_members)

还有一个容易踩坑的点:consul_raft_leader这个指标在非 leader 节点上是 0,在 leader 节点上是 1。所以领路唯一判定我一般写作count(consul_raft_leader == 1),正常情况下结果应该是 1;如果结果是 0,说明集群里没有可用的 leader,那是很严重的异常。

3.2 服务健康与节点状态

Consul 的健康检查状态是分类的,对应的 Prometheus 指标大致是consul_health_node_status和consul_health_service_status,都带一个status标签,值可能是passing、warning、critical、maintenance。

统计不健康节点数:

sum(consul_health_node_status{status!="passing"})

统计各类状态分布,我一般用:

sum by (status) (consul_health_node_status)

这个查询会按状态画出多条线,一眼就能看出颜色的分布。如果你的 Consul 指标命名不完全一样,可以先用label_values()或者我们 2.3 节的 Explore 方式确认一下标签名。

服务注册注销速率:

  • 注册速率:rate(consul_catalog_register[5m])
  • 注销速率:rate(consul_catalog_deregister[5m])

这两个指标能从业务角度反映服务生命周期变化。比如某个瞬间注册速率突然飙升,伴随大量注销,多半是有实例在频繁重启,或者发布系统在批量部署。

3.3 Raft 稳定性与事务量

Consul 用 Raft 协议做一致性。监控 Raft 的关键是看 leader 是否稳定、日志提交是否通畅。

关键查询:

# Raft 提交计数 rate(consul_raft_apply[5m]) # Peers 数量 consul_raft_peers # Leader 切换趋势 changes(consul_raft_leader[5m])

changes()这个函数很好用,它返回指标在时间窗口内发生变化的次数。如果changes(consul_raft_leader[5m])大于 0,说明过去 5 分钟内 leader 发生了切换。偶尔一次可能还好,如果频繁出现,就要警惕网络分区、节点资源不足、或某些节点的心跳异常。

我还习惯给“Leader 当前数”加一条阈值线,当长时间为 0 时告警。具体告警逻辑放在第 6 小节说。

3.4 资源消耗与 KV 操作

Consul 运行本身吃内存,尤其是当服务数量、KV 条目数量增长后。我常看这几个指标:

# 内存分配量 consul_runtime_alloc_bytes # 堆对象数 consul_runtime_heap_objects # KV 写入速率 rate(consul_fsm_consul_kv_set[5m])

在生产环境,我习惯把consul_runtime_alloc_bytes换算成 MB 展示,方便值班同学判断。可以在 Grafana 面板的 Standard options 里设置 Unit 为bytes (SI),或者直接用consul_runtime_alloc_bytes / 1024 / 1024转为 MB。

KV 写入速率是我个人比较看重的一个指标。很多业务系统会把配置、分布式锁、租约信息存到 Consul KV,如果 KV 写入速率突然暴涨,往往意味着某个服务在疯狂写配置,或者锁竞争异常。这类问题不一定影响 Consul 本身,但对业务影响很大,监控上必须能看见。

4. 自定义面板的进阶玩法:模板变量与多集群复用

面板在单机 Consul 集群上跑通后,下一步就是让它能在多节点、多机房、多集群场景下复用。模板变量是这里的关键。

4.1 模板变量搭建

我一般会在 Grafana dashboard 的 Settings 里定义几个变量:

变量名定义方式用途
nodelabel_values(consul_health_node_status, node)筛选单个节点
dclabel_values(consul_serf_lan_members, dc)筛选数据中心
statuslabel_values(consul_health_node_status, status)筛选健康状态

之后每个面板的查询都能用变量来约束范围。例如,只看特定数据中心的节点:

sum by (node) (consul_health_node_status{dc="$dc"})

这里要注意:变量值依赖指标里的标签,如果指标本身没有dc标签,那就定义不出来。遇到这种情况,可以先到 Prometheus 里看一下该指标的标签集合,再决定变量怎么建。

还有一个技巧:变量可以设置为“All”。比如status变量允许选全部状态,那么查询中最好写成{status=~"$status"},而不是{status="$status"}。因为 Grafana 在变量选择为All时会注入一个正则匹配串,=~才能正确匹配。

4.2 面板 JSON 的结构与复用技巧

如果你不想靠鼠标重复建面板,也可以直接编辑 dashboard 的 JSON 文件来实现批量复用。Grafana 的 dashboard 本质是一个 JSON 文件,里面有panels数组,每个 panel 是一个对象。举个例子,一个简单的 Raft Leader 状态面板的 JSON 长这样:

{ "type": "stat", "title": "Raft Leader", "datasource": { "type": "prometheus", "uid": "your-prometheus-datasource-uid" }, "fieldConfig": { "defaults": { "thresholds": { "steps": [ { "color": "red", "value": null }, { "color": "green", "value": 1 } ] } } }, "targets": [ { "expr": "count(consul_raft_leader == 1)", "legendFormat": "leader" } ], "gridPos": { "h": 4, "w": 4, "x": 0, "y": 0 } }

把这样的 JSON 片段插到 dashboard JSON 的panels数组里,再调整gridPos就能快速复制面板。对多集群场景,还可以把 dashboard JSON 保存到 git 里,用 CI 统一部署。

不建议把同一个 dashboard 复制到多个 Grafana,更推荐用一个带变量的 dashboard 再配合不同的数据源或标签。比如在 Prometheus 中给不同集群打上/cluster标签,然后在面板里用$cluster变量过滤,这样维护一套 JSON 就够了。

4.3 自定义面板的细节调优

面板不是“数据能画出来”就行了。我做以下几个细节调优:

  • 单位设置:内存类指标设置为bytes,速率类指标设置为cps,百分比类指标设置为percent,避免值班同学看一串原始数字还要心算。
  • 图例格式化:查询时尽量用legendFormat把图例写成有含义的名字,比如{{dc}} / {{node}} / {{status}},避免默认的Series 1、Series 2。
  • 时间区间:一些瞬时状态面板(如“当前节点数”)建议设置instant查询。Grafana 里把查询的Format选为Instant,面板上就只显示当前值,不会因为时间窗口变化而出现误导性的历史平均值。
  • 阈值线:在 Stat 面板里加阈值线和颜色转变,例如节点数低于 3 就变红,这样值班人员能在远距离一眼发现问题。

5. 真实环境里的坑:问题排查与经验

这块内容基本是我在落地这套监控时踩过的坑汇总,建议先收藏。

5.1 指标抓不到

现象:Grafana 面板全空,或者部分 Consul 节点没有数据。

排查步骤:

  1. 先看 Prometheus 的 Targets 页面,确认抓取目标是不是 UP。如果状态是 DOWN,检查网络连通性、ACL Token、端口。
  2. 如果状态是 UP 但面板空,先用 Explore 查一下指标名是否存在。Consul 版本升级后指标名称可能变化,比如某些老版本叫consul.raft.apply,新版本叫consul_raft_apply,这种差异很容易导致查询为空。
  3. 确认抓取路径和参数。我在 2.2 里写的params.format=prometheus必须加上,否则抓回来是 JSON,Grafana 里看到的标签会非常奇怪。

5.2 面板数据不对

现象:集群实际有 5 个节点,但面板显示 10 个。

这个大概率是节点指标被重复上报了。比如每个 Consul agent 都会暴露本地视角的节点信息,如果有多个 agent 上报同一批节点,就会出现重复计数。解决方式就是按节点去重:

count(distinct(consul_health_node_status{status="passing"}))

如果指标里带instance标签,也可以按instance区分开看。不要图省事直接sum,一定要先想清楚指标是全局的还是节点级的。

5.3 告警抖动与基数问题

这是我认为最影响使用体验的两个问题。

告警抖动。如果直接对queue_consul_raft_apply[1m]设一个超过阈值的告警,可能在高峰期频繁触发。我的做法是在 Prometheus 的告警规则里加上持续时间,例如 5 分钟内持续大于阈值才告警,同时使用 rate 而不是瞬时值,减小抖动影响。

高基数。Consul 的指标如果带上了节点、服务、状态、数据中心等大量标签,series 数量会膨胀得很厉害。特别是服务数量多、节点数量大的时候,一个consul_health_service_status就能生成几千条序列。我的建议是面板查询尽量先用sum by聚合,减少 Grafana 渲染压力,同时在 Prometheus 端适当做metric_relabel_configs过滤掉不用的标签。

还有一个容易忽略的坑:面板“空闲”时看起来一切正常,但一旦你拖动时间范围回查很久以前的数据,Grafana 可能要花很长时间。原因是查询粒度太细。我习惯在时间范围超过 7 天时,把查询选项里的Interval调大,比如拉到 5m 甚至 1h,让数据点密度降低,图表也能快速加载。

6. 告警规则与后续迭代建议

看板解决了“看”,告警才解决“管”。我一开始只做面板,结果出问题还是靠业务方打电话才知道,很被动。

6.1 从面板出发配告警

在 Grafana 新版里,可以直接在面板的 Alert 页签里创建规则。比如“Raft 节点丢失”的告警:

count(consul_raft_leader == 1) < 1

评价周期可以设置为5m,这样当集群 5 分钟没有主节点时才告警,避免节点重启导致临时抖动。

另一个我常用的告警是“节点健康状态非 passing 比例超过阈值”:

( sum(consul_health_node_status{status="critical"}) / sum(consul_health_node_status) ) * 100

超过百分之几就触发,时间窗口同样设置 5 分钟。这个告警适合在服务规模大的集群里用,比直接对单节点告警更不容易误报。

告警通知我一般接到企业微信群或飞书机器人。Grafana 自带的通知渠道里有 Webhook,只需要配置好回调地址即可。如果业务方平时不看 Grafana,可以把告警直接推到即时通讯的群里。

6.2 后续还能怎么扩展

这套自定义面板只是第一步。跑稳定后,我建议继续做三件事:

  • 把面板和告警规则代码化。用 Terraform 管理 Grafana dashboard 和数据源,或者把 JSON 保存到 Git 仓库,让变更留痕,避免所有人都在生产 Grafana 上手动改来改去。
  • 把 Consul 指标和业务日志联动。只看指标能发现异常,但往往不知道元凶。我会把节点异常时间点对齐到业务日志的时间线,在排障时能省很多时间。
  • 把 Consul 的自动恢复流程纳入监控闭环。比如节点掉线时,自动触发重启脚本或者通知后端系统重新拉取服务列表,实现一定程度的自愈。

个人实践下来,监控体系和业务一样,都需要迭代。一开始你只需要看节点和 leader,服务规模大了,KV 和健康状态指标就不得不看,再后来你可能还需要给不同业务线划分不同的 dashboard 页面。所以不要追求一步到位,先把第一版跑起来,然后在真实故障里不断调整阈值和面板结构,最终会变成一套非常贴合你们业务的监控系统。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询