Elasticsearch 索引备份与恢复实践(基于 NFS 共享仓库)

一、环境准备

1.1 搭建 NFS 共享存储(用于存放快照文件)

在 NFS 服务端(例如 IP 192.168.100.100)安装并配置:

bash 复制代码
# 安装 NFS 服务
yum install nfs-utils -y

# 创建共享目录
mkdir -p /data/share

# 配置 exports(允许 172.16.19.0/24 网段读写)
cat > /etc/exports <<EOF
/data/share 192.168.100.0/24(rw,sync,no_subtree_check,no_root_squash,insecure)
EOF

# 启动并设置开机自启
systemctl start nfs-server
systemctl enable nfs-server
exportfs -ra

1.2 在每个 Elasticsearch 节点上挂载 NFS

bash 复制代码
# 安装 NFS 客户端
yum install nfs-utils -y

# 创建挂载点
mkdir -p /opt/nfs

# 挂载 NFS(假设服务端 IP 为 192.168.100.100)
mount 192.168.100.100:/data/share /opt/nfs

# 设置开机自动挂载(可选)
echo "192.168.100.100:/data/share /opt/nfs nfs defaults 0 0" >> /etc/fstab

1.3 调整目录权限

Elasticsearch 默认以 elasticsearch 用户运行,必须赋予该用户写入权限:

bash 复制代码
chown -R elasticsearch:elasticsearch /opt/nfs
chmod 755 /opt/nfs

1.4 配置 Elasticsearch 仓库路径

编辑每个节点的 elasticsearch.yml,添加:

yaml 复制代码
path.repo: ["/opt/nfs"]

重启 Elasticsearch 服务(每个节点依次重启,节点恢复后再启动另外一个节点):

bash 复制代码
systemctl restart elasticsearch

二、创建快照仓库

在任意节点上执行,定义仓库名称为 ESbak_nfs,类型为 fs(文件系统):

bash 复制代码
curl -XPUT -H 'Content-Type: application/json' localhost:9200/_snapshot/ESbak_nfs -d '{
  "type": "fs",
  "settings": {
    "location": "/opt/nfs"
  }
}'

查看已创建的仓库:

bash 复制代码
curl -XGET "localhost:9200/_snapshot/_all"

三、准备测试数据(可选)

为验证备份恢复功能,可写入 1000 条测试数据到索引 index:

bash 复制代码
for i in {1..1000}; do
  echo '{"index":{"_index":"index"}}'
  echo "{\"id\":$i,\"name\":\"user$i\",\"timestamp\":\"$(date -Iseconds)\"}"
done | curl -XPOST "http://localhost:9200/_bulk" -H "Content-Type: application/json" --data-binary @-

确认文档数量:

bash 复制代码
curl -XGET "http://localhost:9200/index/_count"

四、创建快照备份

4.1 备份所有索引(包含集群状态)

bash 复制代码
curl -XPUT "localhost:9200/_snapshot/ESbak_nfs/snapshot_all?wait_for_completion=true"

4.2 备份指定索引(推荐)

只备份名为 index 的索引,不备份集群全局状态:

bash 复制代码
curl -XPUT "localhost:9200/_snapshot/ESbak_nfs/202605271422?wait_for_completion=true" \
  -H "Content-Type: application/json" \
  -d '{
    "indices": "index",
    "ignore_unavailable": true,
    "include_global_state": false
  }'
  • indices:支持通配符和逗号分隔,如 "index1,index2" 或 "log-*"。
  • ignore_unavailable:当指定索引不存在或关闭时忽略错误。
  • include_global_state:设为 false 只备份索引数据,避免还原时覆盖模板、ILM 策略等。

4.3 备份执行结果示例

成功时会返回 JSON 响应,其中 "state":"SUCCESS" 表示成功:

json 复制代码
{
  "snapshot": {
    "snapshot": "202605271422",
    "state": "SUCCESS",
    "shards": {"total": 6, "failed": 0, "successful": 6}
  }
}

五、验证备份

5.1 查看单个快照信息

bash 复制代码
curl -XGET "localhost:9200/_snapshot/ESbak_nfs/202605271422"

5.2 列出仓库所有快照

bash 复制代码
curl -XGET "localhost:9200/_snapshot/ESbak_nfs/_all"

5.3 查看快照中各索引分片状态

bash 复制代码
curl -XGET "localhost:9200/_snapshot/ESbak_nfs/202605271422/_status"

六、从快照恢复

6.1 恢复到同集群的另一个索引(不覆盖原索引)

bash 复制代码
curl -XPOST "localhost:9200/_snapshot/ESbak_nfs/202605271422/_restore" \
  -H "Content-Type: application/json" \
  -d '{
    "indices": "index",
    "rename_pattern": "index",
    "rename_replacement": "index_restored",
    "include_global_state": false
  }'

恢复完成后,新索引 index_restored 拥有原快照的全部数据。

6.3 跨集群迁移(备份转移到新集群)

步骤一:将 NFS 目录下的快照文件复制到新集群可访问的共享存储

假设新集群使用相同的 NFS 路径 /opt/nfs,只需确保新集群各节点能挂载同一 NFS 共享(或复制整个目录)。

步骤二:新集群同样配置 path.repo 并重启

在每台新节点上执行:

bash 复制代码
mkdir -p /opt/nfs
mount 192.168.100.100:/data/share /opt/nfs
chown elasticsearch:elasticsearch /opt/nfs
echo "path.repo: [\"/opt/nfs\"]" >> /etc/elasticsearch/elasticsearch.yml
systemctl restart elasticsearch
步骤三:新集群创建同名仓库并恢复
bash 复制代码
# 创建仓库(与旧集群配置完全相同)
curl -XPUT -H 'Content-Type: application/json' localhost:9200/_snapshot/ESbak_nfs -d '{
  "type": "fs",
  "settings": {"location": "/opt/nfs"}
}'

# 验证快照已自动发现
curl -XGET "localhost:9200/_snapshot/ESbak_nfs/_all"

# 恢复索引
curl -XPOST "localhost:9200/_snapshot/ESbak_nfs/202605271422/_restore" \
  -H "Content-Type: application/json" \
  -d '{
    "indices": "index",
    "include_global_state": false
  }'

七、常见问题及解决方案

7.1 access_denied_exception

现象 :failed to update snapshot in repository ... /opt/nfs/meta-*.dat (Permission denied)

原因:Elasticsearch 进程对 NFS 目录无写权限。

解决:

  • 确保 NFS 导出选项包含 rw 且客户端挂载为读写模式(mount | grep /opt/nfs 应含 rw)。
  • 修改目录所有者为 elasticsearch 并设置 755 权限。
  • 如果已挂载为只读,重新挂载:mount -o remount,rw /opt/nfs

7.2 快照包含非预期的系统索引

现象 :备份时尽管只指定 "indices":"index",返回结果中仍出现 .ds-*、.geoip_databases 等索引。

原因 :未设置 "include_global_state":false 时,快照可能自动包含数据流及系统索引。

解决 :在创建快照的请求中明确添加 "include_global_state": false。

7.3 恢复时提示索引已存在

现象 :"reason": "cannot restore index [index] because an open index with same name already exists"

解决 :按 6.2 节先删除原索引,或使用 rename_pattern / rename_replacement 恢复到不同名称。

八、最佳实践建议

  • 定期验证:生产环境应定期执行恢复演练,验证快照完整性。
  • 命名规范 :快照名称建议包含日期时间(如 snapshot_20260527_1422),便于管理。
  • 仅备份必要数据 :通过 indices 参数仅备份业务索引,避免系统索引和无关数据。
  • 使用共享存储:多节点集群必须使用共享文件系统(NFS、HDFS、S3 等),否则快照无法被所有节点访问。
  • 监控磁盘空间:快照目录需预留足够容量,可配合 ILM 自动清理旧快照。

九、总结

利用 Elasticsearch 的快照功能结合 NFS 共享存储,可以高效实现:

  • 指定索引的定时备份
  • 同集群内快速恢复或克隆索引
  • 跨集群数据迁移(更换集群、升级版本等)

通过以上步骤,您可以安全、可控地管理 Elasticsearch 索引的生命周期,确保数据高可用性。

相关推荐
xbgRS41 分钟前
Elasticsearch的查询
elasticsearch
Elasticsearch4 小时前
使用 Lucene 搜索你的 Bean —— Highlighting
elasticsearch
Elasticsearch4 小时前
使用 Lucene 搜索你的 Bean —— Elasticsearch
elasticsearch
Elasticsearch9 小时前
最好的 LLM 只有 59% 的时间能写出正确的 Elasticsearch ES|QL。以下是另外 41% 出错的原因
elasticsearch
垚垚学技术_聚焦云原生9 小时前
Ansible Role 生产环境标准目录结构与规范化实践
java·elasticsearch·ansible
小林ixn10 小时前
从 MySQL 的 LIKE 到 ES 倒排索引:一次把全文检索和混合检索讲透
sql·elasticsearch·全文检索·agent·关键词
MayBaymax10 小时前
ES 基础总结
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客10 小时前
两个依赖和一个配置块:通过 Prometheus 远程写入将 Spring Boot 指标发送到 Elasticsearch
大数据·数据库·spring boot·elasticsearch·搜索引擎·全文检索·prometheus
SelectDB技术团队11 小时前
ELK 太占磁盘、ES 总报写入拒绝:从归因到可执行的优化清单
大数据·clickhouse·elk·elasticsearch·全文检索·复杂查询·实时更新
frjc21 小时前
数据库选型:如何从众多数据库中选出最理想的那一个
redis·mysql·clickhouse·elasticsearch