集群磁盘写满是 Elasticsearch 运维中最常见也最容易预防的事故。一旦触发 flood 水位,所有索引被强制设为只读,写入全线中断,恢复要靠手工清块并等待分片重新分配,代价极高。更隐蔽的是 low 与 high 水位之间的灰色地带:分片不再迁入、新索引无法分配,集群表面上还在跑,直到某个节点彻底撑不住。本文讲清三档水位的确切行为、分片大小与数量的规划原则,以及如何用数据而不是感觉来做扩容决策。
1. 磁盘水位的意义
一句话总结: 水位机制是 Elasticsearch 的自我保护,用三档阈值把「磁盘将满」这个致命状态拆成可干预的三个阶段。
1.1 为什么需要水位
Elasticsearch 的分片分配是自动的,如果没有磁盘约束,主节点会把分片分配到任意节点,直到某个节点磁盘写满。写满的后果不是「写入失败」这么简单:该节点上的分片无法写入、副本无法同步、集群状态可能变红。水位机制让集群在磁盘接近满时主动收缩写入与分配,把故障控制在可恢复的范围内。
1.2 检查的粒度
水位按节点上的每个数据路径独立计算,而不是整机磁盘总量。如果一台机器上挂了多个数据盘(path.data 配置多个目录),每个盘单独判定。这带来一个常见误解:机器上还有另一块空盘,但某个数据路径已经超过水位,节点照样进入只读。
1.3 检查频率
主节点定期(默认每 30 秒)收集各数据节点的磁盘使用情况并重新评估水位。也就是说,水位不是实时触发的,从磁盘超过阈值到集群做出反应,最多有几十秒延迟。这解释了为什么「刚刚还好好的」突然就只读了——水位评估在后台周期性跑,不是每次写入都检查。
2. 三档水位
一句话总结: low 禁止分片迁入、high 开始尝试迁出分片、flood 强制所有索引只读,三档逐级加码。
2.1 默认阈值
| 水位 | 默认阈值 | 触发后的行为 |
|---|---|---|
| low | 85% | 新分片不再分配到该节点 |
| high | 90% | 尝试把分片迁出该节点 |
| flood | 95% | 该节点上所有索引设为只读 |
阈值基于磁盘使用率,不是剩余空间。对大容量磁盘(如 4TB),95% 意味着还剩 200GB,看似宽裕,但分片迁移、merge 和快照都需要临时空间,实际余量并不安全。
2.2 low 水位
达到 low 水位后,主节点不再把新分片分配到该节点,但已有分片继续正常工作,也不会主动迁出。这个阶段的典型症状是「新索引的副本一直处于 unassigned 状态」,因为找不到满足条件的节点。
2.3 high 水位
达到 high 后,主节点开始尝试把该节点上的分片迁移到其他节点。迁移是有条件的:目标节点必须低于 low 水位、满足分片分配过滤规则。如果所有节点都接近满,迁移会失败并反复重试,集群状态长时间处于 yellow 或 red。
2.4 flood 水位
这是最后一道防线。达到 flood 后,Elasticsearch 对该节点上所有索引执行只读设置,写入直接被拒绝:
{
"error": {
"type": "cluster_block_exception",
"reason": "index [logs-2026.10.02] blocked by: [TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark, index has read-only-allow-delete block]"
}
}
注意这个块是集群级下发的,不是索引自身的设置。恢复时必须显式解除。
2.5 阈值调整
阈值可以按集群动态调整:
PUT /_cluster/settings
{
"persistent": {
"cluster.routing.allocation.disk.watermark.low": "85%",
"cluster.routing.allocation.disk.watermark.high": "90%",
"cluster.routing.allocation.disk.watermark.flood_stage": "95%",
"cluster.routing.allocation.disk.watermark.flood_stage.max_headroom": "20gb"
}
}
也支持绝对值形式(如 50gb)。对大磁盘集群,绝对值的表达力更好:watermark.low: 200gb 表示剩余不足 200GB 就不再分配分片,比百分比更贴近真实需求。max_headroom 参数则给大磁盘兜底,避免 95% 在超大容量盘上留出过多无用空间。
3. 只读索引块与恢复
一句话总结: flood 触发的只读块必须手工解除,且清块前必须先腾出磁盘空间,否则会立刻再次触发。
3.1 只读块的类型
index.blocks.read_only 与 index.blocks.read_only_allow_delete 是两个不同的设置。flood 水位使用的是后者:索引不可写,但仍允许删除文档,这是为了让用户能通过删除数据自救。
3.2 解除只读
清空磁盘空间后,逐个索引或全集群解除:
PUT /_all/_settings
{
"index.blocks.read_only_allow_delete": null
}
null 表示移除该设置。注意必须确认磁盘确实降下来了,否则下一次水位评估会立刻重新加上块。
3.3 恢复顺序
正确的恢复顺序是:
- 定位写满的节点,确认是哪个数据路径。
- 删除或迁走数据——优先删旧索引、清临时文件、删过期快照。
- 等磁盘使用率降到 high 以下。
- 解除只读块。
- 观察水位评估是否再次触发。
跳过第 3 步直接解块,会在几十秒后再次只读,形成反复。
3.4 预防性只读
除了 flood,也可以主动给历史索引加只读块,防止误写入:
PUT /logs-2026.01/_settings
{
"index.blocks.write": true
}
这与 ILM 的 cold/frozen 阶段做的事一致,属于主动治理而非被动保护。
4. 分片大小与数量规划
一句话总结: 单个分片控制在 10GB 到 50GB,分片总数与节点数保持合理比例,是避免水位频繁触发的前提。
4.1 分片大小的经验值
官方给出的推荐区间是单分片 10GB 到 50GB。小于 10GB 的分片数量过多,每个分片都有固定开销(段文件、集群状态条目、堆内存),管理成本上升;大于 50GB 的分片在恢复、迁移时耗时长,merge 压力大,且单个分片故障影响面大。
搜索密集型场景偏向小区间(10 到 30GB),日志与写入密集型偏向大区间(30 到 50GB)。
4.2 分片数量的规划
分片数量的经验公式是「每 GB 堆内存对应 20 个分片以内」。一个 30GB 堆的节点,分片数控制在 600 以内比较稳妥。分片过多会显著增加主节点的集群状态管理开销——每次集群状态变更都要广播给所有节点,分片元数据越大,恢复越慢。
总分片数 ≈ 数据总量 / 单分片目标大小
单节点分片数 ≤ 堆内存GB × 20
4.3 滚动索引控制分片数
对时序数据,用 ILM 按时间滚动产生新索引,每个索引的分片数固定,从而让分片总数随时间线性增长。此时的关键参数是滚动周期与分片数:
PUT /_ilm/policy/logs-policy
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": { "max_primary_shard_size": "30gb", "max_age": "1d" }
}
}
}
}
}
max_primary_shard_size 让滚动由「主分片大小」触发,比按文档数或天数更贴近磁盘实际占用。
4.4 避免过小分片
日索引如果每天只有几百 MB,却配了 5 个分片,一年下来就是上千个小分片。正确做法是降低分片数(甚至单分片),或者改用更大粒度的索引(周索引、月索引)。
5. 容量估算方法
一句话总结: 容量估算要覆盖原始数据、索引膨胀、副本、段合并余量与安全余量五个部分,最终得出所需磁盘总量。
5.1 五部分构成
| 组成 | 典型倍数 | 说明 |
|---|---|---|
| 原始数据 | 1.0 | 业务写入的文档体积 |
| 索引膨胀 | 1.1 到 2.0 | 倒排索引、doc values、存储字段 |
| 副本 | 1 + 副本数 | 每份副本占等量空间 |
| merge 余量 | 1.5 | 段合并期间的临时双份占用 |
| 安全余量 | 1.15 | 留给水位与运维操作 |
举例:原始数据 1TB,膨胀系数取 1.3,1 个副本,merge 余量 1.5,安全余量 1.15,则所需磁盘为 1 × 1.3 × 2 × 1.5 × 1.15 ≈ 4.5TB。
5.2 膨胀系数的影响因素
- 字段类型:
text建立倒排索引,膨胀明显;keyword与数值字段的 doc values 相对紧凑。 - 是否开启
_source:关闭_source能省空间,但会失去 reindex 与更新能力,慎用。 index: false的字段:仅存储不索引,能显著降低膨胀。- 分词粒度:细粒度分词产生更多词项,倒排更大。
5.3 增长趋势外推
容量规划不是算一次就完事。要按周或按月统计实际磁盘增长速率,做线性或带季节性的外推:
预计耗尽时间 = (可用空间 × 0.85) / 日均增长量
以「距离 low 水位还有多少天」作为核心告警指标,而不是「当前用了百分之几」。剩余 30 天时开始规划扩容,剩余 14 天时必须执行。
5.4 快照仓库的空间
快照仓库通常与数据盘分开,但也要纳入规划。增量快照虽然只存变化部分,但首次全量快照的体积接近数据总量,且长期保留策略会累积。仓库写满会导致快照失败,SLM 策略静默失效。
6. 扩容决策与实施
一句话总结: 扩容前先判断是「数据增长」还是「分片失衡」,前者加节点,后者先做分片重平衡。
6.1 先诊断再扩容
磁盘告警时先回答三个问题:
- 是单节点异常还是全集群普遍偏高? 单节点高说明分片分配不均,应调 rebalance 或手动迁移。
- 是主分片增长还是副本堆积? 副本过多可以降副本数,这是最快的止血手段。
- 增长是趋势性的还是突发? 突发可能来自某次批量导入或日志暴涨,加节点是过度反应。
6.2 分片重平衡
如果只是分配不均,用分配过滤把分片从高水位节点迁走:
PUT /_cluster/settings
{
"transient": {
"cluster.routing.allocation.exclude._name": "node-1"
}
}
迁移完成后清空该设置。注意迁移本身会消耗网络与磁盘 IO,且目标节点必须有空间。
6.3 垂直与水平扩容
- 垂直扩容:给节点加盘或换大盘。操作简单但受单机上限约束,且重启节点会触发分片重分配。
- 水平扩容:加新节点,让分片自动均衡。更符合 Elasticsearch 的设计,但要注意新节点加入后的大量分片迁移会占用带宽。
水平扩容的节点配置应与现有节点一致,否则新节点会成为瓶颈。
6.4 扩容后的验证
加节点后要确认三件事:新节点是否被正确加入集群、分片是否开始迁移、迁移完成后各节点使用率是否均衡。分片迁移是 IO 密集操作,建议在低峰期执行,并临时降低 cluster.routing.allocation.node_concurrent_recoveries 避免打满带宽。
6.5 降副本作为应急手段
磁盘告急时,最快的腾挪方式是临时把副本数从 1 降到 0:
PUT /logs-*/_settings
{
"index.number_of_replicas": 0
}
这能立刻释放一半空间,但集群进入无冗余状态,任何一个节点故障都会丢数据。仅作为应急,扩容完成后必须恢复副本并等待分片重新分配。
7. 生产实践与常见坑
一句话总结: 磁盘治理的重点是「提前告警、分层存储、定期清理」,而不是等到只读后再救火。
7.1 分层与冷热
用 ILM 把数据从热节点滚动到温节点,再到冷节点,最后删除或转为可搜索快照。热节点用 SSD、容量小;冷节点用大容量 HDD。分层能让昂贵的存储只承载热数据,是控制成本与水位最有效的手段。
7.2 告警指标设计
- 节点磁盘使用率超过 75% 预警,超过 82% 严重告警。
- 「距 low 水位剩余天数」低于 30 天告警。
- 集群出现
unassigned分片且原因是disk时立即告警。 - 监控
cluster.routing.allocation.disk.threshold_enabled是否被误关。
7.3 常见坑清单
- 多数据路径误判:只看整机磁盘,忽略了单个
path.data已超限。 - 副本数过多:为了「高可用」把副本设成 2 或 3,磁盘成倍消耗。
- merge 期间误判:大 merge 会临时占用双倍空间,触发水位后 merge 被阻塞,形成死锁。
- 快照仓库与数据盘同盘:快照写入把数据盘写满,直接触发 flood。
_all/_settings解块忘记确认空间:反复只读。- 磁盘满时删除文档:
read_only_allow_delete允许删除,但删除产生新段,短期内磁盘占用可能不降反升。
7.4 定期巡检
每月做一次容量巡检:核对增长趋势与外推结果、检查是否有超大分片或过小分片、确认 ILM 策略按预期执行、验证快照是否成功。把巡检结果记录下来,容量规划就从「拍脑袋」变成了「看数据」。
8. 总结
| 环节 | 要点 |
|---|---|
| 水位机制 | low 85% 禁迁入、high 90% 迁出、flood 95% 只读 |
| 判定粒度 | 按每个数据路径独立计算,非整机磁盘 |
| 恢复流程 | 先腾空间再解块,顺序错误会反复只读 |
| 分片大小 | 单分片 10GB 到 50GB,避免过小分片 |
| 分片数量 | 每 GB 堆不超过 20 个分片 |
| 容量估算 | 原始数据乘膨胀、副本、merge 与安全系数 |
| 扩容决策 | 先诊断失衡与增长,再决定垂直或水平扩容 |
| 长期治理 | ILM 分层加定期巡检,把水位挡在触发之前 |
磁盘水位是一条不能靠运气跨越的红线:它平时不发声,一旦触发就是写入中断。把容量规划做成有数据支撑的常规流程,比任何应急手册都可靠。存储分层是控制水位的长期手段,而把冷数据搬到对象存储、仍保留查询能力,则是可搜索快照要解决的问题。
延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。