Elasticsearch 基础与集群巡检
各位同学,今天我们聊聊 Elasticsearch 的基础和集群巡检。说实话,作为一个从 Logstash 1.x 就开始折腾的老运维,我判断一个 ES 集群靠不靠谱,第一件事就是看健康状态。不是看监控面板上那些花哨的图表,而是直接敲一行 API。
我个人习惯把集群巡检分成三个层面:节点层面、分片层面、业务层面。前两个层面通过健康状态 API 一把梭,第三个层面靠巡检脚本定时扫。今天我们先打地基——把节点角色、API 用法和常见故障啃透。
安装与配置:别踩这些坑
ES 的安装本身不难,单节点下载解压就能跑。但生产环境我建议用 RPM 或 Docker 方式,方便后续管理。这里分享几个我踩过的坑:
- network.host 别乱配:我以前图省事直接配
0.0.0.0,结果跨网段通讯时发现节点之间无法发现。原因是发现模块的discovery.seed_hosts没加本机 IP。 - JVM 堆内存别超过 31GB:ES 底层大量使用对象压缩,超过 31GB 会触发 JVM 的压缩对象指针失效,导致性能雪崩。我一般设成物理内存的一半,上限 30GB。
- data 和 logs 目录分开:把两个目录挂到不同磁盘,防止日志写满导致数据节点挂掉。这个事情我在一个客户环境里吃了大亏——日志塞满磁盘,集群直接红色了两小时。
下面是一份简版配置清单,适合 3 节点入门集群:
| 配置项 | 推荐值 | 说明 |
|---|---|---|
cluster.name | elk-cluster | 同一集群必须一致 |
node.name | node-1, node-2, node-3 | 每个节点唯一 |
network.host | 内网 IP | 不要用 0.0.0.0 或 127.0.0.1 |
discovery.seed_hosts | ["IP1", "IP2", "IP3"] | 种子节点列表 |
cluster.initial_master_nodes | ["node-1"] | 首次选举用 |
path.data | /data/elasticsearch | 建议独立磁盘 |
path.logs | /var/log/elasticsearch | 系统盘分区分开 |
我的小技巧:启动前用 elasticsearch-setup-passwords interactive 设置内置用户密码,安全审计逃不掉。
节点角色:各司其职才稳定
一个 ES 集群里节点可以扮演多重角色。你想想看,如果让一个节点又当 master 又忙 data 又做 ingest,出问题概率会很高。我建议按职能拆分。
| 角色 | 职责 | 配置参数 | 我踩过的坑 |
|---|---|---|---|
| Master | 管理集群元数据、分配分片、处理 join/leave | node.master: true | master 节点数量推荐奇数(3或5),避免脑裂。我见过有人用 2 个 master,网络抖动直接丢半数票 |
| Data | 存储数据、执行 CRUD 和聚合 | node.data: true | 数据节点磁盘利用率超过 85% 自动触发分片迁移,这是 ES 的自我保护机制,合理,但会加剧 IO 压力 |
| Ingest | 在索引前处理文档(Pipeline) | node.ingest: true | 默认开启,如果 ingest 负载高建议独立节点,避免拖慢数据写入 |
| Coordinating | 接收客户端请求,转发到对应节点并合并结果 | 以上三个角色全为 false | 这种节点负责做负载均衡,不加硬盘也能跑。我之前写巡检脚本时发现协调节点 CPU 飙升,排查后才意识到是聚合请求没做限流 |
实际生产环境,我建议至少部署 3 个专有 master 节点 + 3 个 data 节点 + 2 个 coordinating 节点。如果你资源紧张,至少保证 master 和 data 角色物理分离。
集群健康状态 API:一眼看穿问题
最常用也最实用的 API 就这一条:
GET /_cluster/health
返回结果长这样:
{
"cluster_name" : "elk-cluster",
"status" : "yellow",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 2,
"active_primary_shards" : 45,
"active_shards" : 90,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 1,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 98.9
}
说白了,核心就三句话:
- green:所有主副分片都分配好了,集群健康。
- yellow:主分片正常,但有些副本没分配。往往是因为单节点或磁盘不足。黄了赶紧查,别拖成红。
- red:有主分片丢失,数据不可用。这是事故,需要立刻处理。
我记得有一次,巡检脚本报警显示 yellow 持续了 3 天,我以为是副本延迟分配,没在意。结果第四天数据节点宕机,因为副本一直没分配,主分片无法转移,集群直接红了……从那以后我在巡检脚本里加了逻辑:yellow 状态如果超过 1 小时就发紧急告警。
小心这个陷阱:API 返回的 unassigned_shards 不等于 0 的时候,不要只盯着 status。有些场景下 status 是 green 但 unassigned_shards 非零(比如延迟分配策略),一样棘手。我建议巡检脚本同时检查这两个字段。
基础故障排查:遇到问题别慌
集群出问题太正常了。下面这几个是我在实战中反复遇到的,每个都有血泪史。
- 节点无法加入集群——检查
cluster.name是否一致,discovery.seed_hosts是否可达。我曾经犯过低级错误:两个节点配了不同的 transport.port。 - 分片未分配——用
GET /_cluster/allocation/explain查看具体原因。常见原因有:磁盘空间不足、节点有_allocation.exclude._ip设置、索引副本数大于可用节点数。 - 集群状态 red——先定位丢失的索引:
GET /_cat/shards?h=index,shard,prirep,state | grep UNASSIGNED。如果数据不重要,直接删除索引;如果重要,尝试 reroute 手动分配或重新索引。 - 节点 OOM——看日志里的 OutOfMemoryError,通常是聚合查询太暴力。我建议限流 + 设置
search.max_buckets。
经验之谈:不要一上来就重启节点。重启可能导致 master 选举,如果 master 节点集群只有两个节点,选举失败会直接脑裂。优先用 POST /_nodes/_restart 滚动重启。
下面这张图画的是我每次做集群健康检查时的操作流程,你可以直接套用到自己的巡检脚本里。
流程很简单:先请求健康 API,协调节点转发给 master,master 检查所有索引的 primary 和 replica 分片是否都到位,然后返回 green/yellow/red。巡检脚本拿到状态后,配合 unassigned_shards 和 relocating_shards 做阈值判断,该报警报警,该处理处理。
小结
今天的内容算是 ES 巡检的入门必修课。安装配置别犯低级错误,节点角色按场景拆分,健康 API 要读懂每个字段,故障排查有套路可循。这些技能我建议你直接在测试环境出一份故障模拟——故意关掉一个数据节点,然后用 API 观察状态变化,比看十遍文档都管用。