3. 集群拓扑与容量规划

Elasticsearch 集群的稳定性和查询性能,很大程度上不取决于单机配置有多高,而取决于节点角色是否划分清楚、分片与副本是否规划合理。一个常见的误区是:把所有节点都配成“什么都能干”的默认角色,结果主节点被查询流量拖垮、协调节点成为瓶颈、数据节点磁盘写满却无法迁移分片。本节围绕集群拓扑与容量规划,讲清楚角色划分、冷热分层、分片副本设计这三条主线。

一、节点角色划分:让每类节点只做擅长的事

Elasticsearch 节点角色由 node.roles 控制。生产集群通常把角色拆分为以下几类:

  • 主节点(master):负责集群状态管理,如索引创建、分片分配、节点上下线。主节点不存储业务数据,也不处理查询。它维护的是集群元数据(cluster state),因此对 CPU 和网络延迟敏感,对磁盘和内存要求不高。
  • 数据节点(data):存储分片、执行读写和聚合。数据节点是资源消耗的主体,需要大内存、高 IO 磁盘和较强 CPU。可进一步细分为 data_hot、data_warm、data_cold、data_frozen,对应冷热架构。
  • 协调节点(coordinating):只做请求分发与结果聚合,不存数据、不参与主节点选举。它承担“查询入口”的角色,适合用中等配置、多实例部署,避免单点。
  • 摄取节点(ingest):执行 pipeline 预处理,如字段解析、富化。若写入量大且 pipeline 复杂,应独立部署,避免抢占数据节点资源。
  • 专用主节点(dedicated master):只做 master,不承担其他角色,是生产环境推荐做法。

角色划分的核心原则是“职责隔离”:主节点不被查询拖累,协调节点不存数据,数据节点专注存储与计算。一个典型的中大型集群拓扑如下:3 台专用主节点、若干协调节点、按热/温/冷分层的多组数据节点,以及可选的摄取节点。

Elasticsearch 集群角色拓扑(示例) 客户端 / Kibana 查询与写入请求 协调节点 ×3 分发请求 / 聚合结果 专用主节点 ×3 集群状态 / 分片分配 摄取节点 ×2 pipeline 预处理 数据节点分层(冷热架构) Hot 层 SSD / 高 CPU / 大内存 承接实时写入与高频查询 副本数 ≥1,保证写入可用 Warm 层 SATA SSD / 中等配置 存放近周期历史数据 查询频率下降,可合并段 Cold 层 大容量 HDD / 低配 CPU 归档数据,偶尔查询 可设副本数 0 节省空间 ILM ILM 分片与副本分布(索引 logs-2024.06,主分片 3,副本 1) P0 P1 P2 R0 R1 R2

二、主节点:集群的“大脑”,必须专用且奇数

主节点负责维护集群状态。集群状态包含所有索引的映射、设置、分片分配信息,默认会同步到每个节点。主节点数量必须是奇数,推荐 3 台,可容忍 1 台故障;5 台可容忍 2 台。生产环境应设置 discovery.seed_hosts 和 cluster.initial_master_nodes,并配置 node.master: true 且 node.data: false。

主节点被查询拖垮的典型表现是:集群状态更新变慢、分片分配卡住、GET _cluster/health 返回 master_not_discovered_exception。因此,专用主节点应避免承担协调和数据角色,内存建议 4~8 GB,CPU 2~4 核即可。

三、数据节点与冷热架构:按数据生命周期分层

冷热架构的本质是:数据从“热”到“冷”迁移,存储成本递减,查询性能递减。实现方式是通过 ILM(Index Lifecycle Management)策略,按索引年龄或大小触发 rollover 和迁移。

一个可参考的 ILM 策略示例(示例参数,非实测):

PUT _ilm/policy/logs_policy
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": { "max_size": "50gb", "max_age": "1d" },
          "set_priority": { "priority": 100 }
        }
      },
      "warm": {
        "min_age": "7d",
        "actions": {
          "forcemerge": { "max_num_segments": 1 },
          "shrink": { "number_of_shards": 1 },
          "allocate": { "require": { "data": "warm" } }
        }
      },
      "cold": {
        "min_age": "30d",
        "actions": {
          "allocate": { "require": { "data": "cold" } },
          "freeze": {}
        }
      },
      "delete": {
        "min_age": "180d",
        "actions": { "delete": {} }
      }
    }
  }
}

热层节点使用 SSD,副本数至少 1;温层可做 forcemerge 和 shrink,减少分片数;冷层可设副本 0,用 HDD 存储。迁移过程中要观察 _cat/shards 的 RELOCATING 状态,确认分片迁移完成后再进入下一阶段。

四、分片与副本设计:容量规划的核心

分片数一旦设定,后期只能通过 reindex 或 shrink/split 调整,因此初期规划至关重要。经验规则:单个分片大小控制在 10~50 GB,搜索场景建议 20~30 GB;分片总数控制在每 GB 堆内存 20~25 个分片以内。

假设一个日志索引每天写入 200 GB,保留 30 天,副本 1。若按每天一个索引、每个索引 5 个主分片,则单分片约 40 GB,处于合理区间。总主分片数 = 30 天 × 5 = 150,副本分片 150,总分片 300。若集群有 6 个数据节点,每节点约 50 个分片,堆内存 16 GB 时每 GB 约 3 个分片,远低于 20 的上限,属于健康范围。

副本设计要考虑:副本提高查询吞吐和容错,但增加存储和写入放大。热层副本 ≥1;温层可保持 1;冷层可降为 0。副本数不能超过数据节点数,否则分片无法分配,集群健康状态会变为 yellow。

容量规划时,先算存储:原始数据 × (1 + 副本数) × 1.1(索引开销)× 1.2(预留空间)。再算分片:总数据量 ÷ 单分片目标大小。最后算节点:总分片数 ÷ 每节点建议分片数。

五、协调节点与查询路径

协调节点接收客户端请求,将查询分发到相关分片所在的数据节点,再合并结果返回。它不存数据,因此可以水平扩展。当查询 QPS 高、聚合复杂时,增加协调节点比升级数据节点更有效。协调节点配置建议:node.roles: [],即不承担任何数据或主节点角色。

查询路径为:客户端 → 协调节点 → 数据节点(分片)→ 协调节点聚合 → 客户端。若协调节点过少,会出现请求排队;若过多,会增加网络跳数。一般按每 3~5 个数据节点配 1 个协调节点估算。

六、容量规划检查清单

检查项建议值 / 判断依据
专用主节点数量3 台(奇数),不承担数据与协调角色
单分片大小10~50 GB,搜索场景 20~30 GB
每 GB 堆内存分片数≤ 20~25 个
热层副本数≥ 1
冷层副本数可为 0,节省存储
磁盘使用率低于 85%,预留迁移空间
集群健康状态green;yellow 表示副本未分配

最后强调:拓扑和容量不是一次规划就固定不变的。随着数据量增长和查询模式变化,应定期用 _cat/indices?v、_cat/shards、_nodes/stats 观察分片分布、磁盘水位和节点负载,再决定是否调整分片数、迁移冷热层或增加协调节点。