Elasticsearch 三节点集群部署实战:从单机到生产可用
Elasticsearch 单机跑起来很容易,难的是让它在磁盘涨满、节点掉线时不丢数据、不变只读。本文以 Elasticsearch 8.x、三台 Rocky Linux 9 节点(es-01 / es-02 / es-03)为例,走完从系统准备、集群组建、安全配置到分片规划与快照备份的完整流程,目标是一套能承接日志检索或业务搜索的生产可用集群。文中口径以每台 16 GB 内存、数据盘独立挂载为基准,其他规格按比例折算即可。
部署前的系统准备
ES 对操作系统参数比多数中间件敏感,以下四项不做完,节点要么起不来,要么埋下后期故障:
- vm.max_map_count:必须 ≥ 262144,否则启动直接报错退出。写入 /etc/sysctl.d/99-es.conf 并 sysctl --system 生效。
- 文件句柄与进程数:用 systemd 部署时在服务单元里设 LimitNOFILE=65535、LimitNPROC=4096;手动 limits.conf 只对登录会话生效,容易踩坑。
- 关闭 swap 或锁定内存:swap 会让 GC 与查询延迟不可控,生产建议直接关 swap。
- 堆内存口径:JVM 堆设为物理内存的一半且不超过 31 GB(一半留给 Lucene 的页缓存,31 GB 以上会失去指针压缩反而变慢)。16 GB 机器堆设 8 GB。
前置条件
- 三台节点主机名可互相解析,9200(HTTP API)与 9300(节点间通信)端口互通;
- Elasticsearch 8.x 安装包(RPM 或 tarball)已分发到三台;
- 数据目录 /data/es 与日志目录规划在数据盘上,不要放在系统盘;
- 三台机器时间同步完成。
第一步:安装与基础配置
三台节点安装方式一致。以 tarball 方式为例,创建用户、解压并调整目录:
useradd -r -s /sbin/nologin elasticsearch
tar -xzf elasticsearch-8.17.0-linux-x86_64.tar.gz -C /opt/
ln -s /opt/elasticsearch-8.17.0 /opt/elasticsearch
mkdir -p /data/es/data /data/es/logs
chown -R elasticsearch:elasticsearch /data/es
编辑 config/elasticsearch.yml,三台仅 node.name 不同,其余一致:
cluster.name: prod-search
node.name: es-01
# 三个节点都兼任 master 与 data 角色(小集群标准形态)
node.roles: [ master, data, ingest ]
path.data: /data/es/data
path.logs: /data/es/logs
network.host: 0.0.0.0
http.port: 9200
transport.port: 9300
# 初始主节点名单:首次组建时三台写全,集群成型后此项不再需要改动
discovery.seed_hosts: ["es-01", "es-02", "es-03"]
cluster.initial_master_nodes: ["es-01", "es-02", "es-03"]
# 开启安全(8.x 默认开启):证书由内置 CA 生成,见下文
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
两个关键点:一是 cluster.initial_master_nodes 只在集群第一次选举时起作用,集群成型后不要再改它——节点重启不需要它,改错反而会触发重复组建;二是防脑裂靠的是主节点选举的法定人数机制,三节点天然满足多数派,节点数保持奇数即可,不要上偶数台 master 角色节点。
第二步:堆内存与服务单元
在 config/jvm.options.d/heap.options 里固定堆大小(初始与最大一致,避免运行时伸缩抖动):
-Xms8g
-Xmx8g
# systemd 单元关键项(节选)
# LimitNOFILE=65535
# LimitNPROC=4096
# User=elasticsearch
# ExecStart=/opt/elasticsearch/bin/elasticsearch
systemctl daemon-reload
systemctl enable --now elasticsearch
第三步:安全证书与密码
8.x 默认开启安全,节点间传输层证书用内置工具生成一次、分发到三台的 config/certs 目录;HTTP 层如需 HTTPS 同理生成 http 证书。节点启动后,用官方脚本为内置用户批量生成随机密码并妥善保存,业务接入统一走自建的、最小权限的角色与用户,不要拿 elastic 超级账号写进应用配置:
# 生成传输层 CA 与节点证书(三台主机名一次性签发)
/opt/elasticsearch/bin/elasticsearch-certutil ca --out /tmp/elastic-ca.p12
/opt/elasticsearch/bin/elasticsearch-certutil cert --ca /tmp/elastic-ca.p12 \
--name es-01 --dns es-01 --ip 192.0.2.11 --out /tmp/es-01.p12
# 其余两台同理,把 p12 拷入各节点 config/certs 并在 yml 中引用
# 集群启动后重置内置用户密码(交互式生成并打印一次)
/opt/elasticsearch/bin/elasticsearch-reset-password -u elastic
验证:集群健康怎么读
curl -s -u elastic:'你的密码' https://es-01:9200/_cluster/health?pretty
curl -s -u elastic:'你的密码' https://es-01:9200/_cat/nodes?v
curl -s -u elastic:'你的密码' https://es-01:9200/_cat/shards?v
健康状态的真实含义要讲透:green 是所有主分片与副本分片都已分配;yellow 是主分片都在、但有副本未分配——单节点集群必然 yellow,三节点集群出现 yellow 说明有节点或磁盘出了问题,数据可查但没有冗余;red 是有主分片未分配,对应索引的部分数据不可用,这是必须立刻处理的状态。判断集群好坏先看 status,再看 unassigned_shards 与 active_shards_percent_as_number 定位范围,不要只看一个颜色就下结论。
索引与分片规划的入门口径
分片数一旦建索引就定死(只能靠 reindex 改),规划原则:单个分片控制在 10–50 GB、单节点分片总数不超过约每 GB 堆内存 20 个。日志类索引按天或按大小滚动(ILM 策略),副本数生产设 1 起步;业务搜索索引按数据量预估一年内的总量反推主分片数。宁可分片略少,也不要为每个小业务都建一堆分片——分片本身就是元数据与内存开销。
快照备份到对象存储
ES 的备份只有快照一条正路,拷数据目录无效。接 S3 兼容对象存储的最小配置:
# 把访问密钥写入 keystore(三台节点都要执行)
/opt/elasticsearch/bin/elasticsearch-keystore add s3.client.default.access_key
/opt/elasticsearch/bin/elasticsearch-keystore add s3.client.default.secret_key
# 注册快照仓库
curl -s -u elastic:'你的密码' -X PUT https://es-01:9200/_snapshot/backup-repo \
-H 'Content-Type: application/json' -d '{
"type": "s3",
"settings": { "bucket": "es-backup", "base_path": "prod-search" }
}'
# 手动打一次快照并查看进度
curl -s -u elastic:'你的密码' -X PUT \
https://es-01:9200/_snapshot/backup-repo/snap-2026-001?wait_for_completion=false
curl -s -u elastic:'你的密码' \
https://es-01:9200/_snapshot/backup-repo/snap-2026-001
仓库注册成功后,用 SLM 策略把快照做成每日定时任务,并至少做一次真实恢复演练——没恢复过的快照不算备份。
常见问题
1. 索引突然变只读,写入报错 read-only
这是磁盘水位线在起作用:节点磁盘超过 flood-stage 水位(默认 95%)后,ES 会给索引加上写封锁。先腾磁盘或扩容,再手动解除:PUT 索引 _settings 把 index.blocks.read_only_allow_delete 置为 null。治本是接入磁盘告警并做冷热分层,别把水位线调高来绕过。
2. 集群 red,如何恢复
先用 _cluster/allocation/explain 看未分配分片给出的官方原因,区分是节点宕机未归、磁盘水位拒绝分配,还是分片文件损坏。若主副本同时丢失且确认源节点回不来,最后的手段才是用 allocation reroute 的 allocate_empty_primary 强拉——这意味着承认这部分数据丢失,必须在业务知情下执行。
3. 节点频繁被踢出集群
多为大 GC、磁盘 IO 抖动或网络闪断导致心跳超时。先看 GC 日志与磁盘 await,堆内存不足就按口径调整;不要先去调大故障检测超时,那会同时放大真实故障的发现时间。
4. 误以为 yellow 是故障
扩容、滚动重启期间出现短暂 yellow 是正常的副本重建过程,看 active_shards_percent 是否在持续回升即可。只有 yellow 长时间不消退才需要查具体是哪些副本分配失败。
小结
ES 集群的生产可用不取决于装得多快,而取决于四件基本功:系统参数与堆内存按口径一次做对、选主与发现配置不留脑裂隐患、用健康状态的真实含义而不是颜色本身做判断、上线第一天就把快照与恢复演练安排上。这四件事做到位,三节点集群足以扛住绝大多数中小规模的检索业务。







