news 2026/9/9 11:13:10

ES8与ZooKeeper统一监控实战:Prometheus Exporter告警设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ES8与ZooKeeper统一监控实战:Prometheus Exporter告警设计

1. 为什么把ES8和ZooKeeper放进同一套监控体系

我在整理监控这份工作的时候,最开始是把Elasticsearch和ZooKeeper分开看的。毕竟这两个组件做的事完全不一样:ES8负责搜索引擎、日志分析、指标存储,ZooKeeper负责分布式协调、服务注册、配置管理和分布式锁。一个偏数据面,一个偏控制面,看起来没什么交集。

但实际跑了一段时间后我发现,这两个组件在绝大多数团队的架构里,往往是命运共同体。Kafka依赖ZooKeeper做broker元数据管理和controller选举,Dubbo这类微服务框架用ZooKeeper做注册中心做服务发现;而ES8集群的监控数据要落到Kafka,日志采集链路要经过ES,业务流程要依赖注册中心。也就是说,ZooKeeper一挂,Kafka全挂,Kafka一挂,整个日志采集管道断开,ES这边也就只能查到存量数据,增量全断。这个连锁反应链,决定了这两个组件必须放在同一个监控视角下看,而不是各看各的。

另一个原因是运维成本。很多中小团队根本没有专职的ES DBA或者大数据运维,监控这事往往是一个人扛。如果ES一套监控看板、ZK一套监控看板、告警平台再各接一套,出问题的时候需要在几个系统之间来回切,光是判断"到底是ZK先挂还是ES先挂"就要折腾半天。把它们统一到同一套监控体系里,用同一个时间轴去对比指标曲线,排查根因的效率会高很多。

所以这篇文章的核心思路不是讲"ES8怎么调优"或者"ZooKeeper源码怎么读",而是从监控这个切入点,把这两个组件的关键指标、采集方式、看板搭建、告警规则串起来,形成一套能直接落地的方案。适合正在搭监控平台的同学参考,也适合那些已经有一套监控但总觉得"指标很多、有效信息很少"的团队。

2. 选型思路:Prometheus加Exporter为什么是最省事的组合

2.1 监控组件的选型对比

先说说为什么我没用Zabbix而选了Prometheus。不是Zabbix不好,而是它的模型对这两个组件的适配度不如Prometheus高。Zabbix的核心是模板+触发器,采集方式以agent主动推、server主动拉为主,对动态扩容的集群来说,每次加节点都要在Zabbix里维护主机,非常痛苦。而Prometheus的服务发现机制配合Kubernetes、Consul或者最简单的文件发现,新增节点后指标自动就能抓到,不需要人工介入。

从指标模型来看,Prometheus的多维数据模型(metric + label)也更适合表达ES和ZK的指标。比如ES的分片状态,我可以用elasticsearch_indices_status{cluster="es-prod", index="nginx-log"}这样一个时序来表示,查询的时候按label过滤即可。Zabbix的item key体系做这种多维标签要麻烦得多。

再一个考虑是Exporter生态。Elasticsearch和ZooKeeper在开源社区都有非常成熟的Prometheus Exporter,不需要自己开发采集器,配置一下连接信息就能拉到指标。作为监控体系的搭建设计,能站在已有轮子上工作,没必要自己造轮子。

2.2 采集架构设计

我的实际部署结构是这样的:

  • Prometheus主节点一台,负责拉取所有Exporter的指标并存储
  • Grafana一台,对接Prometheus数据源,做可视化看板
  • 每个ES节点部署一个elasticsearch_exporter,监听9108端口(默认端口)
  • 每个ZK节点部署一个zookeeper_exporter,监听9141端口(默认端口)
  • 通过Prometheus的file_sd_configs做静态服务发现,维护两个yml文件,分别记录ES和ZK的节点列表

这套结构的好处是,采集链路非常干净:Prometheus定时去目标Exporter拉指标,Exporter负责到ES/ZK做协议转换。即使ES或ZK本身出问题,Exporter进程依然活着,Prometheus的up == 0机制能够立刻感知目标失联,而不是等指标超时。

顺带说一下,最开始的架构我比较贪心,想把ES和ZK的指标都塞到同一个Exporter里采集,后来发现完全不值得。因为这两个组件的指标体量和维度差异很大,分开采集,告警规则可以独立控制,也更方便定位是哪一侧的问题。

3. ES8监控落地:从指标分类到告警阈值设计

3.1 访问ES8的关键前置条件:安全认证

ES8和之前的版本最大的区别之一,就是安全功能默认开启。这意味着如果直接用原来的连接方式,Exporter连上来就会报unauthorized或者证书校验失败。我记得第一次部署的时候,启动elasticsearch_exporter指定--es.uri=http://localhost:9200,Prometheus抓取到的全部是connection refused之类的问题,调试了很久才发现是ES8默认只开放HTTPS而且强制认证。

对应到Exporter的启动参数,需要这样处理:

./elasticsearch_exporter \ --es.uri=https://elastic:your_password@es-node1:9200 \ --es.ssl-skip-verify \ --es.all \ --es.indices \ --es.indices_settings \ --es.shards \ --es.cluster_settings

--es.ssl-skip-verify是跳过证书校验,生产环境如果ES用的是自签证书,这个参数很有必要。--es.all表示采集所有节点的统计信息,--es.indices采集索引级别的指标,--es.indices_settings采集索引配置,--es.shards采集分片级别的指标,这些都要加上,否则看板很多图标都是空的。

如果你的ES集群开启了RBAC,建议单独创建一个只读监控账号,不要用超级管理员来跑Exporter。操作上可以这样:

PUT /_security/user/monitor_user { "password": "a_strong_password", "roles": ["monitor"], "full_name": "Prometheus Exporter" }

monitor角色在ES8中已经默认包含了对集群监控指标和节点统计信息的只读权限,足够Exporter使用。

3.2 ES8的关键监控指标分类

ES的监控指标数量非常多,如果全采回来,看板上一堆图,反而干扰判断。我从实际使用中梳理出了四类对我来说最关键的指标:

集群层面:

  • elasticsearch_cluster_health_status:这是最核心的布尔量,值为1表示green,0表示yellow,-1表示red
  • elasticsearch_cluster_health_unassigned_shards:未分配分片数量,这个指标在节点宕机或新节点加入后最容易异常
  • elasticsearch_cluster_health_active_shardsrelocating_shards:分片迁移数量短期内激增,说明集群在做重大调整

节点层面:

  • elasticsearch_jvm_memory_heap_used_percent:JVM堆内存使用率,超过85%就要警惕
  • elasticsearch_jvm_gc_collection_time_seconds_total的速率:GC时间,通常关注ES进程的Young GC和Old GC时间
  • elasticsearch_os_cpu_percent:节点CPU使用率
  • elasticsearch_filesystem_data_available_byteselasticsearch_filesystem_data_size_bytes:磁盘可用空间,这两个指标比直接用系统磁盘指标更准确,因为ES会统计到其数据路径

索引层面:

  • elasticsearch_indices_docs_count:文档总数
  • elasticsearch_indices_store_size_bytes:存储大小
  • elasticsearch_indices_search_query_total的速率:查询QPS
  • elasticsearch_indices_search_query_time_seconds的速率:查询耗时,结合QPS可以算出平均延迟
  • elasticsearch_indices_merges_total的速率:段合并操作频率,这个指标如果在短时间内暴增,说明写入量大幅上升或段策略需要调整

线程池层面:

  • elasticsearch_thread_pool_search_queue_size:搜索线程池的队列积压
  • elasticsearch_thread_pool_write_queue_size:写入线程池的队列积压
  • elasticsearch_thread_pool_search_rejected_totalelasticsearch_thread_pool_write_rejected_total:拒绝数,一旦出现拒绝,说明线程池已经不堪重负,这是最紧急的告警信号

为了帮助理解,我做了一张简单的监控指标速查表:

层面指标告警阈值参考说明
集群健康状态green非green即告警
集群未分配分片>0持续5分钟一般伴随节点异常
节点JVM堆使用率>85%持续10分钟堆压力过大
节点磁盘可用空间<20%水位触发前的预警
索引查询延迟P99>1000ms持续5分钟需要检查慢查询
线程池write拒绝数>0写入严重过载
节点CPU使用率>90%持续15分钟可能在做段合并或热点查询

3.3 Grafana看板设计思路

Grafana看板我没有用社区模板直接抄,而是根据监控诉求重新排了一版。核心逻辑是"一屏看集群趋势,二屏看节点明细,三屏看索引排行"。

集群总览页放4个大图:集群状态时间线、JVM堆使用率汇总、磁盘使用率汇总、查询/写入吞吐量趋势。这张页面的作用是每天上班扫一眼,确认整体健康。

节点明细页用一个下拉变量的方式选择具体节点,然后展示该节点的CPU、堆内存、GC耗时、磁盘IO、线程池队列深度等指标。这样在定位单节点问题的时候,不用在多个看板间切换。

索引排行页则通过Impala的topk语法,把写入量最大或查询最慢的前10个索引列出来。这一步在排查"某个业务索引拖垮集群"这类问题时非常有用。生产环境中曾出现过一次日志索引的映射爆炸,字段数从几十涨到上千,导致写入性能急剧下降,就是靠这个页面找到的元凶。

4. ZooKeeper监控落地:四字命令与JMX的配合实用价值

4.1 ZooKeeper监控的特殊性

ZooKeeper不像ES那样提供丰富的REST API,它的监控数据主要通过四字命令和JMX接口暴露。四字命令是ZooKeeper最早提供的监控手段,通过TCP连接在clientPort上发送简短的命令(比如ruokstatmntr),ZooKeeper返回对应的文本信息。而JMX是Java层面的标准监控接口,可以通过jconsole或 Prometheus JMX Exporter 来采集。

ZooKeeper 3.5.0之后,四字命令默认被白名单机制限制,不开启的话,最常用的mntr命令会直接返回The command 'mntr' failed to execute...。部署时一定要在zoo.cfg里加上:

4lw.commands.whitelist=ruok,stat,mntr,conf,envi,srvr,cons

这样做的目的是避免安全风险,但监控需要的最常用几个命令都放行即可,不建议直接配置成*全开。

4.2 Mntr指标的实际解读

在采集方式上,我首选mntr命令,因为它的输出是键值对格式,对Exporter解析最友好。以下是一台生产ZooKeeper节点echo mntr | nc 127.0.0.1 2181的真实输出:

zk_version 3.6.3--1 zk_server_state leader zk_num_alive_connections 8 zk_outstanding_requests 0 zk_znode_count 4321 zk_watch_count 18 zk_ephemerals_count 67 zk_approximate_data_size 179046 zk_open_file_descriptor_count 48 zk_max_file_descriptor_count 1048576 zk_avg_latency 1 zk_min_latency 0 zk_max_latency 18 zk_packets_received 884231 zk_packets_sent 884230 zk_followers 3 zk_synced_followers 3 zk_pending_syncs 0

对于ZooKeeper监控,我最关注的是下面几个指标:

  • zk_server_state:节点角色,leader或follower。这个指标没有数值,但在Prometheus中可以通过记录转换来映射成可查询的label。如果多个节点同时变成leader,那就是脑裂了,这是最严重的故障。
  • zk_num_alive_connections:实时连接数。连接数突然暴跌或暴涨都需要注意,暴跌可能意味着客户端集体断连,暴涨可能是某些客户端出现连接泄漏。
  • zk_outstanding_requests:堆积的未处理请求数。正常情况下这个值应该是0,如果持续大于0,说明ZooKeeper处理能力跟不上,通常是因为磁盘IO性能瓶颈或GC停顿。
  • zk_avg_latency:请求处理平均延迟。正常情况下个位数毫秒,如果这个值开始爬升到几十毫秒甚至上百毫秒,基本可以断定ZooKeeper节点已经不健康。
  • zk_znode_count:节点数量。这个指标更多反映容量规划,如果业务方在使用过程中不断创建临时节点,可能造成Znode数量过大,拖慢ZooKeeper处理。

4.3 Zookeeper Exporter部署配置

使用Prometheus的官方ZooKeeper Exporter时,部署方式有两种:一种是直接对mntr输出做解析,另一种是走JMX接口。我选择的是前者,原因是JMX需要额外开启JMX端口,而且暴露的信息虽然全面,但用起来麻烦一些,光是各类MBean名字就有一大堆。zookeeper_exporter最常见的部署方式是写入Prometheus配置文件,指向每个ZooKeeper节点的2181端口。

- job_name: 'zookeeper' static_configs: - targets: - zk1:2181 - zk2:2181 - zk3:2181

启动Exporter的时候,它是通过TCP发送四字命令给ZooKeeper,所以Prometheus只需要访问Exporter的抓取端口即可,Exporter再主动连ZooKeeper的2181端口。如果ZooKeeper和Prometheus之间存在网络ACL,注意放行Exporter到ZooKeeper的2181端口。

另外部署时要关注ZooKeeper Exporter本身的资源占用。我在一个生产环境遇到过Exporter进程内存持续攀升的问题,后来定位到是ZooKeeper的watch数量非常大的场景下,Exporter采集一次需要拉取大量数据,内存开销不小。建议给Exporter的JVM设置一个合理的堆上限:

java -Xmx256m -jar zookeeper_exporter.jar 9141 :2181

不需要给Exporter分配过多内存,因为它只是做指标转换,不是缓存数据。

4.4 Zookeeper集群层面的额外监控

单个节点的指标只能反映节点自身的健康状态,但ZooKeeper是集群,必须站在集群视角看。集群层面需要额外监控:

  • zk_followerszk_synced_followers:这两个指标只在leader节点上有值,它们表示follower数量以及已同步的follower数量。如果synced_followers小于followers,说明有些节点同步落后,可能很快就会丢投票权。
  • 节点之间的时钟偏差和网络延迟:ZooKeeper对节点间的网络稳定性要求极高,特别是leader选举期间。如果哪台节点和leader之间的网络延迟超过几十毫秒,很容易导致频繁的leader切换。这个指标可以通过Prometheus的probe模块对2888端口做TCP探测来监测。

ZooKeeper最容易出问题的场景之一,就是业务方在使用过程中频繁创建临时Znode并设置watch。大量watch在节点故障时的清理过程会给ZooKeeper带来很大的瞬时压力。所以zk_watch_count这个指标也很重要,虽然平时不至于告警,但出现瞬时增长的时候要能查得到历史趋势。

5. 部署过程中的坑与排查链路

5.1 ES8证书校验失败的排查全过程

第一次启动ES8的elasticsearch_exporter时,Prometheus的Target页面显示Get "https://es-node1:9200/": x509: certificate signed by unknown authority。当时第一反应是证书有问题,换成了CA签发的证书后依然报错。

排查链路:

  1. 先用curl测试ES接口:
curl -k -u elastic:password https://localhost:9200

这个命令能正常返回JSON,说明ES本身没问题。

  1. 再用Exporter的调试模式启动:
./elasticsearch_exporter --es.uri=https://elastic:password@es-node1:9200 --web.listen-address=:9108 --log.level=debug

日志里能看到Exporter在建立TLS连接时拿到的证书指纹,和ES节点实际的证书指纹对比,发现完全不一致。

  1. 最后确认问题出在Exporter默认校验了ES集群的证书链,而ES8自签证书的证书链在Exporter的JVM信任库里不存在。解决办法就是在启动参数里加--es.ssl-skip-verify=true,让Exporter跳过证书校验。

这个坑其实只花了半小时就定位了,但当时不理解的人可能会在证书配置上绕很久。ES8默认安全策略带来的改变,对监控侧最直接的影响就是所有采集端的认证和TLS配置全部要跟着调整。

5.2 ZooKeeper四字命令被白名单拦截

ZooKeeper 3.5之后的版本,任何四字命令默认都不会被处理,除非在配置文件中显式声明。我第一次部署时没有注意这个变化,启动zookeeper_exporter后,Prometheus抓到的指标全部是空的,看zookeeper_exporter的日志,发现连接和命令发送都成功,但返回的内容不对。

我手动执行了一次:

echo mntr | nc 127.0.0.1 2181

返回一大堆The command 'mntr' failed to execute...的错误。当时就知道是白名单问题。修改zoo.cfg,加上4lw.commands.whitelist配置后重启ZooKeeper节点,再用mntr验证,数据就出来了。

修复后我还额外做了一件事:把ruok返回的imoksrvr返回的节点角色都纳入监控。ruok虽然只能确认进程是否存活,但它是最轻量的探活方式;srvr能看到节点的角色和版本信息,对告警时判断主从状态比较有用。

5.3 Prometheus抓取超时导致的数据断点

监控跑起来一段时间后,我发现ES的看板上偶尔会出现某个时间段的指标完全空白,就像"断点"一样。刚开始以为是Exporter进程OOM退出,检查后发现Prometheus的scrape_interval是15秒,而某个ES节点的Exporter在采集大量索引指标时,单次抓取耗时超过了15秒。

Prometheus对每次抓取请求的默认超时时间是10秒(scrape_timeout默认继承自scrape_interval),实际抓取如果超过了限制,这次抓到的数据就会被丢弃,从而在图上形成空白。

解决办法有两种:

  1. 调整Prometheus的抓取配置:
scrape_configs: - job_name: 'elasticsearch' scrape_interval: 30s scrape_timeout: 25s static_configs: - targets: ['es-node1:9108']
  1. 给Exporter加--es.indices参数的过滤,比如只采集白名单内的索引,减少单次抓取的数据量。

我最后两个调整都做了:一方面把ES的抓取周期调成30秒,另一方面在Exporter启动参数里加了--es.indices=logstash-*,nginx-*这类过滤规则,只采集业务相关的索引,避免一次拉取全量索引导致Exporter处理不过来。

5.4 告警风暴与降噪机制

监控体系搭建完成后的第一个星期,我最大的困扰是告警太多。ES的堆使用率超过85%的告警,一天能触发几十次;ZK的连接数指标稍微抖动就告警。排查下来发现两个问题:一是阈值设置没有结合业务实际,二是告警规则里没有加持续时间(for)参数。

我的调整策略是这样的:基础健康类的告警,比如集群变成yellow、节点掉线,这些高危指标立即告警,不加for参数;需要观察的指标,比如JVM堆使用率、磁盘空间、GC耗时,加上for: 10m或者for: 15m,降低抖动的误报。

在告警分级上,我也做了明确的区分:

  • P0(立即处理):ES集群red、ZK节点全部不可用(过半节点掉线)、线程池拒绝数大于0
  • P1(5分钟内处理):ES集群yellow、JVM堆使用率超过90%、ZK连接数超过基线的3倍
  • P2(30分钟内处理):磁盘可用空间低于15%、ZK平均延迟超过20ms、旧版本YGC耗时超过1秒

最终的效果是告警量从每天几十条降到了每天三五条,每一条都是真正需要人工介入的。

6. 告警规则与监控项设计的一些调整心得

6.1 从"监控指标"到"监控效果"的转变

部署这套监控体系之后,我最大的体会是:指标采集只是开始,真正有价值的是把这些指标串成"业务可感知的监控效果"。

ES集群健康状态从green变成yellow,如果不看未分配分片的数量,只收到一个yellow的告警,可能还以为是哪块分片暂时没就绪。但如果同时关联了节点掉线数、磁盘使用率、线程池拒绝数,就能很快判断出yellow的本质原因。

ZK的状态也一样,watching一个Znode的业务如果发现服务列表刷新变慢了,从ZK监控图上看连接数和延迟曲线,能很快锁定是ZK节点性能问题还是网络问题。

6.2 容量规划视角的监控补充

监控不仅仅是告警,还要为容量规划提供数据支持。在ES这边,我额外保留了一张"未来一个月磁盘水位预测"的图,用简单的线性回归来预测磁盘满的时间节点。方式很粗暴,用当前磁盘增长速率的平均值算一个趋势线,虽然不算精确,但足以提醒团队"三个月后是否需要扩容节点"。

ZK这边,我会定期观察zk_znode_countzk_approximate_data_size的增长。这两个指标虽然不会直接影响性能,但当数据量超过某个阈值后,ZooKeeper的FIFO队列和同步机制会开始变得吃力。提前知道数据一直在增长,就能在业务方注册大量临时节点之前提醒他们清理。

6.3 告警通知渠道与值班衔接

最后说一下告警通知的实操细节。我们的告警分为两个渠道:P0/P1的告警通过Webhook推送到企业微信机器人并同步发短信,P2的告警只发企业微信。这样既保证了重大故障期间的强提醒,又不至于让所有人被低级别告警轰炸。

同时,我每次都把告警消息里的日志片段和当前的监控图链接带上。值班人员不用先登录Grafana看半天再判断,点开消息里的图就能第一时间看到趋势。

如果你也在维护ES和ZK的监控体系,我的建议是别急着把几百个指标全部采集下来,先确定你想回答的运维问题,再倒推需要哪些指标。监控系统是给人用的,不是指标越多越好。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 11:12:36

Simscape Battery电池仿真建模全流程:电芯、电池包与BMS验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 11:12:33

Python实现PageRank:稀疏矩阵与幂迭代法处理大数据集实战

简介&#xff1a;面向大数据与图算法学习者&#xff0c;这是一份围绕web-Google.txt数据集计算PageRank的Python实现资源。资源提供三种方法&#xff1a;先用Python稀疏矩阵完成单机计算&#xff0c;再调用NetworkX库的内置PageRank&#xff0c;第三种则基于NetworkX但自行编写…

作者头像 李华
网站建设 2026/9/9 11:10:11

手机变身服务器:Termux+Ubuntu搭建LNMP动态网站实战

1. 为什么绕一大圈装Ubuntu&#xff0c;而不是直接用Termux搭网站先说结论&#xff1a;直接在Termux里装Nginx、PHP、MySQL完全可行&#xff0c;但真正把动态网站跑起来之后&#xff0c;你会碰到一堆"能用但别扭"的问题。我最初也试过在Termux原生环境里直接干&#…

作者头像 李华
网站建设 2026/9/9 11:09:52

STM32C5与LSM6DSVE轮询驱动实战:突破中断时序瓶颈

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 11:09:27

Python二手车数据分析及可视化系统实战:从爬虫到Flask大屏展示

很多人问我&#xff0c;用 Python 做数据分析到底能做出什么像样的东西&#xff0c;我一般都会拿这个二手车数据分析及可视化项目举例。这个系统从数据采集、清洗整理、多维度分析到可视化大屏展示&#xff0c;把 Python 数据分析的全流程走了一遍。它不是教科书里那种孤立的 d…

作者头像 李华
网站建设 2026/9/9 11:09:11

太阳能追光系统实战:基于STM32与Arduino的光伏板自动追踪设计

简介&#xff1a;针对STM32与Arduino联合实现的太阳能追光系统&#xff0c;这份资料提供了完整的工程源码与硬件配置&#xff0c;适合嵌入式学习者、电子设计竞赛参赛者以及新能源应用开发者。项目以自供能为特色&#xff0c;涵盖光照检测、角度追踪算法、步进电机驱动和电源管…

作者头像 李华