☰
Elasticsearch集群监控实战:elasticsearch_exporter+Prometheus+Grafana搭建指南
2026/10/12 12:01:34 网站建设 项目流程

1. 为什么这套监控组合值得你花时间搭

Elasticsearch 集群这东西,用起来爽,出事的时候是真让人抓狂。我见过太多团队,ES 集群平时跑得好好的,一到业务高峰期就各种慢查询、节点掉线、磁盘写满,等到用户反馈搜索卡顿才手忙脚乱去查。问题的根源往往不是 ES 本身不行,而是缺少一套能提前预警、能定位瓶颈的监控体系。

elasticsearch_exporter + Prometheus + Grafana这套组合,是目前社区里做 ES 集群监控最主流、也最经得起生产环境考验的方案。它的分工很清晰:elasticsearch_exporter负责从 ES 的各个接口抓取指标并转换成 Prometheus 能识别的格式;Prometheus 负责定时拉取、存储这些时序数据,并基于规则触发告警;Grafana 则把这些数据渲染成直观的仪表盘,让你一眼就能看出集群健不健康。

这套方案能解决什么问题?简单说,它能让你看到集群级别的健康状态(绿黄红)、节点级别的资源消耗(JVM 堆内存、CPU、磁盘、线程池)、索引级别的读写性能(查询延迟、索引速率、段合并情况),以及分片分配是否均衡。适合谁来参考?运维工程师、后端开发、SRE,以及任何需要对自己维护的 ES 集群负责的人。哪怕你之前没怎么接触过 Prometheus,跟着下面的思路走,也能把这套东西搭起来。

我自己的经验是,监控这东西,搭建只是第一步,真正有价值的是指标选得对不对、告警阈值定得合不合理、出问题时会看哪几个图。所以这篇不会只给你一堆配置文件,我会把每个关键指标背后的含义、为什么这么配、踩过哪些坑都讲清楚。

2. 整体架构设计与组件选型思路

2.1 三个组件各自扮演什么角色

先把这三个东西的关系理清楚,不然后面配置起来容易懵。

elasticsearch_exporter是一个用 Go 写的独立进程,它本质上就是个 HTTP 服务。你启动它的时候告诉它 ES 的地址,它就会定期去调用 ES 的_cluster/health、_nodes/stats、_stats等接口,把返回的 JSON 数据拍平成一堆以elasticsearch_开头的指标,暴露在/metrics路径上。Prometheus 来抓这个路径,就完成了数据采集。

Prometheus 是拉模式(pull-based)的时序数据库。它按照你配置的scrape_interval定时去抓 exporter 的/metrics,把数据存下来。同时它内置了告警规则引擎,你可以写 PromQL 表达式,当条件满足时触发 Alertmanager 发通知。

Grafana 不存数据,它只是查询 Prometheus 然后把结果画出来。社区里有现成的 ES 监控 Dashboard 模板,导入就能用,省去从零画图的时间。

2.2 为什么选这套而不是别的

市面上监控 ES 的方案不止一种。比如 ES 自带的 X-Pack Monitoring,功能确实全,但它是商业功能,集群规模一大就要收费。再比如用 Metricbeat 采集,也能配合 ES 和 Kibana 做监控,但如果你已经在用 Prometheus 体系监控其他服务,再单独维护一套 Metricbeat + ES 存储就有点重复建设了。

选elasticsearch_exporter + Prometheus + Grafana的核心理由有三点。第一,统一监控栈。大部分团队已经在用 Prometheus 监控数据库、中间件、应用服务,ES 接进来就是加一个 job 的事,告警规则、通知渠道都能复用。第二,指标可控。exporter 暴露哪些指标、Prometheus 保留多久、Grafana 怎么展示,全在你手里,不依赖商业授权。第三,社区成熟。这个 exporter 在 GitHub 上维护活跃,Grafana 官方和社区都有现成的 ES Dashboard,遇到问题搜一下基本都有答案。

2.3 部署拓扑的两种常见形态

实际部署时,exporter 放哪里是有讲究的。常见两种做法。

一种是集中式部署,exporter 单独跑在一台监控机上,配置里填 ES 集群的协调节点地址。这种最简单,但有个隐患:如果 ES 集群开启了安全认证,exporter 需要能访问所有节点的 stats 接口,网络策略要放开。而且集中式抓取时,如果 ES 节点多,exporter 串行请求可能比较慢。

另一种是边车式(sidecar)部署,在每个 ES 节点上跑一个 exporter,只抓本节点的指标。Prometheus 通过服务发现或者静态配置抓取所有 exporter。这种方式压力分散,也更符合 Prometheus 的哲学。缺点是部署和维护成本高一些,节点扩缩容时要同步调整。

我的建议是:集群规模在 10 个节点以内,用集中式就够了,配置简单;超过 10 个节点或者对采集实时性要求高,考虑边车式。下面实操部分我以集中式为主来讲,边车式的差异我会单独提。

3. 核心指标解读与采集配置要点

3.1 必须关注的几类核心指标

exporter 暴露的指标有上百个,但真正需要天天盯的其实就那么几类。我把它们分成四组,每组说清楚看什么、为什么看。

集群健康类:elasticsearch_cluster_health_status这个指标最直观,0 是绿色、1 是黄色、2 是红色。还有elasticsearch_cluster_health_number_of_nodes、elasticsearch_cluster_health_unassigned_shards。黄色通常意味着有副本分片没分配,红色意味着有主分片没分配,这两种情况都要立刻查。

JVM 与内存类:elasticsearch_jvm_memory_used_bytes和elasticsearch_jvm_memory_max_bytes配合看堆内存使用率。ES 对堆内存非常敏感,官方建议不超过物理内存的 50%,且不要超过 31GB。堆内存持续高于 75% 就要警惕,高于 85% 基本离 Full GC 不远了。还有elasticsearch_jvm_gc_collection_seconds_count看 GC 次数和耗时。

磁盘与 I/O 类:elasticsearch_filesystem_data_used_percent直接反映磁盘使用率。ES 有个水位线机制,默认 85% 时不再分配新分片,95% 时甚至会把索引设为只读。所以这个指标超过 80% 就该处理了。另外elasticsearch_indices_store_size_bytes看索引占用空间。

性能与线程池类:elasticsearch_indices_search_query_time_seconds看查询耗时,elasticsearch_indices_indexing_index_time_seconds看写入耗时。线程池方面,elasticsearch_thread_pool_rejected_count是关键,一旦有 rejected,说明线程池队列满了,请求被拒绝,用户体验直接受损。elasticsearch_thread_pool_queue_count看排队情况。

3.2 exporter 启动参数怎么配

exporter 的启动参数不多,但有几个直接影响采集效果。

./elasticsearch_exporter \ --es.uri=http://es-coordinating-node:9200 \ --es.all \ --es.indices \ --es.indices_settings \ --es.shards \ --es.snapshots \ --web.listen-address=:9114 \ --collector.clustersettings

逐个说。--es.uri指定 ES 地址,如果有认证就写成http://user:password@host:9200。--es.all表示采集所有节点的指标,不加的话只采集你指定的那个节点。--es.indices采集索引级别指标,这个数据量大,如果索引特别多(上千个),要考虑是否开启,否则 exporter 响应会变慢。--es.shards采集分片级别指标,对排查分片分配问题很有用。--es.snapshots如果你用快照备份就开。--collector.clustersettings采集集群设置,能看到水位线等配置。

注意:--es.indices和--es.shards在索引数量多的时候会显著增加 exporter 的响应时间和 ES 的查询压力。我遇到过索引超过 2000 个的集群,开启这两个采集后 exporter 每次抓取要 10 秒以上,Prometheus 默认 10 秒的 scrape_timeout 直接超时。解决办法是调大 timeout,或者用--es.indices_regex只采集关心的索引。

3.3 Prometheus 抓取配置

Prometheus 这边就是加一个 scrape job。

scrape_configs: - job_name: 'elasticsearch' scrape_interval: 30s scrape_timeout: 25s static_configs: - targets: ['exporter-host:9114'] labels: cluster: 'prod-es'

scrape_interval设 30 秒比较合适。ES 的指标变化没那么快,15 秒有点浪费存储,60 秒又可能漏掉短时抖动。scrape_timeout要留足余量,因为 exporter 抓取 ES 数据本身要时间,设成 interval 的 80% 左右比较稳。labels里加个 cluster 标签,多集群场景下在 Grafana 里可以按集群筛选。

如果 exporter 是边车式部署,用服务发现更合适:

- job_name: 'elasticsearch' scrape_interval: 30s consul_sd_configs: - server: 'consul:8500' services: ['elasticsearch-exporter']

具体用哪种服务发现取决于你的基础设施,Kubernetes 环境用kubernetes_sd_configs,Consul 环境用consul_sd_configs。

4. 从零搭建的完整实操流程

4.1 环境准备与 exporter 部署

假设你有一台监控服务器,上面已经跑着 Prometheus 和 Grafana。现在要把 ES 监控接进来。

第一步,下载 exporter。去 GitHub releases 页面找对应架构的二进制包,或者用 Docker 镜像。生产环境我倾向于用 systemd 管理二进制,比 Docker 少一层网络开销,排查问题也直接。

wget https://github.com/prometheus-community/elasticsearch_exporter/releases/download/v1.7.0/elasticsearch_exporter-1.7.0.linux-amd64.tar.gz tar xzf elasticsearch_exporter-1.7.0.linux-amd64.tar.gz mv elasticsearch_exporter-1.7.0.linux-amd64/elasticsearch_exporter /usr/local/bin/

第二步,创建 systemd unit。

[Unit] Description=Elasticsearch Exporter After=network.target [Service] Type=simple User=prometheus ExecStart=/usr/local/bin/elasticsearch_exporter \ --es.uri=http://10.0.0.10:9200 \ --es.all \ --es.indices \ --es.shards \ --web.listen-address=:9114 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target

第三步,启动并验证。

systemctl daemon-reload systemctl enable --now elasticsearch-exporter curl -s http://localhost:9114/metrics | grep elasticsearch_cluster_health_status

如果能看到elasticsearch_cluster_health_status{cluster="es",color="green"} 0这样的输出,说明 exporter 工作正常。

4.2 Prometheus 接入与告警规则

exporter 通了之后,在 Prometheus 的prometheus.yml里加上前面说的 scrape job,然后systemctl reload prometheus。去 Prometheus 的 Web UI 的 Status -> Targets 页面,应该能看到 elasticsearch 这个 job 是 UP 状态。

接下来配告警规则。新建一个es_alerts.yml:

groups: - name: elasticsearch rules: - alert: ESClusterRed expr: elasticsearch_cluster_health_status{color="red"} == 1 for: 1m labels: severity: critical annotations: summary: "ES 集群状态为红色" description: "集群 {{ $labels.cluster }} 存在未分配的主分片,请立即排查" - alert: ESClusterYellow expr: elasticsearch_cluster_health_status{color="yellow"} == 1 for: 5m labels: severity: warning annotations: summary: "ES 集群状态为黄色" description: "集群 {{ $labels.cluster }} 存在未分配的副本分片" - alert: ESJVMHeapHigh expr: elasticsearch_jvm_memory_used_bytes{area="heap"} / elasticsearch_jvm_memory_max_bytes{area="heap"} > 0.85 for: 5m labels: severity: warning annotations: summary: "ES 节点堆内存使用率过高" description: "节点 {{ $labels.node }} 堆内存使用率超过 85%" - alert: ESDiskHigh expr: elasticsearch_filesystem_data_used_percent > 80 for: 5m labels: severity: warning annotations: summary: "ES 节点磁盘使用率过高" description: "节点 {{ $labels.node }} 磁盘使用率 {{ $value }}%" - alert: ESThreadPoolRejected expr: rate(elasticsearch_thread_pool_rejected_count[5m]) > 0 for: 2m labels: severity: warning annotations: summary: "ES 线程池出现拒绝" description: "节点 {{ $labels.node }} 的 {{ $labels.type }} 线程池出现请求拒绝"

在prometheus.yml里通过rule_files引入这个文件,reload 后告警规则就生效了。

实操心得:for字段很关键。ES 集群状态偶尔闪一下黄色很正常,比如某个节点重启期间。如果for设成 0,你会被大量瞬时告警淹没。我一般给红色设 1 分钟,黄色设 5 分钟,堆内存和磁盘设 5 分钟,线程池拒绝设 2 分钟。这个节奏既能及时发现问题,又不会太吵。

4.3 Grafana Dashboard 导入与定制

Grafana 这边最省事的做法是导入现成模板。Grafana 官网 Dashboard 库里搜 "Elasticsearch",有几个高星模板,比如 ID 为 2322 的那个,覆盖了集群概览、节点详情、索引性能等面板。

导入步骤:Grafana 左侧菜单 -> Dashboards -> Import -> 输入模板 ID -> 选择 Prometheus 数据源 -> Import。

导入后你会发现有些面板没数据,通常是两个原因。一是模板里的指标名和你的 exporter 版本对不上,新版本 exporter 改过一些指标名。二是变量(比如$node、$index)的查询语句需要根据你的标签调整。这时候就要手动改面板的查询。

我一般会基于模板做几处定制。把集群健康状态做成 Stat 面板,绿色/黄色/红色直接对应颜色,一眼就能看。把 JVM 堆内存使用率做成 Gauge,阈值设在 75% 和 85%。把线程池 rejected 做成 Time series,按节点和线程池类型分组。再单独加一个磁盘使用率的表格,按使用率降序排列,方便快速定位快满的节点。

4.4 关键面板的 PromQL 写法

模板里的 PromQL 不一定符合你的需求,这里给几个我常用的。

集群健康状态:

elasticsearch_cluster_health_status{color="green"} == 1

堆内存使用率:

elasticsearch_jvm_memory_used_bytes{area="heap"} / elasticsearch_jvm_memory_max_bytes{area="heap"} * 100

查询速率(每秒查询次数):

rate(elasticsearch_indices_search_query_total[5m])

查询平均延迟(毫秒):

rate(elasticsearch_indices_search_query_time_seconds[5m]) / rate(elasticsearch_indices_search_query_total[5m]) * 1000

索引速率(每秒写入文档数):

rate(elasticsearch_indices_indexing_index_total[5m])

线程池队列积压:

elasticsearch_thread_pool_queue_count

这些 PromQL 你可以直接贴到 Grafana 面板的查询框里,改一下图例和单位就能用。

5. 常见问题排查与避坑经验

5.1 exporter 抓取超时或指标缺失

这是最常见的问题。表现是 Prometheus 里这个 target 时好时坏,或者 exporter 的/metrics响应特别慢。

原因通常有三个。一是 ES 集群索引太多,--es.indices采集开销大。解决办法是用--es.indices_regex限制采集范围,比如只采集业务索引。二是 exporter 到 ES 的网络延迟高,或者 ES 本身负载高响应慢。可以在 exporter 所在机器上curl -w "%{time_total}"测一下 ES 接口的响应时间。三是 exporter 单进程串行请求所有节点,节点多的时候慢。这种情况考虑边车式部署。

排查时先看 exporter 日志,加--log.level=debug能看到每次请求的耗时。然后看 Prometheus 的 target 页面,scrape duration 是多少。如果接近 scrape_timeout,就要优化了。

5.2 指标名对不上导致面板空白

exporter 版本升级时改过指标名,比如早期版本用elasticsearch_jvm_memory_used_bytes,某些版本可能加了前缀或改了后缀。Grafana 模板是基于特定版本做的,版本不匹配就空白。

解决办法是先去 Prometheus 里查一下实际有哪些指标。在 Prometheus Web UI 的 Graph 页面输入{__name__=~"elasticsearch_.*"},就能看到所有 ES 相关指标名。然后对照着改 Grafana 面板的查询。

5.3 告警风暴怎么治

刚上线监控时最容易出这个问题。集群状态一抖、某个节点 GC 一下,告警就刷屏。

治标的方法是调for时长和阈值。治本的方法是做告警分组和抑制。在 Alertmanager 里配置group_by: ['alertname', 'cluster'],把同类告警合并。再配inhibit_rules,比如集群红色告警触发时,抑制该集群下所有节点级别的告警,因为根因已经找到了。

还有一个技巧是给告警加severity标签,critical 的发短信或电话,warning 的只发群消息。这样既不会漏掉严重问题,又不会被 warning 吵到。

5.4 磁盘水位线告警的坑

ES 默认磁盘水位线是 85% 和 95%。但如果你在 ES 里改过cluster.routing.allocation.disk.watermark配置,告警阈值就要跟着改。我见过一个案例,运维把水位线调到了 90%,但告警还设在 80%,结果天天告警但没人处理,最后真到 95% 时反而没人注意了。

所以告警阈值一定要和 ES 实际配置对齐。可以用--collector.clustersettings采集集群设置,然后在 Grafana 里把水位线配置和实际磁盘使用率画在一起,这样一眼就能看出离水位线还有多远。

5.5 常见问题速查表

现象可能原因排查方向解决思路
target 频繁 downexporter 进程崩溃或超时看 exporter 日志和 systemd 状态调大 scrape_timeout,检查 ES 响应
指标缺失采集开关没开或版本不匹配查/metrics实际输出加对应--es.xxx参数
面板空白指标名或标签对不上Prometheus 里查实际指标改 Grafana 查询语句
告警刷屏阈值太敏感或 for 太短看告警历史调阈值、加 for、配抑制规则
堆内存告警但 GC 正常堆内存高但没到 GC 压力看 GC 次数和耗时结合 GC 指标判断,避免误报
磁盘告警但 ES 没反应告警阈值低于 ES 水位线对比 ES 配置对齐告警阈值和 ES 水位线

6. 监控体系持续优化的几个方向

搭起来只是开始,真正让监控产生价值的是持续调优。我分享几个自己实践下来觉得有用的方向。

指标分层。把指标分成"必须告警"、"需要关注"、"仅作参考"三层。必须告警的比如集群红色、磁盘超水位线、线程池拒绝;需要关注的比如堆内存、查询延迟;仅作参考的比如段数量、合并次数。Grafana 首页只放第一层和第二层,第三层放到详情页。这样值班的人一眼就能看到关键信息。

容量趋势预测。用 Prometheus 的predict_linear函数做磁盘容量预测。比如predict_linear(elasticsearch_filesystem_data_used_percent[7d], 86400*30)能预测 30 天后的磁盘使用率。如果预测值超过 85%,就提前扩容或清理索引,而不是等告警响了才动手。

慢查询关联分析。把 ES 的慢查询日志和监控指标关联起来。当查询延迟告警触发时,能快速定位是哪个索引、哪类查询导致的。这个需要在应用层埋点或者开启 ES 的慢查询日志,然后把日志和监控面板联动。

定期回顾告警。每个月花半小时看看这个月触发了哪些告警、哪些是误报、哪些阈值需要调整。监控不是配完就不管了,它需要跟着业务变化一起演进。

我个人在实际操作中的体会是,监控体系的价值不在于图有多好看、指标有多全,而在于出问题时你能不能快速定位、平时能不能提前发现隐患。我见过指标采集了几百个但没人看的集群,也见过只盯十几个关键指标但每次都能提前预警的集群。后者才是我们该追求的状态。所以别贪多,先把集群健康、JVM、磁盘、线程池这四类核心指标盯住,告警阈值调准,再慢慢扩展。这套elasticsearch_exporter + Prometheus + Grafana的组合,只要你把核心指标和告警规则打磨好,它能陪你走很远。

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

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

立即咨询