ElasticSearch:未分配的碎片,如何解决?

时间:2013-11-14 00:49:34

标签: elasticsearch sharding master

我有一个包含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
}

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

  • 删除(取消)分片?
  • 将分片移动到另一个节点?
  • 将分片分配给节点?
  • 将'number_of_replicas'更新为2?
  • 还有其他什么吗?

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

关注问题:我是否做错了导致这种情况发生在一开始?对重新启动节点时以这种方式运行的集群,我没有多少信心。

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

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

25 个答案:

答案 0 :(得分:106)

默认情况下,Elasticsearch会动态地为节点重新分配分片。但是,如果您已禁用分片分配(可能您执行了rolling restart并忘记重新启用它),则可以重新启用分片分配。

# 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您的线程池may be too small

最后,您可以使用reroute API明确地将分片重新分配给节点。

# 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
        }
    }]
}'

答案 1 :(得分:53)

好的,我已经在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配置中,从那时起,服务器/服务的任何重新启动都没有问题。碎片立即重新分配回来。

FWIW,为了回答一个经常被追捧的问题,将MAX_HEAP_SIZE设置为30G,除非你的机器的RAM少于60G,在这种情况下将其设置为可用内存的一半。

参考

答案 2 :(得分:37)

这个小小的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

答案 3 :(得分:14)

唯一对我有用的是更改number_of_replicas(我有2个副本,所以我将其更改为1,然后再更改为2)。

首先:

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

然后:

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

(我已经在this question中找到了答案)

答案 4 :(得分:9)

如果将以下配置设置为all,Elasticsearch会自动分配分片。可以使用rest api as well设置此配置 cluster.routing.allocation.enable:all

如果在应用下面的配置后,es无法自动分配分片,那么你必须自己强制分配分片。 ES official link for this

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

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

#!/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

答案 5 :(得分:6)

我今天遇到了同样的分片分配问题。那个脚本 W. Andrew Loe III在他的回答中提出并不适合我,所以我对它进行了一些修改,最终有效:

#!/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

现在,我不是一个Bash大师,但脚本真的适合我的情况。请注意,您需要为“ES_HOST”和“NODE”变量指定适当的值。

答案 6 :(得分:5)

就我而言,已达到硬盘空间上限。

看看这篇文章: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"
  }
}

因此,如果使用&lt; 90%的硬盘空间,它将分配,并且如果使用> 95%的硬盘空间,则将分片移动到群集中的另一台机器;它每1分钟检查一次。

答案 7 :(得分:4)

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

希望它有所帮助! :)

答案 8 :(得分:3)

就我而言,当我创建新的 索引 时,默认 number_of_replicas 设置为1。并且我的集群中的节点数量只有一个,因此没有额外的节点来创建副本,因此健康状况变为黄色。 因此,当我使用 设置 属性创建索引并将 number_of_replicas 设置为0.然后它工作正常。希望这会有所帮助。

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

答案 9 :(得分:3)

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

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

  

[NO(目标节点版本[1.4.2]比源节点版本旧   [1.4.4])]

将旧节点更新为1.4.4后,这些节点开始与其他好节点重新绑定。

答案 10 :(得分:3)

我也遇到过这个问题,我找到了解决问题的简单方法。

  • 获取未分配分片的索引

    $ curl -XGET http://172.16.4.140:9200/_cat/shards
    
  • 安装curator工具,并使用它删除索引

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

    注意:在我的情况下,索引是2016-04-21当天的logstash

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

答案 11 :(得分:2)

我也遇到了类似的错误。这件事发生在我身上,是因为我的一个数据节点已满,并且碎片分配失败。如果存在未分配的分片,并且您的群集为RED,并且索引也为RED,那么在这种情况下,我将按照以下步骤操作,它们就像冠军一样。
在kibana开发工具中-

GET _cluster/allocation/explain

如果有任何未分配的分片,则您将获得详细信息,否则将引发错误。

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

POST _cluster/reroute?retry_failed

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

答案 12 :(得分:2)

我也遇到了这种情况并最终解决了。

首先,我将描述我的情况。我在ElasticSearch集群中有两个节点,他们可以找到彼此,但是当我创建一个设置&#34; number_of_replicas&#34; :2 ,&#34; number_of_shards&#34; :5,ES显示黄色信号,unassigned_shards为5。

问题出现是因为 number_of_replicas 的值,当我用 1 设置其值时,一切都很好。

答案 13 :(得分:1)

在我的情况下,具有旧共享的旧节点正在加入群集,因此我们必须关闭旧节点并使用未分配的分片删除索引。

答案 14 :(得分:1)

我尝试了上面的一些建议,但不幸的是,它们都没有奏效。我们在较低的环境中有一个“日志”索引,应用程序会在其中编写错误。它是单节点集群。为我解决的是检查节点的YML配置文件,并发现它仍然具有默认设置“gateway.expected_nodes:2”。这超越了我们拥有的任何其他设置。每当我们在这个节点上创建索引时,它会尝试将3个分片中的3个分散到虚拟第2个节点。因此,这些将显示为未分配,并且永远不会被移动到第一个和唯一的节点。

解决方案是编辑配置,将设置“gateway.expected_nodes”更改为1,因此它将退出查找群集中永远不会找到的兄弟,并重新启动Elastic服务实例。此外,我不得不删除索引,并创建一个新索引。创建索引后,分片全部显示在第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

答案 15 :(得分:1)

对我来说,这是通过从开发控制台运行来解决的:&#34; POST / _cluster / reroute?retry_failed&#34;

.....

我首先查看索引列表以查看哪些索引是红色然后运行

&#34; get /_cat/shards?h=[INDEXNAME],shard,prirep,state,unassigned.reason"

并且看到它的分片卡在ALLOCATION_FAILED状态,因此运行上面的重试会导致他们重新尝试分配。

答案 16 :(得分:0)

首先使用 cluster health API 获取集群的当前运行状况,其中 RED 表示缺少一个或多个主分片,而黄色表示缺少多个副本分片之一。

此后,使用 cluster allocation explain API 了解为什么缺少特定分片并且 elasticsearch 无法在数据节点上分配它。

一旦找到确切的根本原因,尝试解决问题,这通常需要更改一些集群设置(在@wilfred 回答earlier 中提到)但在某些情况下,如果它的副本分片,并且您有同一分片的另一个副本(即另一个副本)可用,您可以使用 update replica setting 减少副本数量,然后在需要时再次增加它。

除上述之外,如果您的集群分配 API 提到它没有有效的数据节点来分配分片,那么您需要添加新的数据节点,或更改 shard allocation awareness settings

答案 17 :(得分:0)

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

可以通过设置其他阈值或通过.yml或通过Kibana禁用它来解决此问题

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

答案 18 :(得分:0)

在处理损坏的分片时,可以将复制因子设置为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。

答案 19 :(得分:0)

我刚增加了

  

“ index.number_of_replicas”

减1(直到节点同步),然后再减1,这有效地删除了未分配的分片,并且群集再次变为绿色,而没有丢失任何数据的风险。

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

希望这会有所帮助。

答案 20 :(得分:0)

我有两个带有未分配碎片的索引,这些索引似乎无法自我修复。我最终通过临时添加额外数据节点 [1] 解决了此问题。在指标恢复健康并且一切都稳定为绿色之后,我移除了多余的节点,系统得以重新平衡(重新)并处于健康状态。

最好避免一次杀死多个数据节点(这就是我进入此状态的方式)。可能,我没有为至少一个分片保留任何副本/副本。幸运的是,Kubernetes保留了磁盘存储,并在我重新启动数据节点时重新使用了它。


...有些时间过去了...

好吧,这次只是添加一个节点似乎不起作用(在等待几分钟后,某件事才发生),所以我开始研究REST API。

GET /_cluster/allocation/explain

这显示了我的新节点为"decision": "YES"

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

然后我做了以下简单的POST [2] 没有身体这使事情陷入了困境 ...

POST /_cluster/reroute

其他说明:


[1] 如果您有足够的净空,那么在Kubernetes中很容易做到:只需通过仪表板扩展状态集即可。 < / p>

[2] 使用Kibana的“ Dev工具”界面,我不必费心SSH / exec shell。

答案 21 :(得分:0)

我尝试删除未分配的分片或手动将它们分配给特定的数据节点。它没有用,因为未分配的碎片不断出现,健康状况一遍又一遍“红”。 然后我注意到其中一个数据节点处于“重启”状态。我减少了数据节点的数量,杀了它。问题不再可再生。

答案 22 :(得分:0)

我遇到了完全相同的问题。这可以通过在重新启动elasticsearch之前临时将分片分配设置为false来防止,但如果它们已经存在,则无法修复未分配的分片。

在我的情况下,这是由数据节点上缺少可用磁盘空间引起的。未分配的分片,在重新启动后仍在数据节点上但主分机无法识别它们。

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

答案 23 :(得分:0)

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

  

从最新版本到上一版本的分片复制   版本不起作用

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

Elastic Documentation - Rolling Upgrade Process

答案 24 :(得分:0)

可能有帮助,但在尝试以嵌入模式运行ES时出现此问题。修复是为了确保Node具有本地(true)设置。