Elasticsearch索引备份与迁移

总结Elasticsearch各种备份与迁移方案,亲测。
详细记录了具体步骤。

一、环境

  • Ubuntu 14.04/16、04
  • JDK1.8
  • Elasticsearch 5.3
  • Kibana 5.3.2

二、单节点环境

1. 创建备份存储目录

sudo mkdir /media/es/es_backup
# 该目录要是elasticsearch可访问的,我们的环境一般是elasticsearch用户
chown -R elasticsearch:elasticsearch /media/es/es_backup/

2. 修改elasticsearch.yml文件

  修改elasticsearch.yml文件,添加path.repo配置。

vim elasticsearch.yml
# 增加一行如下:
path.repo: ["/media/es/es_backup"]

3. 重启Elasticsearch

4. 创建仓库

  借助Kibana操作。

# 创建仓库,创建一个名为my_backup的仓库
PUT _snapshot/my_backup
{
  "type": "fs",
  "settings": {
    "location": "/media/es/es_backup",
    "compress": true
  }
}

# 检查仓库是否创建成功(my_backup为之前创建的仓库名称) 
GET _snapshot/my_backup

# 删除仓库
DELETE _snapshot/my_backup

5. 备份索引数据

# 给所有索引创建快照
PUT _snapshot/my_backup/snapshot_name        

# 针对具体的index创建快照备份
# 其中my_backup是仓库名称,snapshot_name是快照的名字
# ignore_unavailable在创建快照的过程中会忽略不存在的索引,默认情况下,如果没有设置,在索引不存在的情况下快照请求将会失败
# include_global_state能够防止集群的全局状态被作为快照的一部分存储起来
# 多个索引间不要加空格,否则只会对第一个索引操作(我踩过坑!!!)
PUT _snapshot/my_backup/snapshot_name?wait_for_completion=true
{
  "indices": "index_1,index_2",
  "ignore_unavailable": true,
  "include_global_state": false
}

# 查看指定仓库下所有快照
GET _snapshot/my_backup/_all

# 查看具体某一个快照的信息
GET _snapshot/my_backup/snapshot_name/_status

# 删除快照,要指定仓库名和快照名
# 也能用于取消一个正在进行的快照创建过程,会删除备份了一半的快照
DELETE _snapshot/my_backup/snapshot_name

  这里我取一个仓库名为my_backup,快照名为alert_snap,要备份的index为.nina_view和cc-zabbix-2018.01.05

6. 将数据迁移到另一个环境

# 备份创建好之后,在仓库目录/media/es/es_backup里是这样的:
-rw-r--r-- 1 elasticsearch elasticsearch  317 Jan 22 17:44 index-0
-rw-r--r-- 1 elasticsearch elasticsearch    8 Jan 22 17:44 index.latest
drwxr-xr-x 4 elasticsearch elasticsearch 4096 Jan 22 17:44 indices/
-rw-r--r-- 1 elasticsearch elasticsearch  103 Jan 22 17:44 meta-9KWgeCYtSBqqVrfD42bsNw.dat
-rw-r--r-- 1 elasticsearch elasticsearch  237 Jan 22 17:44 snap-9KWgeCYtSBqqVrfD42bsNw.dat

7. 在目标环境下,重复上面1~4步,建立仓库

  将源集群的备份内容(/media/es/es_backup里的所有文件),复制到迁移目标的仓库目录里,接下来就是类似批量导入了。

# 如果索引已经存在目标的集群,需要先关闭索引,恢复数据后再开启
POST /index_name/_close
POST _snapshot/my_backup/snapshot_name/_restore
POST /index_name/_open

# 从快照中恢复指定的索引,并给索引重命名
# indices里面可以写多个索引名,中间用逗号隔开
# rename_pattern可以写完整的索引名,也可以用正则匹配索引名的局部
# rename_replacement将替换rename_pattern中匹配到的局部(如果是正则,不是将整个索引名都替换)
#下面这条语句会把index_1,index_2恢复为restored_index_1和restored_index_2
POST /_snapshot/my_backup/snapshot_1/_restore
{
  "indices": "index_1,index_2",
  "rename_pattern": "index_(.+)",
  "rename_replacement": "restored_index_$1"
}

# 查看恢复的状态
GET _snapshot/my_backup/snapshot_name/_status 

三、集群-多节点环境

1. 创建共享目录

  (todo…我没实施过,感觉挺麻烦的,不太推荐)
  使用sshfs在ES集群中每个节点的相同位置挂载一个共享目录,
  假设ES集群有三个节点:192.168.1.10,192.168.1.11,192.168.1.12,
  我这里共享目录用了/data/es_backup,ES备份仓库目录(也是共享目录的挂在点)用了/mnt/es_backup,可以根据实际情况调整

# 在每个节点上安装sshfs
sudo apt-get install sshfs

# 选取其中一个节点的目录(非系统盘)作为共享目录 </br>
# 假设选择的节点ip为192.168.1.10:
mkdir /data/es_backup
chown -R elasticsearch:elasticsearch /data/es_backup
chmod -R 777 /data/es_backup

# 在每个ES节点的相同位置创建存放ES仓库的目录
mkdir /mnt/es_backup
chown -R elasticsearch:elasticsearch /mnt/es_backup
chmod -R 777 /mnt/es_backup
# 每个节点挂载共享目录,执行同样的操作。$user为用户,一般为root,回车后输入密码,其中的参数-o allow_other允许了其他用户访问这个目录
sshfs $user@192.168.1.10:/data/es_backup /mnt/es_backup -o allow_other
# 如果修改了默认ssh端口, 比如23566, 则可以这样:
sshfs $user@192.168.1.10:/data/es_backup /mnt/es_backup -p 23566 -o allow_other

# 测试运行ES的用户是否有对共享目录的写权限
sudo su - elasticsearch
touch /mnt/es_backup/test.txt

# 修改每个节点的elasticsearch.yml文件,添加path.repo配置
path.repo: ["/mnt/es_backup"]

  接下来的操作和上面单节点一样,重启es,建立仓库,创建快照等等。

# 在共享目录下为集群创建共享仓库
PUT _snapshot/my_backup
{
  "type": "fs",
  "settings": {
    "location": "/mnt/es_backup",
    "compress": true
  }
}
# 后面步骤省略...

  最后补充一下:取消挂载共享目录,不要直接删除挂载目录,在每个节点下执行下面命令

# 这个命令会断开远程连接同时清空 /mnt/es_backup 目录。
fusermount -u /mnt/es_backup

  类似的实现文件共享的方法还有 nfs 和 samba(支持window和linux互相访问)

2. 借助第三方工具

  第三方迁移工具,网上看了下,主要有三个:
  ● elasticsearch-dump
  ● elasticsearch-exporter
  ● elasticsearch-migration

  优点:方便,快速。支持的功能很多(数据迁移、mapping迁移等等)。
  缺点:原理是用了scroll+bulk,百万、千万级别条数的数据可以使用,数据量过大还是老老实实用我上面整理的快照方法吧;
  备注:对ES操作时候,一些报错没有捕获到并写入log。比如我们只允许自动创建cc-开头的索引,迁移生成的新索引需要改名为别的名字,你会发现迁移完,数据没有进去,这也算是第三方工具的不足之处,不过它应该会不断完善。

四、总结

  不管是运维也好,开发也好,对数据的备份和迁移是经常要做的事。针对环境的不同特别是数据量的差异,需要适时选择合适的方式。
  有时候也要根据自己的具体需求而定,比如为了辅助自己开发,需要回放数据,那完全可以编写一些简单的脚本来实现。
  我写过几个简单的脚本,放在GitHub上:
  ● es_replay
  开发测试用途(数据导出、去重、构造和导入)
  ● es_assistant
  一些用于协助开发和测试的es交互脚本
  ● es_monitor
  Elaticsearch部署机的信息采集脚本(这个是很久很久以前写的,那时候刚学ES,能直接用,功能上没问题,但代码完全可以更优化一下,最近忙着学其他东西,所以一直没去动它。)


  目录