ElasticSearch: неназначенные осколки, как исправить?

166

У меня есть кластер ES с 4 узлами:

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
    }
}'
Spanky
источник

Ответы:

118

По умолчанию 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_secи cluster.routing.allocation.node_concurrent_recoveriesускорить его.

Если вы все еще видите проблемы, возможно, что-то еще не так, поэтому поищите ошибки в журналах Elasticsearch. Если вы видите, что EsRejectedExecutionExceptionваши пулы потоков могут быть слишком маленькими .

Наконец, вы можете явно переназначить осколок узлу с помощью 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
        }
    }]
}'
Уилфред Хьюз
источник
3
Когда я сделал это, я получил: { "error" : "ElasticsearchIllegalArgumentException[[allocate] failed to find [logstash-2015.01.05][1] on the list of unassigned shards]", "status" : 400 } Хотя я вижу, что этот осколок является одним из нераспределенных в ES-Head
wjimenez5271
Кстати, другие осколки работали, которые были перечислены как нераспределенные, а затем остальные исправились.
wjimenez5271
это отличный совет.
Yehosef
1
Начиная с версии 5.0, команда «allocate» была изменена, чтобы предоставить больше опций - приведенный выше пример теперь будет «allocate_empty_primary», пропуская параметр «allow_primary».
JMB
4
вам нужно добавить, -H 'Content-Type: application/json'если вы получите ошибкуContent-Type header [application/x-www-form-urlencoded] is not supported
luckydonald
57

ОК, я решил это с помощью 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, если на вашей машине не менее 60G RAM, и в этом случае установите половину доступной памяти.

Ссылки

Spanky
источник
2
Чтобы решить эту проблему в версии 1.1.1, я должен использовать cluster.routing.allocation.enable = none?
user3175226
1
Отключение распределения там больше не задокументировано, по крайней мере, не 20 ноября.
3
Обратите внимание, что распределение маршрутизации является настройкой всего кластера, поэтому не имеет значения, на какой узел вы отправляете команду.
Уилфред Хьюз
Я добавил оба в мой файл es yml. index.routing.allocation.disable_allocation : false cluster.routing.allocation.enable: noneНо все еще остаются неназначенные осколки .. В чем может быть причина?
Bagui
1
В версии 6.8 я получаю сообщение об ошибке:{ "type": "illegal_argument_exception", "reason": "unknown setting [index.routing.allocation.disable_allocation] please check that any required plugins are installed, or check the breaking changes documentation for removed settings" } ],
Janac Meena
39

Этот маленький 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
В. Эндрю Лоэ III
источник
Работал как шарм. Спасибо!
Пауло Пирес
Я получил эту ошибку: <br> {"error": "JsonParseException [Неожиданный символ r (',' (код 44)): ожидалось допустимое значение (число, строка, массив, объект, 'true'," false "или 'null') \ n в [Источник: [B @ 3b1fadfb; строка: 6, столбец: 27]] "," status ": 500} <br> что я должен сделать, чтобы это исправить
biolinh
Благодаря тонну! Это сэкономило драгоценное время!
Сатиш
Сценарий выдает ошибку:{"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}{"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}
Янак Мина
17

Единственное, что сработало для меня, это изменение number_of_replicas (у меня было 2 реплики, поэтому я изменил его на 1, а затем вернул обратно на 2).

Первый:

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

Затем:

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

(Я уже ответил на это в этом вопросе )

ЭДИ
источник
9

Elasticsearch автоматически распределяет шарды, если в приведенной ниже конфигурации установлено значение all. Этот конфиг может быть установлен с использованием API остальных. Cluster.routing.allocation.enable: all

Если даже после применения приведенного ниже конфига не удастся автоматически назначить шарды, вам придется принудительно назначить шарды самостоятельно. Официальная ссылка 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
Нишал Кумар
источник
Этот скрипт не работал, то есть после того, как я его запустил, у меня все еще были НЕЗНАКОМЛЕННЫЕ осколки.
Крис Ф
@ChrisF В строке 1: вам нужно заменить узел 1, узел 2, узел 3 фактическими именами узлов. Вы можете получить их с помощью curl localhost: 9200 / _cat / node.
Сиди
6

Я застрял сегодня с той же проблемой распределения осколков. Сценарий, который предложил В. Эндрю Ло 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

Я не гуру Баш, но сценарий действительно работал для моего случая. Обратите внимание, что вам нужно указать соответствующие значения для переменных "ES_HOST" и "NODE".

Splanger
источник
к сожалению, ES5x нарушил совместимость : astic.co/guide/en/elasticsearch/reference/5.1/…
Fawix
2
Чтобы скрипт, приведенный выше, работал с ES5x, замените allocateна allocate_empty_primaryи замените \"allow_primary\": trueна\"accept_data_loss\": true
Fawix
Получение {"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}даже после применения предложения
Фавикс
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 минуту.

много способов
источник
4

Может быть, это кому-то помогает, но у меня была та же проблема, и это было из-за недостатка места для хранения, вызванного слишком большим размером журнала.

Надеюсь, это поможет кому-то! :)

Хуанхо Лайнес Рече
источник
4

В моем случае, когда я создаю новый индекс, тогда по умолчанию number_of_replicas устанавливается равным 1. И количество узлов в моем кластере было только одним, поэтому не было дополнительного узла для создания реплики, поэтому состояние работоспособности становилось желтым. Поэтому, когда я создал индекс со свойством settings и установил number_of_replicas равным 0. Тогда он работал нормально. Надеюсь это поможет.

PUT /customer
{
    "settings": {
        "number_of_replicas": 0
    }
}
Апурв Наг
источник
3

У меня была та же проблема, но основной причиной была разница в номерах версий (1.4.2 на двух узлах (с проблемами) и 1.4.4 на двух узлах (хорошо)). Первый и второй ответы (установка «index.routing.allocation.disable_allocation» на «ложь» и установка «cluster.routing.allocation.enable» на «все») не сработала.

Однако ответ @Wilfred Hughes (установка для «cluster.routing.allocation.enable» значения «all» с использованием переходного процесса) вызвала ошибку со следующим утверждением:

[НЕТ (версия целевого узла [1.4.2] старше, чем версия исходного узла [1.4.4])]

После обновления старых узлов до версии 1.4.4 эти узлы начали повторно соединяться с другими исправными узлами.

Йорг Рех
источник
3

У меня тоже была эта проблема, и я нашел простой способ ее решить.

  • Получить индекс неназначенных осколков

    $ curl -XGET http://172.16.4.140:9200/_cat/shards
    
  • Установите инструменты куратора и используйте его для удаления индекса

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

    НОТА: в моем случае индекс будет logstash дня 2016-04-21

  • Затем снова проверьте осколки, все неназначенные осколки исчезнут!
user3391471
источник
1
@Sim, большое спасибо за ваши изменения за мой ответ. Я очень плох в редактировании, буду уделять больше внимания этому.
user3391471
Для меня это было:curator_cli --host 127.0.0.1 delete_indices --filter_list '[{"filtertype":"pattern","kind":"prefix","value":"logstash-"}]'
Гауи
2

Я тоже столкнулся с этой ситуацией и наконец исправил ее.

Во-первых, я опишу мою ситуацию. У меня есть два узла в кластере ElasticSearch, они могут найти друг друга, но когда я создал индекс с настройками «number_of_replicas»: 2 , «number_of_shards»: 5, ES показывает желтый сигнал, а unassigned_shards - 5.

Проблема возникает потому, что значение number_of_replicas , когда я устанавливаю его значение с 1 , все в порядке.

Armstrongya
источник
4
Количество реплик всегда должно быть равно N-1 числу имеющихся у вас узлов. Таким образом, в вашем сценарии с 2 узлами, один из узлов содержит первичный осколок, в то время как у другого узла есть реплика, следовательно, ваше количество реплик должно быть установлено в 1. N = 2, N - 1 = 1.
slm
1

В моем случае к кластеру присоединился старый узел со старыми общими ресурсами, поэтому нам пришлось отключить старый узел и удалить индексы с неназначенными осколками.

alwe
источник
1

Я попробовал несколько из приведенных выше предложений, и, к сожалению, ни одно из них не сработало. У нас есть индекс «Журнал» в нашей нижней среде, где приложения пишут свои ошибки. Это кластер из одного узла. Для меня это решило проверить файл конфигурации YML для узла и убедиться, что он все еще имеет настройку по умолчанию «gateway.expected_nodes: 2». Это переопределяло любые другие настройки, которые у нас были. Всякий раз, когда мы создавали индекс для этого узла, он пытался распространить 3 из 5 шардов на фантомный 2-й узел. Поэтому они будут отображаться как неназначенные, и их никогда нельзя будет переместить в 1-й и единственный узел.

Решением было редактирование конфигурации, изменение параметра «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
Дэниэл Ноултон
источник
1

Для меня это было решено, запустив это из консоли разработчика: "POST / _cluster / reroute? Retry_failed"

.....

Я начал с просмотра списка индексов, чтобы увидеть, какие индексы были красными, а затем побежал

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

и увидел, что в состоянии ALLOCATION_FAILED застряли осколки, поэтому выполнение вышеописанной попытки повлекло за собой повторную попытку выделения.

ScottFoster1000
источник
Начиная с версии 5.6.3 команда должна быть такой: /_cat/shards/[INDEXNAME]?h=,shard,prirep,state,unassigned.reason
fasantos
0

Может помочь, но у меня была эта проблема при попытке запустить ES во встроенном режиме. Исправление состояло в том, чтобы удостовериться, что Узел имеет локальный (истинный) набор.

Jarc
источник
0

Другая возможная причина неназначенных шардов - это то, что в вашем кластере запущено более одной версии двоичного файла Elasticsearch.

репликация шарда из более поздней версии в предыдущие версии не будет работать

Это может быть основной причиной неназначенных осколков.

Упругая документация - процесс непрерывного обновления

Марк Тамский
источник
0

Я столкнулся с точно такой же проблемой. Этого можно избежать, временно установив распределение осколков в false перед перезапуском эластичного поиска, но это не исправит неназначенные осколки, если они уже там.

В моем случае это было вызвано отсутствием свободного дискового пространства на узле данных. Неназначенные сегменты остаются на узле данных после перезапуска, но не распознаются мастером.

Просто очистив один из узлов с диска, я начал процесс репликации. Это довольно медленный процесс, потому что все данные должны быть скопированы с одного узла данных на другой.

Брайан ван Ройен
источник
0

Я пытался удалить неназначенные осколки или вручную назначить их конкретному узлу данных. Это не сработало, потому что по-прежнему появлялись неназначенные осколки, и состояние здоровья становилось «красным» снова и снова. Затем я заметил, что один из узлов данных застрял в состоянии «перезагрузки». Я уменьшил количество узлов данных, убил его. Проблема больше не воспроизводима.

thepolina
источник
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] Это довольно легко сделать в Кубернетесе, если у вас достаточно запаса: просто масштабируйте набор состояний с помощью панели инструментов.

[2] Используя интерфейс Kibana «Dev Tools», мне не нужно было работать с SSH / exec-оболочками.

Брент Брэдберн
источник
0

Я только что увеличил

"index.number_of_replicas"

на 1 (подождите, пока узлы будут синхронизированы), а затем уменьшите его на 1, что эффективно удалит неназначенные осколки, и кластер снова станет зеленым без риска потери каких-либо данных.

Я верю, что есть лучшие способы, но для меня это проще.

Надеюсь это поможет.

Юсуф Демираг
источник
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.

bonzofenix
источник