188

I have an ES cluster with 4 nodes:

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

I had to restart search03, and when it came back, it rejoined the cluster no problem, but left 7 unassigned shards laying about.

{
  "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
}

Now my cluster is in yellow state. What is the best way to resolve this issue?

  • Delete (cancel) the shards?
  • Move the shards to another node?
  • Allocate the shards to the node?
  • Update 'number_of_replicas' to 2?
  • Something else entirely?

Interestingly, when a new index was added, that node started working on it and played nice with the rest of the cluster, it just left the unassigned shards laying about.

Follow on question: am I doing something wrong to cause this to happen in the first place? I don't have much confidence in a cluster that behaves this way when a node is restarted.

NOTE: If you're running a single node cluster for some reason, you might simply need to do the following:

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

28 回答 28

125

默认情况下,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你的线程池可能太小了

最后,您可以使用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
        }
    }]
}'
于 2014-05-21T10:48:12.977 回答
61

好的,我在 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,在这种情况下,请将其设置为可用内存的一半。

参考

于 2013-11-15T21:01:59.607 回答
42

这个小 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
于 2014-11-04T22:24:04.667 回答
21

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

GET _cluster/allocation/explain

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

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

POST _cluster/reroute?retry_failed

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

于 2020-09-07T12:22:35.167 回答
17

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

第一的:

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

然后:

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

(我已经在这个问题中回答了)

于 2015-04-12T11:47:36.503 回答
9

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

如果即使应用了以下配置,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
于 2016-12-13T19:18:25.307 回答
7

我今天遇到了同样的分片分配问题。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”变量指定适当的值。

于 2016-02-23T09:41:39.243 回答
6

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

看这篇文章: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 分钟检查一次。

于 2016-08-29T18:29:17.050 回答
6

在我的情况下,当我创建一个新索引时,默认number_of_replicas设置为 1。我的集群中的节点数只有一个,因此没有额外的节点来创建副本,因此运行状况变为黄色。因此,当我使用设置属性 创建索引并将number_of_replicas设置为 0 时,它工作正常。希望这可以帮助。

PUT /customer
{
    "settings": {
        "number_of_replicas": 0
    }
}
于 2015-11-22T14:26:15.690 回答
4

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

希望它可以帮助某人!:)

于 2015-04-09T10:23:22.720 回答
4

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

  • 获取未分配分片的索引

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

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

    注意:就我而言,索引是 2016-04-21 当天的 logstash

  • 然后再次检查分片,所有未分配的分片都消失了!
于 2016-04-26T08:13:43.763 回答
3

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

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

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

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

于 2015-03-09T20:16:20.427 回答
2

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

首先,我将描述我的情况。我在 ElasticSearch 集群中有两个节点,它们可以相互找到,但是当我使用设置“number_of_replicas”:2 、“number_of_shards”:5创建索引时,ES 显示黄色信号,而 unassigned_shards 为 5。

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

于 2014-10-17T11:26:50.630 回答
2

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

......

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

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

并看到它有碎片卡在 ALLOCATION_FAILED 状态,所以运行上面的重试导致他们重新尝试分配。

于 2018-03-14T00:54:34.770 回答
1

在我的例子中,一个具有旧共享的旧节点正在加入集群,因此我们不得不关闭旧节点并删除具有未分配分片的索引。

于 2015-06-24T13:17:36.523 回答
1

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

解决方案是编辑配置,将设置“gateway.expected_nodes”更改为 1,这样它就不会在集群中寻找它永远找不到的兄弟,并重新启动 Elastic 服务实例。此外,我不得不删除索引,并创建一个新的。创建索引后,分片都出现在第一个也是唯一的节点上,并且没有一个未分配。

# 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
于 2016-04-28T19:02:57.073 回答
0

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

于 2015-06-02T22:29:35.343 回答
0

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

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

只需从磁盘中清除 1 个节点,我就开始了复制过程。这是一个相当缓慢的过程,因为所有数据都必须从一个数据节点复制到另一个数据节点。

于 2015-10-28T15:31:00.293 回答
0

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

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

PUT _cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.disk.threshold_enabled": "false"
  }
}
于 2020-09-05T18:22:02.800 回答
0

如果您使用的是 aws elasticsearch 服务,上述建议将无法提供解决方案。在这种情况下,我使用连接到 s3 的备份结构来备份索引。然后我删除了索引并恢复了它。它对我有用。请确保备份成功完成!

于 2022-02-18T12:59:48.477 回答
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。

于 2019-07-26T15:20:31.340 回答
0

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

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


……过了一段时间……

好吧,这一次只是添加一个节点似乎不起作用(在等待几分钟之后),所以我开始在 REST API 中四处寻找。

GET /_cluster/allocation/explain

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

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

然后我做了以下没有 body的简单 POST [2]这让事情开始运转......

POST /_cluster/reroute

其他注意事项:


[1]如果你有足够的空间,在 Kubernetes 中很容易做到:只需通过仪表板扩展有状态集。

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

于 2019-02-10T02:19:04.187 回答
0

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

Primary 你必须通过"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"
        }
    }]
}

集群重新路由文档

于 2021-10-15T08:21:53.773 回答
0

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

从较新版本到以前版本的分片复制将不起作用

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

Elastic 文档 - 滚动升级过程

于 2015-10-13T21:56:20.520 回答
0

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

于 2016-10-25T00:51:20.420 回答
0

我刚开始增加

“index.number_of_replicas”

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

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

希望这可以帮助。

于 2019-06-04T10:39:19.217 回答
0

如果您有未分配的分片,通常第一步是调用分配说明 API并查找原因。根据原因,你会做一些事情。以下是一些我想到的:

  • 节点没有足够的磁盘空间(检查基于磁盘的分配设置)
  • 由于分配被禁用分配过滤感知等限制,节点无法分配分片(例如,节点位于集群的错误一侧,如其他可用区或热节点或暖节点)
  • 加载分片时出错。例如,文件校验和失败,分析器引用的同义词文件丢失

有时它有助于快速启动它,例如使用Cluster Reroute API手动分配分片,或者禁用和重新启用副本。

如果您需要有关操作 Elasticsearch 的更多信息,请查看 Sematext 的Elasticsearch 操作培训(免责声明:我正在提供)。

于 2021-09-16T14:40:51.993 回答
0

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

在此之后,使用集群分配解释 API来了解为什么缺少特定分片并且 elasticsearch 无法在数据节点上分配它。

一旦你得到了确切的根本原因,试着解决这个问题,这通常需要改变一些集群设置(在前面的@wilfred 回答中提到)但是在某些情况下,如果它的副本分片,并且你有另一个相同分片的副本(即另一个副本)可用,您可以使用更新副本设置减少副本数,然后如果需要,可以再次增加它。

除此之外,如果您的集群分配 API 提到它没有有效的数据节点来分配分片,那么您需要添加新的数据节点,或者更改分片分配感知设置

于 2020-12-22T13:54:34.687 回答