
2.6 Elasticsearch-快照与恢复:SLM 策略 + HDFS/S3 仓库
0. 引言
生产集群里,索引从 GB 级膨胀到 TB 级往往只需要一个促销季。一次误删 mapping、一次脚本字段爆炸,就可能让业务“归零”。快照(Snapshot)是 ES 最后的“后悔药”,而 SLM(Snapshot Lifecycle Management)把“吃药”变成了定时定量、免运维的自动化流程。本节把 SLM 与两种最主流的分布式仓库——HDFS 与 S3——串成一条完整链路:从仓库注册、SLM 策略编写、索引模板隔离、到跨集群恢复与演练,全部给出可直接落地的配置与脚本。
1. 仓库选型:HDFS vs. S3
| 维度 | HDFS 仓库(repository-hdfs) | S3 仓库(repository-s3) |
|---|---|---|
| 最终一致性 | 强一致 | 最终一致(需 s3.client.path_style_access=false+版本桶) |
| 吞吐 | 机架本地磁盘,千兆网卡 110 MB/s×节点数 | 万兆 VPC 到 S3 1 GB/s/节点,可打满 100 GbE |
| 成本 | 自建机房折旧,3 副本膨胀 3× | 按量+低频/归档,可降 70 % |
| 权限模型 | Kerberos + 文件 ACL | IAM + Bucket Policy + KMS |
| 网络隔离 | 同一 YARN 集群 | VPC Endpoint / 专线 / 公网 HTTPS |
结论:
- 离线数仓、YARN 共池、数据不出机房——选 HDFS。
- 云原生、跨 Region 容灾、希望“按量付费”——选 S3;最终一致问题用“分片并发+重试”解决。
2. 注册仓库
2.1 HDFS
# 所有数据节点安装 hadoop-hdfs-client,并放置 core-site.xml / hdfs-site.xml 到 /etc/elasticsearch/
# keystore 里放 Kerberos principal 与 keytab
bin/elasticsearch-keystore add hdfs.client.impersonation.user
bin/elasticsearch-keystore add hdfs.security.principal
bin/elasticsearch-keystore add hdfs.security.keytab
PUT _snapshot/hdfs_prod
{
"type": "hdfs",
"settings": {
"uri": "hdfs://nameservice1",
"path": "/user/elasticsearch/snapshot",
"chunk_size": "500mb",
"compress": true,
"max_restore_bytes_per_sec": "1g",
"max_snapshot_bytes_per_sec": "1g",
"security.principal": "elasticsearch@EXAMPLE.COM"
}
}
2.2 S3(以 MinIO 为例,兼容 AWS)
# 在 keystore 中写入统一的客户端名“backup”
bin/elasticsearch-keystore add s3.client.backup.access_key
bin/elasticsearch-keystore add s3.client.backup.secret_key
bin/elasticsearch-keystore add s3.client.backup.endpoint # http://minio.example.com:9000
PUT _snapshot/s3_prod
{
"type": "s3",
"settings": {
"client": "backup",
"bucket": "es-snapshot-prod",
"base_path": "slm",
"chunk_size": "1gb",
"compress": true,
"server_side_encryption": true,
"storage_class": "INTELLIGENT_TIERING",
"max_restore_bytes_per_sec": "2g",
"max_snapshot_bytes_per_sec": "2g"
}
}
3. SLM 策略:一条 DSL 管五年
SLM 把“什么时候备、保留多久、备哪些索引”三句话固化成 JSON,由 Master 节点定时触发,失败自动重试并写 .slm-history*。
3.1 核心字段
schedule:cron 表达式,注意 ES 用 UTC。name:支持<yyyy-MM-dd-HH-mm>占位符,防止重名。repository:必填,指向上一节注册的仓库名。config.indices:支持通配符,*表示全部开放索引;-*kibana*可排除系统索引。retention.expire_after:快照存活时长,支持30d、12h。retention.min_count/max_count:兜底策略,防止“删光了”。
3.2 实战:每天 02:30 备份,保留 30 天,最少 7 份
PUT _slm/policy/daily-s3
{
"schedule": "0 30 2 * * ?",
"name": "<daily-s3-{now/d}>",
"repository": "s3_prod",
"config": {
"indices": ["*","-.kibana*","-.slm-history*"],
"include_global_state": false,
"partial": false,
"metadata": {
"owner": "inf",
"purpose": "daily-backup"
}
},
"retention": {
"expire_after": "30d",
"min_count": 7,
"max_count": 60
}
}
3.3 灰度策略:按业务标签隔离
对日志集群,常见的做法是给索引打上 team:pay、team:search 的 setting,然后写两条 SLM:
"config": {
"indices": ["*"],
"include_global_state": false,
"feature_states": ["none"],
"partial": false,
"metadata": {
"filter": "team:pay"
}
}
快照名里用 <{metadata.filter}> 占位,即可在仓库路径里看到 pay-2025-11-23 这样的目录,恢复时直接 team:pay 过滤,避免“全量拉回”。
4. 快照并发调优
ES 7.10 之后支持分片级并发上传,参数在仓库层控制:
max_snapshot_bytes_per_sec:节点级限流,默认 40 MB/s。max_restore_bytes_per_sec:恢复限流,防止刷爆 IO。
S3 插件额外提供:
canned_acl:bucket-owner-full-control(跨账号必备)buffer_size:100mb(内存换并发,默认 5 MB)retry.count: 3(最终一致重试)
HDFS 插件提供:
conf.dfs.replication: 2(快照文件无需 3 副本,省空间)conf.dfs.client.use.datanode.hostname: true(DNS 解析,避免 IP 漂移)
5. 跨集群恢复:一键“克隆”
场景:新集群做压测,需要 1 TB 线上数据,但不想走 reindex。步骤:
- 新集群注册同一个仓库(只读即可)。
- 查看快照列表:
GET _snapshot/s3_prod/_all - 按索引粒度恢复,并改名:
POST _snapshot/s3_prod/daily-s3-2025-11-22/_restore { "indices": "pay-order-2025-11-22", "rename_pattern": "(.+)", "rename_replacement": "restore_$1", "include_global_state": false, "index_settings": { "number_of_replicas": 0, "refresh_interval": "-1" } } - 观察集群
cat/recovery;完成后把副本调成 1,refresh 调成 1s,即可对外服务。
注意:S3 最终一致可能导致
IndexShardSnapshotFailedException——ES 7.17 已内置重试,若仍失败,手动DELETE snapshot后重跑 SLM。
6. 灾备演练:把“备份”变“可用”
真正灾难时,恢复时间 = 快照下载 + translog replay + 业务验证。演练脚本(bash + jq):
#!/bin/bash
REPO=s3_prod
SNAP=daily-s3-$(date -d '-1 day' +%F)
TARGET=restore_$(date +%s)
# 1. 找到最大的 5 个索引
INDICES=$(curl -s -XGET "localhost:9200/_cat/indices?bytes=b&h=index,store.size" | \
sort -k2 -nr | head -5 | awk '{print $1}' | paste -sd,)
# 2. 恢复
curl -XPOST "localhost:9200/_snapshot/$REPO/$SNAP/_restore?wait_for_completion=false" -H "Content-Type: application/json" -d"
{
\"indices\": \"$INDICES\",
\"rename_pattern\": \"(.+)\",
\"rename_replacement\": \"${TARGET}_$1\",
\"include_global_state\": false,
\"index_settings\": {
\"number_of_replicas\": 0
}
}"
# 3. 轮询 recovery
until [[ $(curl -s "localhost:9200/_cat/recovery?h=stage" | grep -c done) -eq $(echo $INDICES | tr ',' '\n' | wc -l) ]]; do
sleep 30
done
# 4. 校验 doc 数
for idx in $(echo $INDICES | tr ',' '\n'); do
ori=$(curl -s "localhost:9200/$idx/_count" | jq -r .count)
new=$(curl -s "localhost:9200/${TARGET}_${idx}/_count" | jq -r .count)
echo "$idx $ori -> ${TARGET}_${idx} $new"
done
跑完输出:
pay-order-2025-11-22 512345678 -> restore_1732231200_pay-order-2025-11-22 512345678
数量一致即演练通过;最后批量 DELETE restore_* 清理。
7. 监控与告警
SLM 会把每次执行结果写到 .slm-history-7-*,配套 Kibana 规则:
{
"name": "SLM 连续失败 2 次",
"type": "count",
"index": ".slm-history-*",
"time_field": "@timestamp",
"query": "result:FAILED",
"threshold": 2,
"window": "1h",
"actions": {
"webhook": {
"url": "https://alert.example.com/webhook/slm",
"body": "{\"text\":\"SLM 连续失败 2 次,请检查仓库权限或磁盘空间\"}"
}
}
}
同时监控仓库级指标:
es_snapshot_stats{state=STARTED}长时间不下降 → 卡住。es_repository_s3_chunk_upload_bytes增长缓慢 → 限流或网络瓶颈。
8. 常见问题速查
Q1:快照卡在 “intializing” 不动?
→ 查看 Master log,大概率是 repository 路径权限问题;S3 检查 IAM 是否忘开 s3:AbortMultipartUpload。
Q2:恢复后索引 red?
→ 原集群有 5 主分片,新集群只有 3 数据节点,且 cluster.routing.allocation.awareness.force.zone.values 限制导致分片无法分配;临时 PUT settings {"number_of_replicas":0} 即可。
Q3:SLM 保留策略没删快照?
→ 快照正被恢复或仍在进行中;SLM 会跳过“in-use”快照,先 DELETE /_snapshot/repo/snap 手动删,再查 .slm-history 看报错。
9. 小结
- 仓库先决:HDFS 重权限,S3 重一致;先把
keystore与 IAM 搞对,再谈备份。 - SLM 三板斧:
schedule定时、retention定寿、indices定范围;配合通配符与元数据,能做到“千人千面”的备份策略。 - 灾备不是“有快照”就行,而是“敢恢复”。每月一次演练,把
max_restore_bytes_per_sec拉到 2 GB/s,测出真实 RTO,写进 On-Call 手册。
把这一节配置直接粘进集群,明天凌晨 02:30,第一枚自动快照就会悄悄生成;当你某天真的“手抖”删了索引,只需一条 _restore,数据就能在分钟级回到任何你想要的时间点——这就是 SLM 与分布式仓库给 Elasticsearch 带来的“时间回溯”能力。
更多技术文章见公众号: 大城市小农民

被折叠的 条评论
为什么被折叠?



