作者:来自 Elastic Kofi Bartlett
当你想要升级一个 Elasticsearch 集群时,有时候创建一个新的独立集群并将数据从旧集群迁移到新集群会更容易一些。这让用户能够在不冒任何停机或数据丢失风险的情况下,在新集群上使用所有应用程序测试其所有数据和配置。
这种方法的缺点是需要一些硬件的重复配置,并且在尝试平稳地传输和同步所有数据时可能会带来困难。
如果你需要将应用程序从一个数据中心迁移到另一个数据中心,也可能需要执行类似的操作。
在本文中,我们将讨论并详细介绍三种在 Elasticsearch 集群之间传输数据的方法。
如何在 Elasticsearch 集群之间迁移数据?
有三种方式可以在 Elasticsearch 集群之间传输数据:
-
从远程集群重新索引
-
使用快照传输数据
-
使用 Logstash 传输数据
使用快照通常是最快且最可靠的数据传输方式。然而,请记住,你只能将快照恢复到相同版本或更高版本的集群,且版本差异不能超过一个主版本。这意味着你可以将一个 6.x 的快照恢复到 7.x 的集群,但不能恢复到 8.x 的集群。
如果你需要升级超过一个主版本,你将需要重新索引或使用 Logstash。
现在,让我们详细了解在 Elasticsearch 集群之间传输数据的三种选项。
1. 从远程集群重新索引数据
在开始重新索引之前,请记住你需要为新集群上的所有索引设置合适的映射。为此,你必须直接使用合适的映射创建索引,或使用索引模板。
从远程重新索引 — 所需配置
为了从远程集群重新索引,你需要在接收数据的集群中将以下配置添加到 elasticsearch.yml 文件中,该文件在 Linux 系统中通常位于:
/etc/elasticsearch/elasticsearch.yml
。需要添加的配置如下:
reindex.remote.whitelist: "192.168.1.11:9200"
如果你正在使用 SSL,你应该将 CA 证书添加到每个节点,并在每个节点的 elasticsearch.yml 中加入以下命令:
reindex.ssl.certificate_authorities: “/path/to/ca.pem”
或者,你也可以在所有 Elasticsearch 节点中添加以下这一行,以禁用 SSL 验证。不过,这种方式不太推荐,因为它相比前一种方式安全性较低:
reindex.remote.whitelist: "192.168.1.11:9200"
reindex.ssl.verification_mode: none
systemctl restart elasticsearch service
你需要在每个节点上进行这些修改,并执行滚动重启。有关如何进行的更多信息,请参阅我们的指南。
重新索引命令
在你已经在 elasticsearch.yml 文件中定义了远程主机并在需要时添加了 SSL 证书之后,你可以使用以下命令开始重新索引数据:
POST _reindex
{
"source": {
"remote": {
"host": "http://192.168.1.11:9200",
"username": "elastic",
"password": "123456",
"socket_timeout": "1m",
"connect_timeout": "1m"
},
"index": "companydatabase"
},
"dest": {
"index": "my-new-index-000001"
}
}
在执行此操作时,你可能会遇到超时错误,因此,设置较大的超时时间值可能会比依赖默认值更为有用。
现在,让我们看看在从远程重新索引时你可能遇到的一些常见错误。
从远程重新索引时的常见错误
1. 重新索引未被列入白名单
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "[192.168.1.11:9200] not whitelisted in reindex.remote.whitelist"
}
],
"type": "illegal_argument_exception",
"reason": "[192.168.1.11:9200] not whitelisted in reindex.remote.whitelist"
},
"status": 400
}
如果你遇到这个错误,说明你没有像上面所述那样在 Elasticsearch 中定义远程主机的 IP 地址或节点名称的 DNS,或者忘记重启 Elasticsearch 服务。
为了解决这个问题,你需要将远程主机添加到所有 Elasticsearch 节点中,并重启 Elasticsearch 服务。
2. SSL 握手异常
{
"error": {
"root_cause": [
{
"type": "s_s_l_handshake_exception",
"reason": "PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"
}
],
"type": "s_s_l_handshake_exception",
"reason": "PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target",
"caused_by": {
"type": "validator_exception",
"reason": "PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target",
"caused_by": {
"type": "sun_cert_path_builder_exception",
"reason": "unable to find valid certification path to requested target"
}
}
},
"status": 500
}
这个错误意味着你忘记在 elasticsearch.yml 中添加 reindex.ssl.certificate_authorities,如上所述。要解决此问题,请添加以下内容:
#elasticsearch.yml
reindex.ssl.certificate_authorities: "/path/to/ca.pem"
2. 使用快照传输数据
记住,如上所述,你只能将快照恢复到相同版本或更高版本的集群,且版本差异不能超过一个主版本。
如果你需要升级超过一个主版本,你将需要重新索引或使用 Logstash。
通过快照传输数据的步骤如下:
步骤 1. 将 repository 插件添加到第一个 Elasticsearch 集群 — 为了通过快照在集群之间传输数据,你需要确保 repository 可以从新集群和旧集群都能访问。像 AWS、Google 和 Azure 这样的云存储仓库通常是理想的选择。要创建快照,请参阅我们的指南并按照其中描述的步骤操作。
步骤 2. 重启 Elasticsearch 服务(滚动重启)。
步骤 3. 为第一个 Elasticsearch 集群创建 repository。
步骤 4. 将 repository 插件添加到第二个 Elasticsearch 集群。
步骤 5. 将 repository 设置为只读模式并添加到第二个 Elasticsearch 集群 — 你需要通过重复创建第一个 Elasticsearch 集群时采取的相同步骤来添加 repository。
重要提示: 当将第二个 Elasticsearch 集群连接到相同的 AWS S3 仓库时,你应该将该仓库定义为只读仓库:
PUT _snapshot/my_s3_repository
{
"type": "s3",
"settings": {
"bucket": "my-analytic-data",
"endpoint": "s3.eu-de.cloud-object-storage.appdomain.cloud",
"readonly": "true"
}
}
这很重要,因为你需要防止在同一个快照仓库中混合不同版本的 Elasticsearch。
步骤 6. 将数据恢复到第二个 Elasticsearch 集群 — 在完成上述步骤后,你可以恢复数据并将其传输到新集群。请按照本文中描述的步骤将数据恢复到新集群。
3. 使用 Logstash 传输数据
在开始使用 Logstash 传输数据之前,请记住你需要为新集群上的所有索引设置合适的映射。为此,你需要直接创建索引或使用索引模板。
为了在两个 Elasticsearch 集群之间传输数据,你可以设置一个临时的 Logstash 服务器,并使用它在两个集群之间传输数据。对于小型集群,2GB 内存的实例应该足够。对于较大的集群,你可以使用四核 CPU 和 8GB 内存的实例。
有关安装 Logstash 的指导,请参阅此处。
从一个集群到另一个集群的 Logstash 配置
一个基本的配置,复制单个索引从集群 A 到集群 B,如下所示:
iinput
{
elasticsearch
{
hosts => ["192.168.1.11:9200"]
index => "index_name"
docinfo => true
}
}
output
{
elasticsearch {
hosts => "https://192.168.1.12:9200"
index => "index_name"
}
}
对于安全的 Elasticsearch,你可以使用以下配置:
input
{
elasticsearch
{
hosts => ["192.168.1.11:9200"]
index => "index_name"
docinfo => true
user => "elastic"
password => "elastic_password"
ssl => true
ssl_certificate_verification => false
}
}
output
{
elasticsearch {
hosts => "https://192.168.1.12:9200"
index => "index_name"
user => "elastic"
password => "elastic_password"
ssl => true
ssl_certificate_verification => false
}
}
索引元数据
上述命令将写入一个单独命名的索引。如果你想要传输多个索引并保留索引名称,则需要在 Logstash 输出中添加以下行:
index => "%{[@metadata][_index]}"
如果你还想保留文档的原始 ID,那么你需要添加:
document_id => "%{[@metadata][_id]}"
请记住,设置文档 ID 会使数据传输显著变慢,因此只有在需要时才保留原始 ID。
更新同步
上述所有方法都会花费相对较长的时间,你可能会发现,在等待过程完成的过程中,原始集群中的数据已经被更新。
有多种策略可以使在数据传输过程中发生的任何更新得以同步,在开始此过程之前,你应该考虑这些问题。特别是,你需要考虑以下问题:
-
你有什么方法来识别自数据传输过程开始以来已更新/添加的数据(例如,数据中的 “last_update_time” 字段)?
-
你可以使用什么方法来传输最后一部分数据?
-
是否存在记录重复的风险?通常是有的,除非你使用的方法在重新索引时将文档 ID 设置为已知值。
下面描述了不同的方法来启用更新的同步。
-
使用队列系统
一些摄取/更新系统使用队列,使你能够 “重放” 在过去 x 天内接收到的数据修改。这可能提供一种同步所有更改的方法。 -
从远程重新索引
对所有 “last_update_time” > x 天前的项目重复重新索引过程。你可以通过在重新索引请求中添加 “query” 参数来实现这一点。 -
Logstash
在 Logstash 输入中,你可以添加一个查询来过滤所有 “last_update_time” > x 天前的项目。然而,除非你设置了 document_id,否则这个过程会导致非时间序列数据的重复。 -
快照
无法仅恢复部分索引,因此你必须使用上述其他数据传输方法之一(或脚本)来更新数据传输过程执行以来的任何更改。
然而,快照恢复比重新索引/Logstash 过程要快得多,因此可以在快照传输期间暂停更新,短时间内避免问题的发生。
想要获得 Elastic 认证吗?了解下一期 Elasticsearch 工程师培训的时间!
Elasticsearch 拥有众多新功能,帮助你为你的用例构建最佳搜索解决方案。深入了解我们的示例笔记本,开始免费的云试用,或者现在就尝试在本地机器上使用 Elastic。
原文:How to migrate data between different versions of Elasticsearch & between clusters - Elasticsearch Labs