Elasticsearch 快照备份到 NAS(NFS)实战:SLM 自动化 + 365 天保留策略

Elasticsearch 快照备份到 NAS(NFS)实战:SLM 自动化 + 365 天保留策略

ES 的数据安全只有一道保险:snapshot 快照。但第一次配备份的人几乎都会卡在同一个地方------仓库挂上了、一备份就报 Permission Denied,根因是 NFS 权限走数字 UID,而各节点的 ES 启动用户 UID 不一致。本文给出一套完整落地方案:统一 UID/GID → NAS 导出 → 挂载 → 注册仓库 → SLM 策略每天凌晨 2 点自动备份、保留 365 天,附恢复演练命令。全程可在 Kibana Dev Tools 复现。
📚 前置阅读:备份的粒度从索引规划开始。《Elasticsearch 日志索引设计:按小时切分 + Rollover 兜底》讲了怎么把日志索引切整齐------索引边界清楚了,备份和过期删除才有干净的抓手。

一、方案总览

项目 内容
目标 日志索引(示例 logs-app-*)每日自动快照,备份到 NAS,保留 365 天
技术栈 Elasticsearch Snapshot and Restore + SLM(Snapshot Lifecycle Management) + NFS v4
核心要求 所有节点的 ES 启动用户 UID/GID 必须严格一致

为什么 UID 是第一位的:NFS 文件系统做权限校验时认的是数字 UID/GID ,不是用户名。ES 集群所有节点都要往同一个 NFS 目录写快照,只要有一台机器的 elastic 用户 UID 和别人不同,那台机器写出来的文件其他节点读不了,快照直接报错。专用 NAS(群晖/威联通)同理,要在权限设置里映射到相同 UID。

二、第一步:统一 UID/GID(关键前置)

先在所有 ES 节点检查当前用户:

bash 复制代码
cat /etc/passwd | grep '^elastic'
elastic:x:1004:1004::/home/elastic:/bin/bash

如果各节点输出不一致(比如有 1004:1004 也有 1005:1005),必须统一。假设规划目标为 1005:1005(选一个未被占用的 ID):

bash 复制代码
# 1. 修改组 GID
groupmod -g 1005 elastic
# 2. 修改用户 UID
usermod -u 1005 elastic

改完必须修正文件所有权------UID 变了,原目录下所有文件的属主数字对不上,ES 起不来是常事:

bash 复制代码
# 数据/日志/配置目录,按实际路径替换
chown -R elastic:elastic /data/elasticsearch
# 挂载点如果已存在也要修
chown -R elastic:elastic /mnt/es_snapshots

此时不用急着重启 ES ,等后面 path.repo 改完统一滚动重启一次即可。

三、NAS 端与挂载配置

3.1 NAS 存储端

  1. 创建共享目录:/volume1/es_backup
  2. 配置 NFS 导出:允许 ES 集群全部节点 IP 访问
  3. 权限对齐 :NAS 是 Linux 就把目录属主设为 1005:1005;专用 NAS 在权限设置里把读写权限映射给 UID 1005

3.2 所有 ES 节点挂载

bash 复制代码
mkdir -p /mnt/es_snapshots

/etc/fstab 追加(参数已做 NFS 备份场景优化):

text 复制代码
# <NAS_IP>:<DIR>   <挂载点>          nfs  <选项>  0  0
192.168.1.100:/volume1/es_backup  /mnt/es_snapshots  nfs  defaults,hard,intr,noatime,nfsvers=4,rsize=1048576,wsize=1048576,timeo=600  0  0

参数说明:nfsvers=4 用 v4 协议;rsize/wsize 拉到 1MB 提高吞吐;hard 保证写入不静默丢(备份场景宁挂勿错);timeo=600 网络抖动容忍。

执行挂载并授权:

bash 复制代码
mount -a
df -h | grep es_snapshots        # 验证挂载
chown -R elastic:elastic /mnt/es_snapshots
chmod 750 /mnt/es_snapshots

四、ES 配置与注册仓库

4.1 所有节点修改 elasticsearch.yml

yaml 复制代码
path.repo: ["/mnt/es_snapshots"]

然后滚动重启 ES 集群(按你的部署方式:systemd 或脚本),并确认进程属主正确:

bash 复制代码
ps -ef | grep elasticsearch      # 输出应显示 elastic 用户启动

4.2 注册快照仓库

bash 复制代码
curl -X PUT --user <账号>:<密码>  "http://<ES_IP>:9200/_snapshot/nas_repo" -H 'Content-Type: application/json' -d'
{
  "type": "fs",
  "settings": {
    "location": "/mnt/es_snapshots",
    "compress": true
  }
}
'

必做连通性验证------它会逐个节点检查读写,任何一台 UID 不对都会在这里现形:

bash 复制代码
curl -X POST --user <账号>:<密码>  "http://<ES_IP>:9200/_snapshot/nas_repo/_verify?pretty"

返回包含各节点信息且无 error 即通过。

五、SLM 策略:每天凌晨 2 点自动备份

bash 复制代码
curl -X PUT --user <账号>:<密码>  "http://<ES_IP>:9200/_slm/policy/daily_backup_policy" -H 'Content-Type: application/json' -d'
{
  "schedule": "0 0 2 * * ?",
  "name": "<app-snap-{now/d}>",
  "repository": "nas_repo",
  "config": {
    "indices": "logs-app-*",
    "ignore_unavailable": true,
    "include_global_state": false
  },
  "retention": {
    "expire_after": "365d",
    "min_count": 5,
    "max_count": 400
  }
}
'

字段逐个说:

字段 含义
schedule 0 0 2 * * ? 每天 02:00 触发(Quartz 表达式)
name <app-snap-{now/d}> 快照命名模板,{now/d} 按天取日期,尖括号必带
indices logs-app-* 备份范围,按实际索引前缀替换
include_global_state false 不备份集群全局状态------不加这个,恢复时容易和现有集群状态冲突,是快照失败的常见原因
retention.expire_after 365d 保留 365 天后自动清理
min_count / max_count 5 / 400 至少留 5 份兜底,最多 400 份防 NAS 爆满

SLM 策略创建后不需要额外动作,到点自动执行;执行历史可以在 Kibana 的 Stack Management → Snapshot and Restore 里看。

六、测试与验证

6.1 手动触发一次快照

数据量小可以同步等结果:

bash 复制代码
curl -X PUT --user <账号>:<密码>  "http://<ES_IP>:9200/_snapshot/nas_repo/manual-test?wait_for_completion=true&pretty" -H 'Content-Type: application/json' -d'
{
  "indices": "logs-app-*",
  "ignore_unavailable": true,
  "include_global_state": false
}
'

数据量大改用异步(wait_for_completion=false),立即返回、后台执行:

bash 复制代码
# 查看执行中的快照
curl -X GET --user <账号>:<密码>  "http://<ES_IP>:9200/_snapshot/nas_repo/_current?pretty"

6.2 检查 NAS 侧文件权限

bash 复制代码
ls -ln /mnt/es_snapshots/indices/

输出属主是 1005 1005(数字而不是用户名)就说明 UID/GID 链路全部打通。

七、恢复演练:备份的意义在于恢复

没做过恢复演练的备份等于没有备份。 恢复建议一律用新索引名,避免覆盖现有数据:

bash 复制代码
curl -X POST "http://<ES_IP>:9200/_snapshot/nas_repo/app-snap-2026.10.27/_restore?pretty" -H 'Content-Type: application/json' -d'
{
  "indices": "logs-app-2026.01.26",
  "rename_pattern": "logs-app-(.+)",
  "rename_replacement": "restored-logs-app-$1",
  "ignore_unavailable": true,
  "include_global_state": false
}
'

rename_pattern + rename_replacement 用正则把恢复出来的索引重命名(原 logs-app-2026.01.26restored-logs-app-2026.01.26),验证无误后再决定是否替换原索引。

建议把恢复演练做成季度例行动作,并在文档里记录当时的快照名和恢复耗时。

八、故障排查三条

现象 根因 处理
日志报 Permission Denied 节点间 UID/GID 不一致,或挂载点属主不对 重新核对 /etc/passwdls -ln 挂载点、NAS 侧 UID 映射
快照创建失败 NAS 空间满 检查空间使用率,核对 retention 的 max_count
挂载超时 / 仓库验证失败 NFS 协议或防火墙问题 确认 nfsvers=4 生效、放通 2049 端口

总结

这套方案的三个要点:UID/GID 一致性是 NFS 备份的命门 (90% 的失败在这里);include_global_state: false 是快照策略的标配(否则恢复时容易踩全局状态冲突);备份必须配恢复演练(rename 恢复到新索引名验证)。SLM 接管调度和过期清理后,整套备份就只剩一件事:定期看一眼执行历史。

你们的 ES 备份是方案?快照到 NAS、HDFS 还是 S3?有没有真的用过备份救火?评论区聊聊。


方案在生产环境验证;文中索引名、IP、账号均为示例,请按实际环境替换。

相关推荐
DeepVisionary9 小时前
谷歌 Gemini Omni 1.1 Flash 正式发布:4K 视频、40 秒场景延伸,视频生成进入按 token 计费时代
python·自动化
众壹新能源科技10 小时前
功率预测误差考核怎么降?从气象源到上报口径的排查清单
运维·人工智能·自动化
St_rive16 小时前
移动端自动化环境搭建与准备
运维·自动化
INNOVIX稳石机器人17 小时前
稳石500强实战验证:从人工仓储迈向AI自主智造,给出仓储自动化升级标准答案
运维·人工智能·自动化
JXJD200417 小时前
【无标题】
人工智能·ai·自动化
聪明蛋子哟17 小时前
浏览器自动化的“持久身份”:多会话认证与Agent技能的无缝集成实践
运维·自动化
代码方舟18 小时前
零信任架构实战:基于天远手机携号转网V即时版构建自动化营销风控网关
人工智能·智能手机·架构·自动化
志栋智能18 小时前
大模型驱动运维:重构故障根因分析的“思考”逻辑
运维·服务器·重构·自动化