Elasticsearch 集群搭起来容易,运维好难。测试环境的 ES 集群跑了一年多,踩了不少坑——分片过多导致集群状态 yellow、索引膨胀磁盘满、冷数据占着热节点资源。今天把运维实践整理成笔记,给用 ES 的朋友做个参考。
一、分片策略#
1.1 分片数不是越多越好#
早期建索引时图省事,所有索引都设 5 个主分片 + 1 个副本。结果索引多了之后,集群有几千个分片,每个分片都有额外的内存开销(集群元数据、分片状态),集群状态经常 yellow,恢复慢。
正确的分片数估算:
- 单分片数据量建议 20-50GB
- 分片数 = 预估总数据量 / 30GB
- 小索引(<10GB)1个主分片就够
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| // 大索引(职位搜索,预计50GB)
PUT /job
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
// 小索引(操作日志,预计5GB)
PUT /operation_log
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
}
}
|
1.2 分片均衡#
集群节点配置不一样时,分片分配不均会导致某些节点压力大。用分片分配过滤控制:
1
2
3
4
| PUT /job/_settings
{
"index.routing.allocation.total_shards_per_node": 2
}
|
限制每个节点最多分配 2 个该索引的分片,避免热点。
二、索引生命周期管理(ILM)#
ES 7.x 自带 ILM(Index Lifecycle Management),自动管理索引的生命周期,不用自己写脚本删索引。
2.1 ILM 策略#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| PUT _ilm/policy/log_policy
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": {
"max_size": "50GB",
"max_age": "7d"
}
}
},
"warm": {
"min_age": "7d",
"actions": {
"shrink": {"number_of_shards": 1},
"forcemerge": {"max_num_segments": 1}
}
},
"cold": {
"min_age": "30d",
"actions": {
"allocate": {
"require": {"data": "cold"}
}
}
},
"delete": {
"min_age": "90d",
"actions": {
"delete": {}
}
}
}
}
}
|
四个阶段:
- hot:热数据,读写频繁,rollover 自动创建新索引
- warm:7天后转 warm,收缩分片数、合并段,减少资源占用
- cold:30天后转 cold,迁移到冷节点(低配机器)
- delete:90天后自动删除
2.2 索引模板关联 ILM#
1
2
3
4
5
6
7
8
9
10
11
12
| PUT _index_template/log_template
{
"index_patterns": ["operation_log-*"],
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"index.lifecycle.name": "log_policy",
"index.lifecycle.rollover_alias": "operation_log"
}
}
}
|
用索引模板,新建索引自动应用 ILM 策略,不用每个索引单独配置。
三、冷热分离#
热节点(高配,SSD)存近期数据,冷节点(低配,机械盘)存历史数据,降低成本。
3.1 节点标记#
1
2
3
| # 启动时指定节点属性
bin/elasticsearch -Enode.attr.data=hot
bin/elasticsearch -Enode.attr.data=cold
|
3.2 索引分配#
1
2
3
4
| PUT /operation_log-2022.10/_settings
{
"index.routing.allocation.require.data": "cold"
}
|
ILM 的 cold 阶段会自动执行这个操作,把索引迁移到冷节点。
四、备份恢复#
4.1 快照仓库#
1
2
3
4
5
6
7
8
| PUT _snapshot/es_backup
{
"type": "fs",
"settings": {
"location": "/data/es_backup",
"compress": true
}
}
|
4.2 自动快照#
用 Curator 或 cron 定时创建快照:
1
2
| # 每天凌晨备份
curl -X PUT "localhost:9200/_snapshot/es_backup/snapshot_$(date +%Y%m%d)?wait_for_completion=true"
|
4.3 恢复#
1
2
3
4
5
6
7
| # 恢复指定索引
curl -X POST "localhost:9200/_snapshot/es_backup/snapshot_20221015/_restore" -H 'Content-Type: application/json' -d'
{
"indices": "job",
"ignore_unavailable": true,
"include_global_state": false
}'
|
五、常见问题排查#
5.1 集群状态 yellow#
yellow 表示主分片都分配了,但有副本没分配。排查:
1
2
3
4
5
6
7
8
9
10
| # 查看未分配的分片
curl "localhost:9200/_cat/shards?v&h=index,shard,prirep,state,unassigned.reason" | grep UNASSIGNED
# 查看未分配原因
curl "localhost:9200/_cluster/allocation/explain" -H 'Content-Type: application/json' -d'
{
"index": "job",
"shard": 0,
"primary": false
}'
|
常见原因:磁盘满(>85%)、分片分配策略限制、节点下线。
5.2 查询慢#
1
2
3
4
5
6
7
8
9
10
11
12
13
| # 开启慢查询日志
PUT /job/_settings
{
"index.search.slowlog.threshold.query.warn": "5s",
"index.search.slowlog.threshold.query.info": "2s"
}
# 用 profile API 分析查询
POST /job/_search
{
"profile": true,
"query": { ... }
}
|
5.3 磁盘满#
- 检查索引大小:
_cat/indices?v&s=store.size:desc - 删除无用索引
- 调整 ILM 策略,更早删除或转冷
- 扩容磁盘
六、总结#
Elasticsearch 集群运维核心要点:
- 分片合理:根据数据量估算分片数,不是越多越好,单分片 20-50GB
- ILM 自动化:用索引生命周期管理自动 rollover、收缩、迁移、删除,不用人工干预
- 冷热分离:热数据放高配节点,冷数据迁低配节点,降低成本
- 备份不可少:定期快照备份,关键时刻能恢复
- 监控要到位:集群状态、节点资源、索引大小、查询延迟,都要监控告警
- 问题会排查:yellow 状态、慢查询、磁盘满,这些常见问题要会快速定位
ES 运维是个持续的过程,业务在变,数据在涨,索引设计和 ILM 策略也要跟着调整。定期 review 集群状态,提前发现问题,比出了问题再救火成本低得多。