原文链接https://www.datadoghq.com/blog/elasticsearch-unassigned-shards/
如何解决Elasticsearch unassigned shards 问题
在Elasticsearch中,健康的集群是一个均衡的集群:主节点和副本分片分布在所有节点上,以便在节点发生故障时具有持久的可靠性。
但是当你看到碎片在UNASSIGNED状态中挥之不去时,你该怎么办?
在我们深入研究一些解决方案之前,让我们验证未分配的分片是否包含我们需要保留的数据(如果不是,删除这些分片是解决问题的最直接的方法)。如果您已经知道数据值得保存,请跳转到解决方案:
本文中的命令是在假设您在默认端口(9200)上运行每个Elasticsearch实例的HTTP服务的情况下格式化的。它们也被定向到localhost,它假定您在本地提交请求;否则,将localhost替换为您节点的IP地址。
精确定位有问题的碎片
curl -XGET localhost:9200/_cat/shards?h=index,shard,prirep,state,unassigned.reason| grep UNASSIGNED
每行列出索引的名称,分片编号,是主分片(p)还是副本(r)分片,以及它未分配的原因:
constant-updates 0 p UNASSIGNED NODE_LEFT node_left[NODE_NAME]
如果您运行的是Elasticsearch的5+版本,您还可以使用群集分配说明API来尝试获取有关分片分配问题的更多信息:
curl -XGET localhost:9200/_cluster/allocation/explain?pretty
生成的输出将提供有关群集中某些分片未分配的原因的有用详细信息:
{
"index" : "testing",
"shard" : 0,
"primary" : false,
"current_state" : "unassigned",
"unassigned_info" : {
"reason" : "INDEX_CREATED",
"at" : "2018-04-09T21:48:23.293Z",
"last_allocation_status" : "no_attempt"
},
"can_allocate" : "no",
"allocate_explanation" : "cannot allocate because allocation is not permitted to any of the nodes",
"node_allocation_decisions" : [
{
"node_id" : "t_DVRrfNS12IMhWvlvcfCQ",
"node_name" : "t_DVRrf",
"transport_address" : "127.0.0.1:9300",
"node_decision" : "no",
"weight_ranking" : 1,
"deciders" : [
{
"decider" : "same_shard",
"decision" : "NO",
"explanation" : "the shard cannot be allocated to the same node on which a copy of the shard already exists"
}
]
}
]
}
在这种情况下,API清楚地解释了副本分片保持未分配的原因:“分片无法分配到已存在分片副本的同一节点”。要查看有关此特定问题的更多详细信息以及如何解决此问题,请跳至本文后面的部分。
如果看起来未分配的分片属于您认为已删除的索引,或者您不再需要的过时索引,则可以删除索引以将群集状态恢复为绿色:
curl -XDELETE 'localhost:9200/index_name/'
如果这没有解决问题,请继续阅读以尝试其他解决方案。
原因1:故意分配碎片分配
当节点离开集群时,主节点暂时延迟分片重新分配,以避免在原始节点能够在特定时间段(默认为一分钟)内恢复时不必要地在重新平衡分片上浪费资源。如果是这种情况,您的日志应如下所示:
[TIMESTAMP][INFO][cluster.routing] [MASTER NODE NAME] delaying allocation for [54] unassigned shards, next check in [1m]
您可以动态修改延迟时间,如下所示:
curl -XPUT 'localhost:9200//_settings' -d
'{
"settings": {
"index.unassigned.node_left.delayed_timeout": "30s"
}
}'
用_all替换
延迟期结束后,您应该开始看到主分配这些分片。如果没有,请继续阅读以探索其他潜在原因的解决方案。
原因2:分片太多,节点不够
当节点加入和离开集群时,主节点会自动重新分配分片,确保分片的多个副本未分配给同一节点。换句话说,主节点不会将主分片分配给与其副本相同的节点,也不会将同一分片的两个副本分配给同一节点。如果没有足够的节点来相应地分配分片,则分片可能会以未分配的状态停留。
要避免此问题,请确保使用下面的公式初始化群集中的每个索引,每个主分片的副本数少于群集中的节点数:
N >= R + 1
其中N是群集中的节点数,R是群集中所有索引的最大分片复制因子
在下面的屏幕截图中,many-shards索引存储在四个主分片上,每个主分片有四个副本。索引的20个分片中有8个未分配,因为我们的群集只包含三个节点。尚未分配每个主分片的两个副本,因为三个节点中的每个节点都已包含该分片的副本。
要解决此问题,您可以向群集添加更多数据节点或减少副本数。在我们的示例中,我们要么需要在集群中添加至少两个节点,要么将复制因子减少到两个,如下所示:
curl -XPUT 'localhost:9200//_settings' -d '{"number_of_replicas": 2}'
减少副本数量后,查看Kopf以查看是否已分配所有分片。
原因3:您需要重新启用分片分配
在下面的Kopf屏幕截图中,一个节点刚加入群集,但尚未分配任何分片。
默认情况下,在所有节点上启用分片分配,但您可能在某些时候禁用了分片分配(例如,为了执行滚动重新启动),并且忘记重新启用它。
To enable shard allocation, update the Cluster Settings API:
curl -XPUT 'localhost:9200/_cluster/settings' -d
'{ "transient":
{ "cluster.routing.allocation.enable" : "all"
}
}'
如果这解决了问题,则Kopf或Datadog仪表板应显示未成功分片的数量,因为它们已成功分配给节点。
未分配的分片datadogThis Datadog timeseries图表显示重新启用分片分配后未分配的分片数量减少。
启用分配后未分配的分片更新的Kopf仪表板显示在重新启用分片分配后,已分配了许多以前未分配的分片。 看起来这解决了所有未分配的分片的问题,但有一个例外:常量更新索引的分片0。让我们探讨碎片保持未分配的其他可能原因。
原因4:群集中不再存在分片数据
在这种情况下,常量更新索引的主分片0未分配。它可能是在没有任何副本的节点上创建的(一种用于加速初始索引过程的技术),并且节点在可以复制数据之前离开了集群。主服务器在其全局群集状态文件中检测到分片,但无法在群集中找到分片的数据。
另一种可能性是节点在重新启动时可能遇到问题。通常,当节点恢复其与群集的连接时,它会将有关其磁盘分片的信息中继到主服务器,然后主服务器将这些分片从“未分配”转换为“已分配/已启动”。当此过程由于某种原因而失败时(例如,节点的存储已经以某种方式损坏),分片可能保持未分配状态。
在这种情况下,您必须决定如何继续:尝试让原始节点恢复并重新加入群集(并且不强制分配主分片),或者使用Reroute API强制分配分片并使用重新索引丢失的数据原始数据源,或来自备份。
如果您决定分配未分配的主分片,请确保在请求中添加“allow_primary”:“true”标志:
curl -XPOST 'localhost:9200/_cluster/reroute' -d
'{ "commands" :
[ { "allocate" :
{ "index" : "constant-updates", "shard" : 0, "node": "", "allow_primary": "true" }
}]
}'
如果没有“allow_primary”:“true”标志,我们会遇到以下错误:
{"error":{"root_cause":[{"type":"remote_transport_exception","reason":"[NODE_NAME][127.0.0.1:9301][cluster:admin/reroute]"}],"type":"illegal_argument_exception","reason":"[allocate] trying to allocate a primary shard [constant-updates][0], which is disabled"},"status":400}
强制分配主分片的警告是你将分配一个“空”分片。如果包含原始主分片数据的节点稍后将重新加入群集,则其数据将被新创建的(空)主分片覆盖,因为它将被视为数据的“较新”版本。
您现在需要重新索引丢失的数据,或使用快照和还原API从备份快照中尽可能多地还原。
Reason 5: Low disk watermark
(磁盘水印低)
如果没有足够的磁盘空间节点,主节点可能无法分配分片(它不会将分片分配给使用率超过85%的磁盘的节点)。一旦节点达到此磁盘使用级别,或Elasticsearch称之为“低磁盘水印”,则不会为其分配更多分片。
您可以通过查询cat API来检查群集中每个节点上的磁盘空间(并查看每个节点上存储的分片):
curl -s 'localhost:9200/_cat/allocation?v'
如果任何特定节点的磁盘空间不足(删除过时的数据并将其存储在群集外,添加更多节点,升级硬件等),请参阅此文章以获取有关如何操作的选项。
如果您的节点具有大磁盘容量,则85%的低水印可能太低。您可以使用Cluster Update Settings API更改cluster.routing.allocation.disk.watermark.low和/或cluster.routing.allocation.disk.watermark.high。例如,此Stack Overflow thread指出,如果您的节点具有5TB磁盘容量,则可以安全地将低磁盘水印增加到90%:
curl -XPUT 'localhost:9200/_cluster/settings' -d
'{
"transient": {
"cluster.routing.allocation.disk.watermark.low": "90%"
}
}'
如果希望在群集重新启动时保持配置更改,请将“transient”替换为“persistent”,或者在配置文件中更新这些值。您可以选择使用字节或百分比值来更新这些设置,但请务必记住Elasticsearch文档中的这一重要说明:“百分比值是指已用磁盘空间,而字节值是指可用磁盘空间”。
原因6:多个Elasticsearch版本
此问题仅出现在运行多个Elasticsearch版本的集群中(可能在滚动升级过程中)。根据Elasticsearch文档,主节点不会将主分片的副本分配给运行旧版本的任何节点。例如,如果主分片在1.4版上运行,则主分区将无法将该分片的副本分配给运行1.4之前的任何版本的任何节点。
如果您尝试将分片从较新版本节点手动重新路由到较旧版本节点,您将看到如下错误:
[NO(target node version [XXX] is older than source node version [XXX])]
Elasticsearch不支持回滚到以前的版本,只支持升级。升级运行旧版本的节点应解决该问题,如果这确实是目前需要的问题。
你试过把它关掉再打开吗?
如果上述方案均不适用于您的情况,您仍然可以选择重新索引原始数据源中的缺失数据,或者从旧快照还原受影响的索引,如此处所述(https://www.elastic.co/cn/blog/introducing-snapshot-restore)。
监视未分配的分片
尽快修复未分配的分片非常重要,因为它们表明数据丢失/不可用,或者您的群集未配置为最佳可靠性。如果您已经在使用Datadog,请打开Elasticsearch集成,您将立即开始监控未分配的分片和其他关键的Elasticsearch性能和运行状况指标。如果您不使用Datadog但愿意,请注册免费试用版。
原文地址
https://elasticsearch.cn/book/elasticsearch_definitive_guide_2.x/_talking_to_elasticsearch.html