Elasticsearch:未分配的碎片,如何修复?

我有一个具有4个节点的ES集群:

number_of_replicas: 1
search01 - master: false, data: false
search02 - master: true, data: true
search03 - master: false, data: true
search04 - master: false, data: true

我不得不重新启动Search03,当它回来时,它重新加入了集群,没有问题,但留下了7个未分配的碎片。

{
"cluster_name" : "tweedle",
"status" : "yellow",
"timed_out" : false,
"number_of_nodes" : 4,
"number_of_data_nodes" : 3,
"active_primary_shards" : 15,
"active_shards" : 23,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 7
}

现在我的集群处于黄色状态。解决此问题的最佳方法是什么?

  • 删除(取消)碎片?
  • 将碎片移动到另一个节点?
  • 是否将碎片分配给节点?
  • 是否将“_副本的_数量”更新为2?
  • 完全是别的东西?

有趣的是,当一个新的索引被添加时,该节点开始处理它,并与集群的其余部分很好地合作,它只是留下了未分配的碎片。

接下来的问题是:我是不是做错了什么,导致了这一切的发生?当节点重新启动时,我对以这种方式运行的集群没有太多信心。

注意:如果您出于某种原因正在运行单节点集群,您可能只需要执行以下操作:

curl -XPUT 'localhost:9200/_settings' -d '
{
"index" : {
"number_of_replicas" : 0
}
}'
303519 次浏览

好的,我已经在ES支持的帮助下解决了这个问题。向所有节点(或您认为是问题原因的节点)上的API发出以下命令:

curl -XPUT 'localhost:9200/<index>/_settings' \
-d '{"index.routing.allocation.disable_allocation": false}'

其中<index>是您认为是罪魁祸首的指数。如果您不知道,只需在所有节点上运行:

curl -XPUT 'localhost:9200/_settings' \
-d '{"index.routing.allocation.disable_allocation": false}'

我还将这一行添加到我的YAML配置中,从那时起,服务器/服务的任何重新启动都没有问题。碎片立即重新分配回来。

顺便说一句,要回答一个经常遇到的问题,请将最大_堆_大小设置为30G,除非您的机器的RAM小于60G,在这种情况下,请将其设置为可用内存的一半。

参考文献

默认情况下,Elasticsearch会动态地将碎片重新分配给节点。然而,如果您已经禁用了分片分配(也许您做了一个滚动重启并且忘记重新启用它),您可以重新启用分片分配。

# v0.90.x and earlier
curl -XPUT 'localhost:9200/_settings' -d '{
"index.routing.allocation.disable_allocation": false
}'


# v1.0+
curl -XPUT 'localhost:9200/_cluster/settings' -d '{
"transient" : {
"cluster.routing.allocation.enable" : "all"
}
}'

然后,Elasticsearch将正常重新分配碎片。这可能会很慢,请考虑提高indices.recovery.max_bytes_per_seccluster.routing.allocation.node_concurrent_recoveries以加快速度。

如果您仍然看到问题,则可能是其他问题,因此请查看您的ElasticSearch日志中的错误。如果您看到EsRejectedExecutionException,那么您的线程池可能太小

最后,您可以显式地将一个分片重新分配给一个__为abc0的节点。

# Suppose shard 4 of index "my-index" is unassigned, so you want to
# assign it to node search03:
curl -XPOST 'localhost:9200/_cluster/reroute' -d '{
"commands": [{
"allocate": {
"index": "my-index",
"shard": 4,
"node": "search03",
"allow_primary": 1
}
}]
}'

我也遇到了这种情况,终于解决了。

首先,我将描述我的情况。我在ElasticSearch集群中有两个节点,它们可以找到彼此,但当我创建一个设置“_副本的_数量”:2的索引时,“_碎片的数量_”:5,ES显示黄色信号,未分配的_碎片为5。

出现问题是因为_副本的_数量的值,当我用1设置它的值时,一切正常。

这个小bash脚本将暴力重新分配,您可能会丢失数据。

NODE="YOUR NODE NAME"
IFS=$'\n'
for line in $(curl -s 'localhost:9200/_cat/shards' | fgrep UNASSIGNED); do
INDEX=$(echo $line | (awk '{print $1}'))
SHARD=$(echo $line | (awk '{print $2}'))


curl -XPOST 'localhost:9200/_cluster/reroute' -d '{
"commands": [
{
"allocate": {
"index": "'$INDEX'",
"shard": '$SHARD',
"node": "'$NODE'",
"allow_primary": true
}
}
]
}'
done

我遇到了同样的问题,但根本原因是版本号不同(两个节点上的1.4.2(有问题)和两个节点上的1.4.4(正常))。第一个和第二个答案(将“ index.routing.allocation.disable_分配”设置为false,将“ cluster.routing.allocation.enable ”设置为“ all ”)不起作用。

但是,@Wilfred Hughes的回答(使用Transient将“ cluster.routing.allocation.enable ”设置为“ all ”)给我提供了以下语句错误:

[否(目标节点版本[1.4.2]早于源节点版本 [1.4.4]]

在将旧节点更新为1.4.4后,这些节点开始与其他良好节点重新连接。

也许这对某些人有帮助,但我也遇到了同样的问题,这是由于日志变得太大而导致的存储空间不足。

希望它能帮助一些人!:)

唯一对我有用的是更改_副本的_数量(我有2个副本,所以我将其更改为1,然后又改回2)。

首先:

PUT /myindex/_settings
{
"index" : {
"number_of_replicas" : 1
}
}

然后:

PUT /myindex/_settings
{
"index" : {
"number_of_replicas" : 2
}
}

(我已经在这个问题中看到了它)

可能会有帮助,但我在尝试以嵌入式模式运行ES时遇到了这个问题。修复方法是确保节点具有本地(true)设置。

在我的示例中,具有旧共享的旧节点正在加入集群,因此我们必须关闭旧节点并删除具有未分配碎片的索引。

未分配碎片的另一个可能原因是您的集群正在运行多个版本的Elasticsearch二进制文件。

从较新版本到较早版本的

碎片复制 版本将不起作用

这可能是未分配碎片的根本原因。

弹性文档-滚动升级过程

我也遇到了同样的问题。这可以通过在重新启动Elasticsearch之前将碎片大厦分配临时设置为false来防止,但这不会修复未分配的碎片(如果它们已经存在)。

在我的例子中,它是由数据节点上的可用磁盘空间不足引起的。重新启动后,未分配的碎片仍在数据节点上,但主节点无法识别它们。

只需从磁盘中清理1个节点,就可以为我启动复制过程。这是一个相当慢的过程,因为所有数据都必须从一个数据节点复制到另一个数据节点。

在我的示例中,当我创建新的索引时,默认__副本的数量设置为1。我的集群中的节点数只有一个,因此没有额外的节点来创建副本,因此运行状况变为黄色。 因此,当我用设置属性创建索引并将_副本的_数量设置为0时,它工作得很好。希望这对你有帮助.

PUT /customer
{
"settings": {
"number_of_replicas": 0
}
}

我今天遇到了同样的碎片分配问题。那个剧本 ABC0在他的回答中提出的__对我不起作用,所以我稍微修改了一下,它终于起作用了:

#!/usr/bin/env bash


# The script performs force relocation of all unassigned shards,
# of all indices to a specified node (NODE variable)


ES_HOST="<elasticsearch host>"
NODE="<node name>"


curl ${ES_HOST}:9200/_cat/shards > shards
grep "UNASSIGNED" shards > unassigned_shards


while read LINE; do
IFS=" " read -r -a ARRAY <<< "$LINE"
INDEX=${ARRAY[0]}
SHARD=${ARRAY[1]}


echo "Relocating:"
echo "Index: ${INDEX}"
echo "Shard: ${SHARD}"
echo "To node: ${NODE}"


curl -s -XPOST "${ES_HOST}:9200/_cluster/reroute" -d "{
\"commands\": [
{
\"allocate\": {
\"index\": \"${INDEX}\",
\"shard\": ${SHARD},
\"node\": \"${NODE}\",
\"allow_primary\": true
}
}
]
}"; echo
echo "------------------------------"
done <unassigned_shards


rm shards
rm unassigned_shards


exit 0

现在,我不是那种巴什大师,但脚本确实适合我的情况。请注意,您需要为“ ES_主机”和“节点”变量指定适当的值。

我也有这个问题,我找到了一个简单的方法来解决它。

  • 获取未分配碎片的索引

    $ curl -XGET http://172.16.4.140:9200/_cat/shards
    
  • Install curator Tools, and use it to delete index

    $ curator --host 172.16.4.140 delete indices --older-than 1 \
    --timestring '%Y.%m.%d' --time-unit days --prefix logstash
    

    注意:在我的例子中,指数是每日日志2016-04-21

  • 然后再次检查碎片,所有未分配的碎片都会消失!

我尝试了上面的几个建议,不幸的是,它们都不起作用。我们在较低的环境中有一个“日志”索引,应用程序在其中写入它们的错误。它是一个单节点集群。我解决这个问题的方法是检查节点的YML配置文件,发现它仍然具有默认设置“ Gateway.Expected_节点:2 ”。这覆盖了我们所有的其他设置。每当我们在这个节点上创建索引时,它都会尝试将5个碎片中的3个扩展到第2个幻像节点。因此,它们将显示为未分配,并且永远不能移动到第一个也是唯一的节点。

解决方案是编辑配置,将设置“ gateway.expected_节点”更改为1,这样它将停止在集群中查找其永远找不到的兄弟,并重新启动弹性服务实例。此外,我不得不删除索引,并创建一个新的。创建索引后,所有碎片都显示在第一个也是唯一一个节点上,没有未分配的碎片。

# Set how many nodes are expected in this cluster. Once these N nodes
# are up (and recover_after_nodes is met), begin recovery process immediately
# (without waiting for recover_after_time to expire):
#
# gateway.expected_nodes: 2
gateway.expected_nodes: 1

在我的例子中,达到了硬盘空间的上限。

请看这篇文章:https://www.elastic.co/guide/en/elasticsearch/reference/current/disk-allocator.html

基本上,我跑:

PUT /_cluster/settings
{
"transient": {
"cluster.routing.allocation.disk.watermark.low": "90%",
"cluster.routing.allocation.disk.watermark.high": "95%",
"cluster.info.update.interval": "1m"
}
}

以便在使用了<;90%的硬盘空间时进行分配,并在使用了>95%的硬盘空间时将碎片移动到集群中的另一台计算机。它每1分钟检查一次。

我尝试删除未分配的碎片或手动将其分配给特定的数据节点。它不起作用,因为未分配的碎片不断出现,健康状态一次又一次地显示为“红色”。 然后我注意到其中一个数据节点停留在“重新启动”状态。我减少了数据节点的数量,杀死了它。问题不再重现。

如果下面的配置设置为ALL,Elasticsearch会自动分配碎片。也可以使用REST API设置此配置 集群.路由.分配.启用:全部

如果在应用了下面的配置之后,ES仍然无法自动分配分片,那么您必须自己强制分配分片。这个的ES官方链接

我已经编写了一个脚本来强制在集群中分配所有未分配的碎片。

下面的数组包含要在其中平衡未分配碎片的节点的列表

#!/bin/bash
array=( node1 node2 node3 )
node_counter=0
length=${#array[@]}
IFS=$'\n'
for line in $(curl -s 'http://127.0.0.1:9200/_cat/shards'|  fgrep UNASSIGNED); do
INDEX=$(echo $line | (awk '{print $1}'))
SHARD=$(echo $line | (awk '{print $2}'))
NODE=${array[$node_counter]}
echo $NODE
curl -XPOST 'http://127.0.0.1:9200/_cluster/reroute' -d '{
"commands": [
{
"allocate": {
"index": "'$INDEX'",
"shard": '$SHARD',
"node": "'$NODE'",
"allow_primary": true
}
}
]
}'
node_counter=$(((node_counter)%length +1))
done

对我来说,这个问题可以通过从开发控制台运行以下命令来解决:“ POST/_群集/重新路由?重试_失败”。

.....

我首先查看指数列表,看看哪些指数是红色的,然后运行

“获取/_cat/shards?H=[indexname],shard,prirep,state,unassigned.reason ”

并且发现它的分片停留在分配_失败状态,因此运行上面的重试会导致它们重新尝试分配。

我有两个未分配碎片的索引,它们似乎不能自我修复。通过临时添加额外数据节点[1],我最终解决了这个问题。在指数变得健康,一切都稳定在绿色之后,我已删除额外节点,系统能够(再次)重新平衡,并稳定在一个健康的状态。

避免一次杀死多个数据节点是一个好主意(这是我进入这种状态的原因)。很可能,我没有为至少一个碎片保留任何副本/复制品。幸运的是,Kubernetes保留了磁盘存储,并在我重新启动数据节点时重新使用它。


...一段时间过去了……

好吧,这一次仅仅添加一个节点似乎不起作用(在等待几分钟后发生了一些事情),所以我开始在REST API中四处打探。

GET /_cluster/allocation/explain

这显示了我的__为ABC0的新节点。

顺便说一下,由于"the node is above the low watermark cluster setting",所有预先存在的节点都具有"decision": "NO"。所以这可能与我之前提到的情况不同。

然后我做了以下简单的POST[2]没有尸体这让事情进入了状态。..

POST /_cluster/reroute

其他说明:


如果你有足够的空间,__abc0在Kubernetes中很容易做到:__abc1

__使用Kibana “ Dev Tools ”界面的ABC0,我不必使用SSH/exec shell.

我只是第一次增加了

“ index.number_副本的_”

1(等待节点同步),然后将其减少1,这可以有效地删除未分配的碎片,并且集群再次变为绿色,而不会有丢失任何数据的风险。

我相信有更好的方法,但这对我来说更容易。

希望这能有所帮助。

在处理损坏的碎片时,您可以将复制因子设置为0,然后将其设置回原始值。这将清除大部分(如果不是全部)损坏的碎片,并在集群中重新定位新的副本。

将具有未分配副本的索引设置为使用复制因子0:

curl -XGET http://localhost:9200/_cat/shards |\
grep UNASSIGNED | grep ' r ' |\
awk '{print $1}' |\
xargs -I {} curl -XPUT http://localhost:9200/{}/_settings -H "Content-Type: application/json" \
-d '{ "index":{ "number_of_replicas": 0}}'

将它们设置回1:

curl -XGET http://localhost:9200/_cat/shards |\
awk '{print $1}' |\
xargs -I {} curl -XPUT http://localhost:9200/{}/_settings -H "Content-Type: application/json" \
-d '{ "index":{ "number_of_replicas": 1}}'

注意:如果不同的索引具有不同的复制因子,则不要运行此命令。这会将所有索引的复制因子硬编码为1。

这也可能是磁盘空间的原因, 在Elasticsearch 7.5.2中,默认情况下,如果磁盘使用率高于85%,则不会将副本碎片分配给任何其他节点。

这可以通过设置不同的阈值或在.yml中或通过Kibana禁用它来解决

PUT _cluster/settings
{
"persistent": {
"cluster.routing.allocation.disk.threshold_enabled": "false"
}
}

我也遇到了类似的错误。它发生在我身上,因为我的一个数据节点已满,并且由于碎片分配失败。如果未分配的碎片在那里,并且你的集群是红色的,一些索引也是红色的,在这种情况下,我遵循了下面的步骤,这些工作就像冠军一样。
在Kibana开发工具中-

GET _cluster/allocation/explain

如果有任何未分配的碎片,那么您将获得详细信息,否则将抛出错误。

只需运行以下命令即可解决所有问题-

POST _cluster/reroute?retry_failed

感谢-
https://github.com/elastic/elasticsearch/issues/23199#issuecomment-280272888

首先使用群集运行状况API来获取集群的当前健康状况,其中红色表示缺少一个或多个主碎片,黄色表示缺少一个或多个副本碎片。

在此之后,使用集群分配解释API来了解特定碎片丢失以及Elasticsearch无法在数据节点上分配它的原因。

找到确切的根本原因后,请尝试解决该问题,这通常需要更改一些群集设置(在@Wilfred Answer更早的中提到),但在某些情况下,如果其副本碎片,并且您有同一碎片的另一个副本(即另一个副本)可用,则可以使用更新副本设置减少副本计数,然后在需要时再次增加它。

除了上面提到的,如果您的集群分配API没有有效的数据节点来分配碎片,那么您需要添加一个新的数据节点,或者更改碎片分配感知设置

如果您有一个未分配的碎片,通常第一步是调用分配解释API并查找原因。根据原因,你会做些什么。以下是我想到的一些例子:

  • 节点没有足够的磁盘空间(请检查基于磁盘的分配设置)
  • 由于某些限制(如分配已禁用分配过滤意识),节点无法分配碎片大厦(例如,节点位于群集的错误端,如其他可用性区域或热节点或暖节点)
  • 加载碎片大厦时出错。例如,文件的校验和失败,分析器引用的同义词文件丢失

有时,它有助于快速启动IT,如使用群集重新路由API手动分配碎片大厦,或禁用并重新启用副本。

如果您需要有关操作Elasticsearch的更多信息,请查看Sematext的弹性搜索操作培训(免责声明:我正在交付它)。

在ES 7.4.2上有类似的问题,命令已更改。正如在回答中已经提到的,首先要检查GET _cluster/allocation/explain?pretty,然后是POST _cluster/reroute?retry_failed

主要的 您必须为主碎片

传递"accept_data_loss": true
POST _cluster/reroute
{
"commands": [{
"allocate_stale_primary": {
"index": "filebeat-7.4.2-xxxx",
"shard": 0,
"node": "my_node",
"accept_data_loss": false
}
}]
}

复制品

POST _cluster/reroute
{
"commands": [{
"allocate_replica": {
"index": "filebeat-7.4.2-xxxx",
"shard": 0,
"node": "my_other_node"
}
}]
}

集群重新路由文档

如果您正在使用AWS ElasticSearch服务,则上述建议不会提供解决方案。在本例中,我使用连接到S3的备份结构来备份索引。然后我删除了索引并恢复了它。对我来说很有效。请确保备份成功完成!