集群管理
Elasticsearch 集群是由一个或多个节点组成的分布式系统,共同存储数据并提供搜索服务。本章将介绍集群的架构设计、配置管理和运维技巧,帮助你构建和管理稳定高效的 Elasticsearch 集群。
集群架构基础
节点类型
Elasticsearch 集群中的节点可以承担不同的角色,每种角色负责特定的功能:
| 节点类型 | 配置 | 职责 |
|---|---|---|
| Master | node.roles: [master] | 管理集群状态、创建/删除索引、分配分片 |
| Data | node.roles: [data] | 存储数据、执行搜索和聚合 |
| Ingest | node.roles: [ingest] | 预处理管道,转换文档 |
| Coordinating | node.roles: [] | 处理请求、路由分发、结果合并 |
| ML | node.roles: [ml] | 机器学习任务处理 |
节点角色组合:
节点可以同时拥有多个角色。例如,小型集群中节点通常同时是 Master 和 Data 节点:
node.roles: [master, data]
大型生产集群通常会将角色分离,实现更好的资源隔离和管理:
# 专用 Master 节点(3 个,避免脑裂)
node.roles: [master]
# 专用 Data 节点(多个,水平扩展)
node.roles: [data]
# 协调节点(处理请求路由)
node.roles: []
集群健康状态
GET /_cluster/health
响应示例:
{
"cluster_name": "my-cluster",
"status": "green",
"number_of_nodes": 3,
"number_of_data_nodes": 2,
"active_primary_shards": 10,
"active_shards": 20,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0
}
状态说明:
| 状态 | 含义 | 可能原因 |
|---|---|---|
| green | 所有分片正常分配 | 集群健康 |
| yellow | 主分片正常,副本未分配 | 单节点集群、节点故障 |
| red | 部分主分片未分配 | 节点故障、磁盘问题 |
集群架构图解
一个典型的三节点集群架构:
┌─────────────────────────────────────────────────────────────┐
│ Elasticsearch 集群 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 节点1 (Master + Data) 节点2 (Master + Data) │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Master 候选 │ │ Master 候选 │ │
│ │ P0 P1 P2 │ │ P0 P1 P2 │ 主分片 │
│ │ R1 R2 │ │ R0 │ 副本分片 │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ 节点3 (Data only) │
│ ┌─────────────────┐ │
│ │ R0 R1 R2 │ 只存储副本,不参与选主 │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
P0, P1, P2 = 主分片 (Primary Shard)
R0, R1, R2 = 副本分片 (Replica Shard)
集群配置
基本配置
每个节点都需要配置 elasticsearch.yml 文件:
# 集群名称(同一集群必须相同)
cluster.name: my-application
# 节点名称(同一集群必须唯一)
node.name: node-1
# 节点角色
node.roles: [master, data]
# 网络配置
network.host: 0.0.0.0
http.port: 9200
transport.port: 9300
# 发现配置
discovery.seed_hosts: ["node-1", "node-2", "node-3"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
# 内存锁定
bootstrap.memory_lock: true
配置详解:
| 配置项 | 说明 |
|---|---|
cluster.name | 集群名称,用于节点发现和隔离 |
node.name | 节点名称,默认自动生成 |
network.host | 绑定的网络接口,0.0.0.0 表示所有接口 |
discovery.seed_hosts | 种子节点列表,用于发现其他节点 |
cluster.initial_master_nodes | 初始 Master 候选列表,首次启动时使用 |
三节点集群配置示例
节点 1 配置(Master + Data):
cluster.name: my-cluster
node.name: node-1
node.roles: [master, data]
network.host: 192.168.1.10
http.port: 9200
transport.port: 9300
discovery.seed_hosts: ["192.168.1.10", "192.168.1.11", "192.168.1.12"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
节点 2 配置(Master + Data):
cluster.name: my-cluster
node.name: node-2
node.roles: [master, data]
network.host: 192.168.1.11
http.port: 9200
transport.port: 9300
discovery.seed_hosts: ["192.168.1.10", "192.168.1.11", "192.168.1.12"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
节点 3 配置(Data only):
cluster.name: my-cluster
node.name: node-3
node.roles: [data] # 只作为数据节点
network.host: 192.168.1.12
http.port: 9200
transport.port: 9300
discovery.seed_hosts: ["192.168.1.10", "192.168.1.11", "192.168.1.12"]
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
避免脑裂
脑裂(Split Brain)是指集群被网络分区后,两个分区各自选举出 Master,导致数据不一致。预防措施:
1. 设置最小 Master 数量
# 在 Elasticsearch 7.x+ 中,通过投票配置自动管理
# 但仍建议保持奇数个 Master 候选节点(3、5、7)
2. 自动处理投票配置排除
# 查看当前投票配置
GET /_cluster/state?filter_path=metadata.cluster_coordination
# 排除故障节点
POST /_cluster/voting_config_exclusions/node-3
# 清除排除配置
DELETE /_cluster/voting_config_exclusions
分片管理
分片分配设置
# 查看分配设置
GET /_cluster/settings?include_defaults=true&filter_path=**.allocation.*
# 设置分片分配
PUT /_cluster/settings
{
"persistent": {
"cluster.routing.allocation.enable": "all",
"cluster.routing.allocation.cluster_concurrent_rebalance": 2,
"cluster.routing.allocation.node_concurrent_recoveries": 2,
"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.enable | 分配策略:all、primaries、new_primaries、none |
cluster_concurrent_rebalance | 集群级别并发重平衡数 |
node_concurrent_recoveries | 节点级别并发恢复数 |
disk.watermark.low | 低水位,超过后不再向该节点分配新分片 |
disk.watermark.high | 高水位,超过后尝试迁移分片 |
disk.watermark.flood_stage | 洪水水位,超过后将索引设为只读 |
分片分配过滤
可以将特定索引分配到特定节点:
# 节点属性配置(elasticsearch.yml)
node.attr.rack: rack1
# 分配规则
PUT /_cluster/settings
{
"persistent": {
"cluster.routing.allocation.include._attr": "rack:rack1",
"cluster.routing.allocation.exclude._name": "node-3"
}
}
手动移动分片
POST /_cluster/reroute
{
"commands": [
{
"move": {
"index": "articles",
"shard": 0,
"from_node": "node-1",
"to_node": "node-2"
}
}
]
}
分片重平衡控制
PUT /_cluster/settings
{
"persistent": {
"cluster.routing.rebalance.enable": "all",
"cluster.routing.balance.shard": 0.45,
"cluster.routing.balance.index": 0.55,
"cluster.routing.balance.threshold": 1.0
}
}
集群监控
集群状态 API
# 集群健康
GET /_cluster/health?pretty
# 集群状态
GET /_cluster/state?pretty
# 集群统计
GET /_cluster/stats?pretty
# 节点统计
GET /_nodes/stats?pretty
Cat API
Cat API 提供简洁的文本输出,适合命令行查看:
# 查看节点
GET /_cat/nodes?v
# 查看分片
GET /_cat/shards?v
# 查看索引
GET /_cat/indices?v
# 查看分配情况
GET /_cat/allocation?v
# 查看恢复状态
GET /_cat/recovery?v
# 查看线程池
GET /_cat/thread_pool?v
# 查看主节点
GET /_cat/master?v
常用查询参数:
v:显示列名h:指定显示的列s:排序format=json:JSON 格式输出
# 示例:查看节点的堆内存使用率
GET /_cat/nodes?v&h=name,heap.percent,ram.percent,cpu
# 示例:按文档数排序索引
GET /_cat/indices?v&s=docs.count:desc
关键监控指标
1. JVM 指标
GET /_nodes/stats?filter_path=nodes.*.jvm
关注:
heap_used_percent:堆内存使用率,建议不超过 75%gc:垃圾回收频率和时间
2. 线程池指标
GET /_nodes/stats?filter_path=nodes.*.thread_pool
关注:
search、write队列情况rejected拒绝数量
3. 磁盘指标
GET /_cat/allocation?v
4. 索引性能
GET /_nodes/stats?filter_path=nodes.*.indices.indexing
故障处理
节点故障
当节点故障时,集群会自动处理:
# 查看未分配的分片
GET /_cat/shards?v&s=state
# 解释分片未分配原因
GET /_cluster/allocation/explain
{
"index": "articles",
"shard": 0,
"primary": true
}
# 重试分配
POST /_cluster/reroute?retry_failed=true
常见未分配原因:
| 原因 | 解决方法 |
|---|---|
| NODE_LEFT | 节点离线,等待恢复或添加新节点 |
| ALLOCATION_FAILED | 分配失败,查看日志,重试分配 |
| DECIDERS_NO | 分配器拒绝,检查配置限制 |
| DISK_WATERMARK | 磁盘空间不足,清理或扩容 |
集群重启
滚动重启过程:
# 步骤1:禁用分片分配
PUT /_cluster/settings
{
"persistent": {
"cluster.routing.allocation.enable": "primaries"
}
}
# 步骤2:执行同步刷新
POST /_flush/synced
# 步骤3:停止节点(逐个进行)
systemctl stop elasticsearch
# 步骤4:维护完成后启动节点
systemctl start elasticsearch
# 步骤5:等待节点加入集群
GET /_cat/health
# 步骤6:重复步骤3-5,处理所有节点
# 步骤7:恢复分片分配
PUT /_cluster/settings
{
"persistent": {
"cluster.routing.allocation.enable": "all"
}
}
数据恢复
# 查看恢复进度
GET /_cat/recovery?v&active_only=true
# 取消恢复
POST /_cluster/reroute
{
"commands": [
{
"cancel": {
"index": "articles",
"shard": 0,
"node": "node-1"
}
}
]
}
快照和恢复
创建仓库
# 创建文件系统仓库
PUT /_snapshot/my_backup
{
"type": "fs",
"settings": {
"location": "/mount/backups/my_backup",
"compress": true
}
}
# 创建 S3 仓库
PUT /_snapshot/s3_backup
{
"type": "s3",
"settings": {
"bucket": "my-bucket",
"region": "us-east-1",
"base_path": "elasticsearch/snapshots"
}
}
# 创建 Azure 仓库
PUT /_snapshot/azure_backup
{
"type": "azure",
"settings": {
"container": "backup-container",
"base_path": "elasticsearch"
}
}
创建快照
# 快照所有索引
PUT /_snapshot/my_backup/snapshot_1
# 快照指定索引
PUT /_snapshot/my_backup/snapshot_2
{
"indices": "articles,products",
"ignore_unavailable": true,
"include_global_state": false
}
# 查看快照进度
GET /_snapshot/my_backup/snapshot_1/_status
# 查看所有快照
GET /_snapshot/my_backup/_all
恢复快照
# 恢复所有索引
POST /_snapshot/my_backup/snapshot_1/_restore
# 恢复指定索引
POST /_snapshot/my_backup/snapshot_1/_restore
{
"indices": "articles",
"ignore_unavailable": true,
"include_global_state": false,
"rename_pattern": "(.+)",
"rename_replacement": "restored_$1"
}
参数说明:
rename_pattern:匹配索引名的正则表达式rename_replacement:替换后的索引名include_global_state:是否恢复集群状态(模板、设置等)
快照生命周期管理
# 创建快照生命周期策略
PUT /_slm/policy/nightly-snapshots
{
"schedule": "0 30 1 * * ?", # 每天凌晨 1:30
"name": "<nightly-snap-{now/d}>",
"repository": "my_backup",
"config": {
"indices": ["*"],
"ignore_unavailable": true,
"include_global_state": false
},
"retention": {
"expire_after": "30d",
"min_count": 5,
"max_count": 50
}
}
小结
本章我们深入学习了 Elasticsearch 集群管理的核心知识:
- 集群架构:节点类型、角色配置、集群健康状态
- 集群配置:基本配置、多节点部署、避免脑裂
- 分片管理:分配设置、分配过滤、手动移动分片
- 集群监控:健康 API、Cat API、关键监控指标
- 故障处理:节点故障、滚动重启、数据恢复
- 快照恢复:仓库创建、快照管理、生命周期策略
练习
- 配置一个三节点的 Elasticsearch 集群,包含 2 个 Master+Data 节点和 1 个 Data 节点
- 使用 Cat API 监控集群状态,重点关注 JVM、线程池、磁盘指标
- 配置快照仓库,创建一个包含所有索引的快照
- 模拟节点故障,观察集群自动恢复过程