# 通过Elasticdump实现Elasticsearch集群间数据迁移
#### 应用场景
在企业日常运营中，Elasticsearch集群的数据迁移是常见场景。Elasticdump是一个开源的Elasticsearch集群迁移工具，它支持不同版本的Elasticsearch之间的数据迁移。以下是Elasticdump实现Elasticsearch集群间数据迁移的应用场景：
- 跨版本迁移：在Elasticsearch集群需要升级到新版本时，Elasticdump可以帮助平滑迁移数据，确保升级过程中数据的完整性和可用性。
- 集群合并：当企业需要将多个Elasticsearch集群的数据整合到一个集群中以简化管理时，Elasticdump可以高效地完成这一任务。
- 服务迁移上云：企业可以将自建的Elasticsearch服务迁移至云平台，以利用云服务的弹性扩展、简化维护和成本效益。
- 变更服务提供商：如果企业当前使用的是第三方Elasticsearch服务，但出于成本、性能或其他战略考虑，希望更换服务提供商至华为云。
Elasticdump工具适用于数据量较小，索引数量不多的迁移场景。工具的详细使用方式请参见[elasticsearch-dump](https://github.com/elasticsearch-dump/elasticsearch-dump)官方文档。
#### 方案架构
图1迁移流程   
![](https://support.huaweicloud.com/bestpractice-css/figure/zh-cn_image_0000002531187905.png "点击放大")
通过Elasticdump工具实现Elasticsearch集群间数据迁移的迁移流程如[图1]所示。
1. 在迁移前，需要确保源集群和目标集群的版本兼容，并对源集群的数据备份，以防止数据丢失
2. 在Linux虚拟机上安装Elasticdump迁移工具。
3. 通过配置Elasticdump迁移命令，将源集群的索引数据迁移至目标集群。
 
#### 方案优势
- 跨版本兼容性：Elasticdump支持不同版本的Elasticsearch集群间的数据迁移，包括从老版本迁移到新版本。
- 灵活的迁移方案：Elasticdump提供了灵活的迁移方案，包括迁移索引settings、mapping、data等数据，以适应不同的业务需求。
- 开源免费：作为一个开源工具，Elasticdump代码托管在GitHub上，用户可以免费使用。
 
#### 性能影响
Elasticdump迁移方式的原理是通过Scroll API方式读取原始索引source内容写入到目标集群的索引，迁移时对源集群的数据读写会造成压力，建议在业务低峰期迁移。
#### 约束限制
集群迁移过程中，源集群的索引数据不能增删改，否则会导致数据迁移后的源集群数据和目标集群数据内容不一致。
#### 前提条件
- 已经购买CSS集群，源Elasticsearch集群和目标Elasticsearch集群处于可用状态。
- 集群间需要保证网络连通。
  - 如果源集群和目标集群在同一VPC，则网络已连通。
  
  - 如果源集群和目标集群在不同VPC，则需要先打通VPC网络建立对等连接。具体操作请参见[对等连接简介](https://support.huaweicloud.com/usermanual-vpc/zh-cn_topic_0046655036.html)。
  
  - 如果是自建Elasticsearch集群迁移至华为云，则可以通过给自建Elasticsearch集群配置公网访问打通网络。
  
  - 如果是第三方Elasticsearch集群迁移至华为云，则需要建立企业内部数据中心到华为云的VPN通道或专线。
   
- 确认集群的索引已开启"_source"。 集群索引的"_source"默认是开启的。执行命令**GET {index_name}/_search**，当返回的搜索结果中包含"_source"字段时表示已开启。
  
 
 #### 步骤一：获取Elasticsearch集群信息
在迁移集群前，需要先获取必备的集群信息，用于配置迁移任务。
表1需要获取的Elasticsearch集群信息 
| 集群来源                                                                       || 要获取的信息                                                                                                                                                                                                                                        | 获取方式                                                                                                                                                                                                                                                                                                                                                            |
|:---|---|:---|:---|
| 源集群     | 华为云Elasticsearch集群  | - 源集群的访问地址  - 访问源集群的用户名和密码（仅安全集群涉及）         | - 获取集群名称和访问地址请参见[3](https://support.huaweicloud.com/bestpractice-css/css_07_0009.html#ZH-CN_TOPIC_0000001971547281__li92051018102011)。  - 用户名和密码请联系服务管理员获取。   |
| 源集群     | 自建Elasticsearch集群  | - 源集群的公网访问地址  - 访问源集群的用户名和密码（仅安全集群涉及）   | 联系服务管理员获取。                                                                                                                                                                                                                                                                                                                                                      |
| 源集群     | 第三方Elasticsearch集群  | - 源集群的访问地址  - 访问源集群的用户名和密码（仅安全集群涉及）         | 联系服务管理员获取。                                                                                                                                                                                                                                                                                                                                                        |
| 目标集群 | 华为云Elasticsearch集群 | - 目标集群的访问地址  - 访问目标集群的用户名和密码（仅安全集群涉及）            | - 获取访问地址请参见[3](https://support.huaweicloud.com/bestpractice-css/css_07_0009.html#ZH-CN_TOPIC_0000001971547281__li92051018102011)。  - 用户名和密码请联系服务管理员获取。   |
   
源集群的来源不同，获取信息的方式不同，此处仅介绍如何获取华为云Elasticsearch集群的信息。
1. 登录[云搜索服务管理控制台](https://console.huaweicloud.com/elasticsearch/)。
2. 在左侧导航栏，选择"集群管理 \> Elasticsearch"。
3. 在集群列表，选择目标集群，获取集群名称和访问地址。
   图2获取集群信息   
   ![](https://support.huaweicloud.com/bestpractice-css/figure/zh-cn_image_0000001969281924.png "点击放大") 
 
#### 步骤二：安装Elasticdump工具
1. 创建ECS用于安装Elasticdump工具。
   1. 购买Linux ECS，"镜像"选择CentOS 8系列，"虚拟私有云"和目标集群保持一致，启用公网访问。购买操作指导请参见[快速购买和使用Linux ECS](https://support.huaweicloud.com/qs-ecs/ecs_01_0103.html)。
      ![](https://support.huaweicloud.com/bestpractice-css/public_sys-resources/note_3.0-zh-cn.png)
      如果当前环境的网络未连接，则无需启用ECS的公网访问功能。建议采用离线安装步骤操作（需提前在有网络的环境中下载Elasticdump工具包和nodejs安装包，并传输至目标ECS）。操作指导请参见[常见问题：如何离线安装Elasticdump工具]。
      
   
   2. 测试ECS和源集群、目标集群的连通性。 在ECS执行如下命令测试连通性，当正常返回集群信息时表示已经连通。
      ```
      # 非安全模式的集群
      curl http://[ip]:9200
      # 安全模式+HTTP访问的集群
      curl -ik http://[ip]:9200 -u [username]:[password]
      # 安全模式+HTTPS访问的集群
      curl -ik https://[ip]:9200 -u [username]:[password]
      ```
      
    
2. 在ECS上安装并配置nodejs。
   1. 下载nodejs安装包。
      ```
      wget https://nodejs.org/dist/v20.10.0/node-v20.10.0-linux-x64.tar.gz
      ```
      
   
   2. 解压nodejs安装包。
      ```
      tar -xvf node-v20.10.0-linux-x64.tar.gz
      ```
      
   
   3. 在bash_profile文件导入nodejs环境变量。
      ```
      vim ~/.bash_profile
      ```
      
   
   4. 设置环境变量。执行vi命令打开bash_profile文件，添加如下内容：
      ```
      export PATH=$PATH:/root/node-v20.10.0-linux-x64/bin/
      ```
      
   
   5. 执行source命令使配置生效。
      ```
      source ~/.bash_profile
      ```
      
   
   6. 验证nodejs是否安装成功。
      ```
      node -v
      ```
      
    
3. 在ECS上安装Elasticdump工具。
   ```
   npm install elasticdump -g
   ```
   
4. 验证Elasticdump工具是否安装成功。
   ```
   elasticdump --help
   ```
   
 
#### 步骤三：使用Elasticdump迁移数据
1. 使用Elasticdump迁移Elasticsearch数据，以实现数据迁移至目标集群。 Elasticdump从input读取数据，发送数据到output，因此input配置的是源Elasticsearch集群信息，output配置的是目标Elasticsearch集群信息。如[表2]所示提供了参数配置说明。
   - 迁移指定索引settings：
     ```
     elasticdump --input={protocol}://{host}:{port}/{index_name} --output={protocol}://{host}:{port}/{index_name} --type=settings
     # 示例:非安全模式的集群迁移到安全模式+HTTPS协议的集群
     NODE_TLS_REJECT_UNAUTHORIZED=0 elasticdump --input=http://xx.xx.xx.xx:9200/my_index --output=https://username:password@xx.xx.xx.xx:9200/my_index --type=settings
     ```
     
   
   - 迁移指定索引mapping：
     ```
     elasticdump --input={protocol}://{host}:{port}/{index_name} --output={protocol}://{host}:{port}/{index_name} --type=mapping
     # 示例:非安全模式的集群迁移到安全模式+HTTPS协议的集群
     NODE_TLS_REJECT_UNAUTHORIZED=0 elasticdump --input=http://xx.xx.xx.xx:9200/my_index --output=https://username:password@xx.xx.xx.xx:9200/my_index --type=mapping
     ```
     
   
   - 迁移指定索引数据：
     ```
     elasticdump --input={protocol}://{host}:{port}/{index_name} --output={protocol}://{host}:{port}/{index_name} --type=data
     # 示例:非安全模式的集群迁移到安全模式+HTTPS协议的集群
     NODE_TLS_REJECT_UNAUTHORIZED=0 elasticdump --input=http://xx.xx.xx.xx:9200/my_index --output=https://username:password@xx.xx.xx.xx:9200/my_index --type=data
     ```
     
   
   - 通过query语句迁移数据：
     ```
     elasticdump --input={protocol}://{host}:{port}/{index_name} --output={protocol}://{host}:{port}/{index_name} --searchBody="QueryString"
     # 示例:非安全模式的集群迁移到安全模式+HTTPS协议的集群
     NODE_TLS_REJECT_UNAUTHORIZED=0 elasticdump --input=http://xx.xx.xx.xx:9200/my_index --output=https://username:password@xx.xx.xx.xx:9200/my_index --searchBody="{\"query\":{\"term\":{\"username\": \"admin\"}}}"
     ```
     
   
   
    表2参数说明 
   | 参数                             | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
   |:---|:---|
   | protocol                       | 连接协议。 - 非安全模式的集群配置为http。  - 安全模式+HTTP协议的集群配置为http。  - 安全模式+HTTPS协议的集群配置为https。                                                                                                                                                                                |
   | host                           | 集群访问地址。 - 非安全模式的集群配置为"集群IP地址"，如"xx.xx.xx.xx"。  - 安全模式的集群配置为"访问集群的用户名:密码@集群IP地址"，如"username:password@xx.xx.xx.xx"。   当集群存在多个IP地址时，中间用","隔开，如"xx.xx.xx.xx,xx.xx.xx.xx"。 集群IP地址的获取方式请参见[步骤一：获取Elasticsearch集群信息]。 |
   | port                           | 集群的连接端口，默认是"9200"。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
   | index_name                    | 待迁移的索引名称。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
   | QueryString                  | 源集群的查询语句，用于指定要迁移的数据范围。支持json字符串格式，如"{\\"query\\":{\\"term\\":{\\"username\\": \\"admin\\"}}}"表示只迁移username为admin的文档。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
   | NODE_TLS_REJECT_UNAUTHORIZED=0 | 忽略安全证书认证，访问HTTPS协议的集群必须配置。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
      
   更多迁移场景请参见[elasticsearch-dump](https://github.com/elasticsearch-dump/elasticsearch-dump)官方文档。
   
2. 数据迁移完成后，使用以下命令分别在源集群和目标集群中获取文档个数，并对比结果以确认数据一致性。
   ```
   # 非安全模式的集群
   curl http://[ip]:9200/[index_name]/_count 
     
   # 安全模式+HTTP访问的集群
   curl -ik -u [username]:[password] http://[ip]:9200/[index_name]/_count
   # 安全模式+HTTPS访问的集群
   curl -ik -u [username]:[password] https://[ip]:9200/[index_name]/_count
   ```
   
 
#### 常见问题：如何使用Elasticdump导出数据
Elasticdump支持导出数据到本地。
- 导出指定索引到本地json文件中：
  ```
  # Backup index data to a file
  elasticdump \
    --input={protocol}://{host}:{port}/{index_name} \
    --output=/{local_file}/my_index.json \
    --type=data
  ```
  
- 导出指定索引到本地并保存为zip压缩包：
  ```
  # Backup an index to a gzip using stdout
  elasticdump \
    --input={protocol}://{host}:{port}/{index_name} \
    --output=$ \
    | gzip > /{local_file}/my_index.json.gz
  ```
  
- 通过query语句导出指定索引到本地：
  ```
  # Backup the results of a query to a file
  elasticdump \
    --input={protocol}://{host}:{port}/{index_name} \
    --output=/{local_file}/query.json \
    --searchBody="QueryString"
  ```
  
表3参数说明 
| 参数       | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
|:---|:---|
| protocol    | 连接协议。 - 非安全模式的集群配置为http。  - 安全模式+HTTP协议的集群配置为http。  - 安全模式+HTTPS协议的集群配置为https。                                                                                                                                                                             |
| host       | 集群访问地址。 - 非安全模式的集群配置为"集群IP地址"，如"xx.xx.xx.xx"。  - 安全模式的集群配置为"访问集群的用户名:密码@集群IP地址"，如"username:password@xx.xx.xx.xx"。   当集群存在多个IP地址时，中间用","隔开，如"xx.xx.xx.xx,xx.xx.xx.xx"。 集群IP地址的获取方式请参见[步骤一：获取Elasticsearch集群信息]。 |
| port         | 集群的连接端口，默认是"9200"。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| index_name | 待迁移的索引名称。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| local_file | 本地存储路径。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| QueryString | 源集群的查询语句，用于指定要迁移的数据范围。支持json字符串格式，如"{\\"query\\":{\\"term\\":{\\"username\\": \\"admin\\"}}}"表示只迁移username为admin的文档。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
   
#### 常见问题：HTTPS访问的集群如何忽略安全证书认证
Elasticdump支持通过设置环境变量NODE_TLS_REJECT_UNAUTHORIZED=0跳过安全证书认证。
```
# An alternative method of passing environment variables before execution
# NB : This only works with linux shells
NODE_TLS_REJECT_UNAUTHORIZED=0 elasticdump --input={protocol}://{host}:{port}/{index_name} --output={protocol}://{host}:{port}/{index_name}
```
 #### 常见问题：如何离线安装Elasticdump工具
当环境中的nodejs已安装成功，需要离线安装Elasticdump工具时，可以参考如下步骤。
1. 为了在无公网访问能力的环境中安装Elasticdump工具，需要提前在**有网络的环境**中生成安装包。
   1. 登录具有公网访问功能的ECS。
   
   2. 参考[2]在ECS上安装并配置nodejs。
   
   3. 安装Elasticdump工具。
      ```
      npm install elasticdump -g
      ```
      
   
   4. 安装npm打包工具。
      ```
      npm install npm-pack-all -g
      ```
      
   
   5. 进入node_modules路径。注意替换为实际路径。
      ```
      cd /root/node-v20.10.0-linux-x64/lib/node_modules/elasticdump/
      ```
      
   
   6. 打包Elasticdump安装包。
      ```
      npm-pack-all
      ```
      
   
   7. 使用**ll** 命令查看当前目录下是否生成了安装包文件。
      如[图3]所示，表示打包成功，已生成"elasticdump-6.x.x.tgz"安装包，不同版本的安装包名称会有差异。
      图3打包成功的安装包   
      ![](https://support.huaweicloud.com/bestpractice-css/figure/zh-cn_image_0000002531898959.png "点击放大") 
   
   8. 使用sftp工具下载Elasticdump安装包。
     
2. 在**有网络的环境** 中下载nodejs安装包。
   下载地址：<https://nodejs.org/dist/v20.10.0/node-v20.10.0-linux-x64.tar.gz>。
   
3. 在**无公网访问能力的环境** 中安装Elasticdump工具。
   1. 将Elasticdump安装包和nodejs安装包上传到目标ECS的root路径下。
   
   2. 在ECS上安装并配置nodejs。
      1. 解压nodejs安装包。
         ```
         tar -xvf node-v20.10.0-linux-x64.tar.gz
         ```
         
      
      2. 在bash_profile文件导入nodejs环境变量。
         ```
         vim ~/.bash_profile
         ```
         
      
      3. 设置环境变量。执行vi命令打开bash_profile文件，添加如下内容：
         ```
         export PATH=$PATH:/root/node-v20.10.0-linux-x64/bin/
         ```
         
      
      4. 执行source命令使配置生效。
         ```
         source ~/.bash_profile
         ```
         
      
      5. 验证nodejs是否安装成功。
         ```
         node -v
         ```
         
       
   
   3. 安装Elasticdump。
      ```
      npm install elasticdump-6.x.x.tgz  -g
      ```
      
   
   4. 设置Elasticdump软链接。注意替换为实际路径。
      ```
      ln -s /root/node-v20.10.0-linux-x64/lib/node_modules/elasticdump/bin/elasticdump  /usr/local/bin
      ```
      
    
4. 验证Elasticdump工具是否安装成功。
   ```
   elasticdump --help
   ```
   
 
