2454 字
约 8 分钟
14
S13-X10 · ES 集群运维与分片分配

_cluster/health 返回 yellow,多数人的第一反应是"再等等"。但 yellow 的语义很明确:主分片全在,有副本没分配——能读能写,只少了一层冗余。把它当"慢慢会好",代价是单节点故障时直接掉数据。运维功夫不在"重启试试",而在读完三个数字就知道下一步点哪里。


1. 三色语义与分片计数怎么读

$ curl -s "localhost:9200/_cluster/health?pretty"
{
  "status": "yellow",
  "number_of_nodes": 3,
  "active_primary_shards": 12,
  "active_shards": 18,
  "relocating_shards": 0,
  "initializing_shards": 0,
  "unassigned_shards": 6,
  "active_shards_percent_as_number": 75.0
}
字段 含义 读法
status green/yellow/red 见下表
unassigned_shards 未分配总数 必须配合 _allocation/explain 看原因
initializing_shards 正在恢复的分片 大于 0 说明仍在恢复,不要在这个窗口做变更
relocating_shards 正在迁移的分片 滚动重启/扩容期间应为 0 才继续下一步
颜色 缺什么 影响 处置优先级
green 主、副本全部分配 正常 无
yellow 主全在,副本缺失 可读写,无冗余;节点挂掉可能丢分片 中:查副本为何没分配
red 至少一个主分片未分配 该分片对应数据不可读写,搜索返回部分结果 高:立刻 explain

red 不等于数据没了:主分片未分配通常是节点离线、磁盘被拒或 mapping 冲突。先 explain 定位,再决定恢复节点还是 allocate_stale_primary。


2. 分配的基本约束与磁盘水位线

分片分配是"约束满足"问题:

约束 默认 后果
主副本不同节点 同 shard 编号的主与副本不能同节点 单节点时副本永远 yellow
磁盘水位线 low 85% / high 90% / flood 95% 超线触发迁移或只读
节点角色 只有 data 节点能放分片 coordinating 节点不承载数据
PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.disk.threshold_enabled": true,
    "cluster.routing.allocation.disk.watermark.low": "85%",
    "cluster.routing.allocation.disk.watermark.high": "90%",
    "cluster.routing.allocation.disk.watermark.flood_stage": "95%",
    "cluster.info.update.interval": "30s"
  }
}

三个水位线的行为差异是排障关键:

  • low(85%):不再往这个节点新分配分片,已有分片不动;
  • high(90%):开始把分片迁出该节点;
  • flood(95%):自动给相关索引加 index.blocks.read_only_allow_delete: true,写入直接失败。

flood 的只读块不随磁盘下降自动解除,必须手动清:

PUT /kb_chunk/_settings
{ "index": { "blocks": { "read_only_allow_delete": null } } }

百分比相对数据盘;多路径 path.data 时按各路径分别判定。多规格机器用绝对阈值("50gb")更可控。


3. _cluster/allocation/explain 怎么读

GET /_cluster/allocation/explain?pretty
{
  "index": "kb_chunk",
  "shard": 0,
  "primary": false
}

返回里两个字段决定结论:

字段 内容 判读
allocate_explanation 一句话结论 先看这句,通常是"cannot allocate because allocation is not permitted to any of the nodes"
node_allocation_decisions[].deciders 每个候选节点被哪条规则否掉 decision: "NO" 的那条就是根因

常见 decider 与对应处置:

decider 含义 处置
same_shard 同分片副本已在该节点 加节点,或临时降副本数
disk_threshold 超 low/high 水位线 清盘、扩盘、迁索引
allocation_decider(并发迁入上限) cluster.routing.allocation.node_concurrent_incoming_recoveries 打满 等恢复完成,别叠加操作
filter / awareness 分配过滤或机架感知不满足 检查 index.routing.allocation.*
no_valid_shard_copy 所有副本都损坏 从快照恢复

不带参数的 GET /_cluster/allocation/explain 会取第一个未分配分片,适合快速定位;精确排查必须带 index + shard + primary。


4. 节点角色怎么分

配置形态是 node.roles: [ master ]、[ data_hot, data_content, ingest ]、[ ] 三种。

角色 职责 不该承担 规模建议
master 集群状态、分片决策 数据、查询 固定 3 台,专用
data 存分片、执行查询与写入 master 选举开销 按容量扩
ingest pipeline 预处理 重 CPU 的 grok 会拖慢写入 可与 data 混布
coordinating(空 roles) 汇总各分片结果 不存数据,但吃内存与网络 大查询场景单独部署

node.roles: [] 是 coordinating-only,不是"什么都能干"。误配的表现是"加了机器,yellow 没好转"。


5. master 选举与脑裂

discovery.seed_hosts: ["10.0.0.11:9300", "10.0.0.12:9300", "10.0.0.13:9300"]
cluster.initial_master_nodes: ["es-master-1", "es-master-2", "es-master-3"]  # 引导后删除
参数 语义 一次性?
discovery.seed_hosts 找候选 master 的地址列表 否,长期保留
cluster.initial_master_nodes 首次引导用的 master 名单 是,集群成型后必须删除
discovery.type: single-node 单节点开发模式 否,生产禁用

initial_master_nodes 残留的危害:集群已成型后重启,节点会按旧名单尝试重新引导,若名单里的节点已下线,可能形成两个独立的 master 视图,表现为同一集群名、不同数据。正确做法是引导完成后立刻从配置里删掉这一行并重启验证。

7.x 起取消 minimum_master_nodes 手工配置,quorum 由选举算法判定,(n/2)+1 不用再算。


6. 副本的作用与恢复流程

配置 写吞吐 读吞吐 冗余 说明
副本 0 最高 单点 无 仅测试或可重建数据
副本 1 略降 +1 份读能力 1 节点故障可恢复 生产底线

副本不提升写吞吐:写请求要同步到所有副本,副本越多写放大越明显。它的价值是"高可用 + 读分摊"。

故障恢复链条:主分片节点失联 → master 把某副本提升为主(promote)→ 旧主回归后作为副本重同步 → 从主分片做 peer recovery(增量或全量)。恢复限速:

PUT _cluster/settings
{
  "persistent": {
    "indices.recovery.max_bytes_per_sec": "200mb",
    "cluster.routing.allocation.node_concurrent_recoveries": 2,
    "cluster.routing.allocation.node_initial_primaries_recoveries": 4
  }
}

indices.recovery.max_bytes_per_sec 默认约 40mb/节点。调大能缩短 red→green,但挤占写入 IO——高峰调限速就是拿可用性换速度。恢复期看 GET /_cat/recovery?v&active_only=true 的 bytes_percent 与 stage。


7. 滚动重启的顺序

# 0) 先禁分片迁移,避免重启触发无谓的再平衡
curl -s -XPUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d '
{"persistent":{"cluster.routing.allocation.enable":"primaries"}}'

# 1) 停一个节点(systemd / docker 均可)
systemctl stop elasticsearch

# 2) 重启后等它加入集群,再放开分配
curl -s -XPUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d '
{"persistent":{"cluster.routing.allocation.enable":"all"}}'

# 3) 轮询到 green 且迁移归零,才动下一个
curl -s "localhost:9200/_cluster/health?wait_for_status=green&timeout=300s&pretty" \
  | grep -E '"status"|relocating_shards'
步骤 目的 做错的后果
先设 allocation.enable: primaries 阻止副本在重启窗口内乱迁 每个节点重启都触发全量再平衡,IO 打满
一次只停一个节点 保证 quorum 与副本可提升 停两台 → 3 副本场景也可能 red
等 relocating_shards: 0 迁移完成再动下一个 副本反复 initializing,恢复永远追不上
恢复 allocation.enable: all 后再等 green 让副本归位 直接进行下一台,副本重建叠加

重启窗口内 unassigned_shards 上升是正常现象;判断异常的标准是同一分片长时间停在 initializing,那说明限速或网络有问题,不是"再等等"。


8. 扩容与再平衡

加节点后分片不会自动"匀",取决于分配决策与再平衡阈值。

再平衡由 cluster.routing.rebalance.enable(默认 all)控制,阈值由 cluster.routing.allocation.balance.* 决定;cluster_concurrent_rebalance 控制并发迁移数,调大换速度。

场景 手段 注意
新节点分不到分片 检查 cluster.routing.allocation.exclude._name 排除规则常被忘掉
分片太散、单节点过多 index.routing.allocation.total_shards_per_node 设太小会导致分配失败
想把某索引挪走 _cluster/reroute 的 move 只能搬已分配分片
冷热分层 index.routing.allocation.require.data 与 ILM 的 allocate 动作配合

POST /_cluster/reroute?dry_run=true 先验证再执行,这是唯一安全的用法:直接 move 失败会让集群进入"两边都没有该分片"的中间态。


9. 排错

现象 原因 处理
长期 yellow,副本全未分配 单节点 / 副本数 > 数据节点数 加数据节点,或把副本降到 1
red 且 explain 报 no_valid_shard_copy 副本全损 / 快照缺失 从 _snapshot 恢复该索引
两个节点各自成集群 initial_master_nodes 残留或 seed 网络不通 删配置行,检查 9300 连通性

10. 边界

场景 更合适的手段 理由
分片数规划 按"单分片 10–50GB"估算后一次性建好 分片数改不了,只能 reindex
单索引超大数据量 ILM + rollover 靠单索引扩容会撞分片上限
频繁全量恢复 快照仓库(S3/共享存储) 副本重建比快照慢一个量级

一句话:green 不是目标,可预期的恢复时间才是。副本数、水位线、恢复限速三个参数决定了故障时你要等多久。


11. 自测

  1. yellow 与 red 在"缺什么"上的区别是什么?
  2. unassigned_shards 有值但 initializing_shards 也为 0,说明卡在哪一步?
  3. 水位线 low / high / flood_stage 分别触发什么动作?
  4. cluster.initial_master_nodes 为什么在集群成型后必须删掉?
  5. 副本数从 1 加到 2,写吞吐会变好吗?
  6. 滚动重启时先设 allocation.enable: primaries 的目的是什么?
S13-X10 · ES 集群运维与分片分配
https://www.clxhxhhr.top/posts/5849/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。