ElasticSearch: Unassigned Shards, jak to naprawić?


165

Mam klaster ES z 4 węzłami:

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

Musiałem ponownie uruchomić search03, a kiedy wrócił, bez problemu połączył się z klastrem, ale zostawił 7 nieprzypisanych fragmentów.

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

Teraz moja gromada jest w stanie żółtym. Jaki jest najlepszy sposób rozwiązania tego problemu?

  • Usunąć (anulować) fragmenty?
  • Przenieść fragmenty do innego węzła?
  • Przydzielić fragmenty do węzła?
  • Zaktualizować „number_of_replicas” do 2?
  • Coś zupełnie innego?

Co ciekawe, kiedy dodano nowy indeks, ten węzeł zaczął nad nim pracować i grał dobrze z resztą klastra, po prostu zostawiał nieprzypisane fragmenty.

Przejdź do pytania: czy w ogóle robię coś złego, aby tak się stało? Nie mam zaufania do klastra, który zachowuje się w ten sposób po ponownym uruchomieniu węzła.

UWAGA: Jeśli z jakiegoś powodu używasz klastra z jednym węzłem, możesz po prostu wykonać następujące czynności:

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

Odpowiedzi:


117

Domyślnie Elasticsearch dynamicznie ponownie przypisuje fragmenty do węzłów. Jeśli jednak wyłączyłeś alokację fragmentu (być może wykonałeś kroczący restart i zapomniałeś go ponownie włączyć), możesz ponownie włączyć alokację fragmentu.

# 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 ponownie przypisze fragmenty w normalny sposób. Może to być powolne, rozważ przebicie indices.recovery.max_bytes_per_seci cluster.routing.allocation.node_concurrent_recoveriesprzyspieszenie.

Jeśli nadal widzisz problemy, prawdopodobnie jest coś innego, więc poszukaj błędów w dziennikach Elasticsearch. Jeśli widzisz, EsRejectedExecutionExceptionże pule wątków mogą być zbyt małe .

Na koniec możesz jawnie ponownie przypisać fragment do węzła za pomocą interfejsu API przekierowania .

# 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
Kiedy to zrobiłem, otrzymałem: { "error" : "ElasticsearchIllegalArgumentException[[allocate] failed to find [logstash-2015.01.05][1] on the list of unassigned shards]", "status" : 400 } Mimo że widzę, że fragment jest jednym z nieprzydzielonych w ES-Head
wjimenez5271

Nawiasem mówiąc, inne fragmenty działały, które zostały wymienione jako nieprzydzielone, a następnie pozostałe naprawiły się.
wjimenez5271

to świetna rada.
Yehosef

1
Od wersji 5.0 polecenie „przydziel” zostało zmienione, aby zapewnić więcej opcji - powyższy przykład miałby teraz nazwę „alert_empty_primary”, z pominięciem parametru „allow_primary”.
jmb

4
musisz dodać, -H 'Content-Type: application/json'jeśli Content-Type header [application/x-www-form-urlencoded] is not supported
pojawi się

56

OK, rozwiązałem ten problem z pomocą pomocy technicznej ES. Wydaj następujące polecenie do interfejsu API na wszystkich węzłach (lub węzłach, które Twoim zdaniem są przyczyną problemu):

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

gdzie <index>jest indeks, który Twoim zdaniem jest winowajcą. Jeśli nie masz pojęcia, po prostu uruchom to na wszystkich węzłach:

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

Dodałem również tę linię do mojej konfiguracji yaml i od tego czasu wszelkie ponowne uruchomienia serwera / usługi były bezproblemowe. Odłamki natychmiast ponownie przydzielone.

FWIW, aby odpowiedzieć na często poszukiwane pytanie, ustaw MAX_HEAP_SIZE na 30G, chyba że twoja maszyna ma mniej niż 60G RAM, w takim przypadku ustaw ją na połowę dostępnej pamięci.

Bibliografia


2
aby rozwiązać ten problem w wersji 1.1.1, czy powinienem użyć cluster.routing.allocation.enable = none?
user3175226

1
Wyłączenie alokacji nie jest już tam udokumentowane, przynajmniej nie od 20 listopada

3
Pamiętaj, że alokacja routingu jest ustawieniem obejmującym cały klaster, więc nie ma znaczenia, do którego węzła wyślesz polecenie.
Wilfred Hughes

Dodałem oba w moim pliku es yml. index.routing.allocation.disable_allocation : false cluster.routing.allocation.enable: noneAle nadal pojawiają się nieprzypisane odłamki… Jaki może być tego powód?
bagui

1
W wersji 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" } ],
wyskakuje

39

Ten mały skrypt basha brutalnie wymusi ponowne przypisanie, możesz stracić dane.

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

Działał jak urok. Dzięki!
Paulo Pires

Otrzymałem ten błąd: <br> {"błąd": "JsonParseException [Nieoczekiwany znak r (',' (kod 44)): oczekiwano prawidłowej wartości (liczba, ciąg, tablica, obiekt, 'prawda', 'fałsz' lub 'null') \ n at [Source: [B @ 3b1fadfb; line: 6, column: 27]] "," status ": 500} <br> co mam zrobić, żeby to naprawić
biolinh

Wielkie dzięki! Oszczędza to cenny czas !!
Sathish

Skrypt zgłasza błąd:{"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}
Janac Meena

17

Jedyną rzeczą, która działała dla mnie, była zmiana number_of_replicas (miałem 2 repliki, więc zmieniłem to na 1, a następnie zmieniłem z powrotem na 2).

Pierwszy:

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

Następnie:

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

(Już odpowiedziałem na to pytanie )


9

Elasticsearch automatycznie przydziela shardy, jeśli poniższa konfiguracja jest ustawiona na all. Tę konfigurację można ustawić również za pomocą interfejsu API REST, a także cluster.routing.allocation.enable: all

Jeśli nawet po zastosowaniu poniższej konfiguracji, es nie przypisze fragmentów automatycznie, musisz samodzielnie wymusić przypisanie fragmentów. Oficjalny link ES do tego

Napisałem skrypt, który wymusza przypisanie wszystkich nieprzypisanych fragmentów w klastrze.

Poniższa tablica zawiera listę węzłów, wśród których chcesz zrównoważyć nieprzypisane fragmenty

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

Ten skrypt nie zadziałał, to znaczy po uruchomieniu go nadal miałem UNASSIGNED shards.
Chris F

@ChrisF W linii 1: musisz zastąpić node1, node2, node3 rzeczywistymi nazwami węzłów. Możesz je uzyskać za pomocą curl localhost: 9200 / _cat / nodes.
sidi

6

Utknąłem dzisiaj z tą samą kwestią alokacji odłamków. Scenariusz, który zaproponował w swojej odpowiedzi W.Andrew Loe III, nie zadziałał, więc trochę go zmodyfikowałem i wreszcie zadziałał:

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

Nie jestem w pewnym sensie guru Bash, ale scenariusz naprawdę zadziałał w moim przypadku. Pamiętaj, że musisz określić odpowiednie wartości dla zmiennych „ES_HOST” i „NODE”.


niestety ES5x zepsuł kompatybilność: flexible.co/guide/en/elasticsearch/reference/5.1/…
Fawix

2
Aby powyższego skryptu do pracy z ES5x zastąpić allocatez allocate_empty_primaryi wymienić \"allow_primary\": truez\"accept_data_loss\": true
Fawix

Uzyskanie {"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}nawet po zastosowaniu sugestii
Fawixa

6

W moim przypadku górna granica miejsca na dysku została osiągnięta.

Spójrz na ten artykuł: https://www.elastic.co/guide/en/elasticsearch/reference/current/disk-allocator.html

Zasadniczo pobiegłem:

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

Aby przydzielił, jeśli jest używane <90% miejsca na dysku twardym, i przeniesie fragment na inny komputer w klastrze, jeśli> 95% zajętego miejsca na dysku twardym; i sprawdza co 1 minutę.


4

Może to komuś pomoże, ale miałem ten sam problem i wynikał z braku miejsca na przechowywanie spowodowanego zbyt dużym kłodą.

Mam nadzieję, że to komuś pomoże! :)


4

W moim przypadku, kiedy tworzę nowy indeks, domyślna liczba_replik jest ustawiana na 1. A liczba węzłów w moim klastrze była tylko jeden, więc nie było dodatkowego węzła do utworzenia repliki, więc stan zdrowia zmienił się na żółty. Więc kiedy utworzyłem indeks z właściwością settings i ustawiłem number_of_replicas na 0. Wtedy zadziałało dobrze. Mam nadzieję że to pomoże.

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

3

Miałem ten sam problem, ale główną przyczyną była różnica w numerach wersji (1.4.2 na dwóch węzłach (z problemami) i 1.4.4 na dwóch węzłach (ok)). Pierwsza i druga odpowiedź (ustawienie „index.routing.allocation.disable_allocation” na false i ustawienie „cluster.routing.allocation.enable” na „all”) nie zadziałały.

Jednak odpowiedź @Wilfred Hughes (ustawienie „cluster.routing.allocation.enable” na „all” przy użyciu transient) dała mi błąd z następującym stwierdzeniem:

[NIE (wersja węzła docelowego [1.4.2] jest starsza niż wersja węzła źródłowego [1.4.4])]

Po zaktualizowaniu starych węzłów do wersji 1.4.4, te węzły zaczęły ponownie współdziałać z innymi dobrymi węzłami.


3

Miałem również ten problem i znalazłem łatwy sposób na jego rozwiązanie.

  • Uzyskaj indeks nieprzypisanych fragmentów

    $ curl -XGET http://172.16.4.140:9200/_cat/shards
    
  • Zainstaluj narzędzia kuratora i użyj ich do usunięcia indeksu

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

    UWAGA: W moim przypadku indeksem jest logstash z dnia 21.04.2016

  • Następnie sprawdź ponownie odłamki, wszystkie nieprzypisane odłamki znikną!

1
@sim, bardzo dziękuję za twoją edycję za moją odpowiedź. Jestem bardzo słaby w edycji, zwrócę na to większą uwagę.
user3391471

Dla mnie był to:curator_cli --host 127.0.0.1 delete_indices --filter_list '[{"filtertype":"pattern","kind":"prefix","value":"logstash-"}]'
Gaui,

2

Ja też spotykam się z tą sytuacją i ostatecznie ją naprawiłem.

Najpierw opiszę swoją sytuację. Mam dwa węzły w klastrze ElasticSearch, mogą się one znaleźć, ale kiedy utworzyłem indeks z ustawieniami „number_of_replicas”: 2 , „number_of_shards”: 5, ES pokazuje żółty sygnał, a unassigned_shards to 5.

Problem pojawia się, ponieważ wartość number_of_replicas , kiedy ustawię jej wartość na 1 , wszystko jest w porządku.


4
Liczba replik powinna zawsze wynosić N-1 liczby posiadanych węzłów. Tak więc w scenariuszu z 2 węzłami 1 z węzłów zawiera fragment podstawowy, podczas gdy w drugim węźle znajduje się replika, stąd liczba replik powinna być ustawiona na 1. N = 2, N - 1 = 1.
slm

1

W moim przypadku do klastra dołączał stary węzeł ze starymi udziałami, więc musieliśmy zamknąć stary węzeł i usunąć indeksy z nieprzypisanymi fragmentami.


1

Wypróbowałem kilka z powyższych sugestii i niestety żadna z nich nie zadziałała. Mamy indeks „Log” w naszym niższym środowisku, w którym aplikacje zapisują swoje błędy. Jest to klaster z jednym węzłem. Rozwiązaniem tego problemu było sprawdzenie pliku konfiguracyjnego YML dla węzła i stwierdzenie, że nadal ma on domyślne ustawienie „gateway.expected_nodes: 2”. To przesłaniało wszelkie inne ustawienia, które mieliśmy. Za każdym razem, gdy utworzylibyśmy indeks w tym węźle, spróbowalibyśmy rozłożyć 3 z 5 fragmentów do drugiego węzła fantomowego. W związku z tym wyglądałyby one jako nieprzypisane i nigdy nie można ich było przenieść do pierwszego i jedynego węzła.

Rozwiązaniem była edycja konfiguracji, zmiana ustawienia „gateway.expected_nodes” na 1, tak aby przestał szukać swojego nieodnalezionego brata w klastrze i zrestartował instancję usługi Elastic. Musiałem też usunąć indeks i utworzyć nowy. Po utworzeniu indeksu wszystkie fragmenty pojawiły się w pierwszym i jedynym węźle i żaden nie był nieprzypisany.

# 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

W moim przypadku problem został rozwiązany, uruchamiając to z konsoli programisty: „POST / _cluster / reroute? Retry_failed”

.....

Zacząłem od spojrzenia na listę indeksów, aby zobaczyć, które indeksy były czerwone, a następnie uruchomiłem

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

i zobaczył, że fragmenty utknęły w stanie ALLOCATION_FAILED, więc wykonanie powyższej ponownej próby spowodowało ponowne wypróbowanie alokacji.


Od wersji 5.6.3 komand powinien być get /_cat/shards/[INDEXNAME]?h=,shard,prirep,state,unassigned.reason
fasantos

0

Może pomóc, ale miałem ten problem podczas próby uruchomienia ES w trybie osadzonym. Poprawka polegała na upewnieniu się, że Węzeł miał ustawiony lokalny (true).



0

Napotkałem dokładnie ten sam problem. Można temu zapobiec, tymczasowo ustawiając alokację fragmentu na wartość false przed ponownym uruchomieniem elastycznego wyszukiwania, ale nie naprawia to nieprzypisanych fragmentów, jeśli już tam są.

W moim przypadku było to spowodowane brakiem wolnego miejsca na dysku w węźle danych. Nieprzypisane fragmenty nadal znajdowały się w węźle danych po ponownym uruchomieniu, ale nie zostały rozpoznane przez master.

Już samo wyczyszczenie 1 węzłów z dysku spowodowało rozpoczęcie procesu replikacji. Jest to raczej powolny proces, ponieważ wszystkie dane muszą zostać skopiowane z jednego węzła danych do drugiego.


0

Próbowałem usunąć nieprzypisane fragmenty lub ręcznie przypisać je do konkretnego węzła danych. To nie zadziałało, ponieważ ciągle pojawiały się nieprzypisane odłamki, a stan zdrowia był „czerwony” w kółko. Potem zauważyłem, że jeden z węzłów danych utknął w stanie „restartu”. Zmniejszyłem liczbę węzłów danych, zabiłem to. Problem nie jest już odtwarzalny.


0

Miałem dwa indeksy z nieprzypisanymi odłamkami, które nie wyglądały na samoleczące. Ostatecznie rozwiązałem ten problem, dodając tymczasowo dodatkowy węzeł danych [1] . Po tym, jak wskaźniki stały się zdrowe i wszystko ustabilizowało się na zielono, usunąłem dodatkowy węzeł i system był w stanie ponownie zrównoważyć (ponownie) i ustabilizować się w zdrowym stanie.

Dobrym pomysłem jest unikanie zabijania wielu węzłów danych na raz (w ten sposób doszedłem do tego stanu). Prawdopodobnie nie udało mi się zachować żadnych kopii / replik co najmniej jednego z odłamków. Na szczęście Kubernetes zachował miejsce na dysku i użył go ponownie, gdy ponownie uruchomiłem węzeł danych.


...Minęło trochę czasu...

Cóż, tym razem samo dodanie węzła nie działało (po kilku minutach oczekiwania, aż coś się wydarzy), więc zacząłem grzebać w REST API.

GET /_cluster/allocation/explain

To pokazało mój nowy węzeł z "decision": "YES".

Nawiasem mówiąc, wszystkie wcześniej istniejące węzły miały "decision": "NO"skutek "the node is above the low watermark cluster setting". Więc to był prawdopodobnie inny przypadek niż ten, o którym mówiłem wcześniej.

Następnie wykonałem następujący prosty POST [2] bez ciała , co wprawiło wszystko w ruch ...

POST /_cluster/reroute

Inne notatki:


[1] Całkiem łatwe do zrobienia w Kubernetes, jeśli masz wystarczający zapas: po prostu wyskaluj zestaw stanowy za pomocą pulpitu nawigacyjnego.

[2] Używając interfejsu Kibana "Dev Tools", nie musiałem zawracać sobie głowy powłokami SSH / exec.


0

Po prostu najpierw zwiększyłem

„index.number_of_replicas”

o 1 (poczekaj, aż węzły zostaną zsynchronizowane), a następnie zmniejsz go o 1, co skutecznie usuwa nieprzypisane fragmenty i klaster jest ponownie zielony bez ryzyka utraty jakichkolwiek danych.

Wierzę, że są lepsze sposoby, ale to jest dla mnie łatwiejsze.

Mam nadzieję że to pomoże.


0

W przypadku uszkodzonych fragmentów można ustawić współczynnik replikacji na 0, a następnie przywrócić pierwotną wartość. Powinno to usunąć większość, jeśli nie wszystkie, uszkodzone fragmenty i przenieść nowe repliki w klastrze.

Ustawianie indeksów z nieprzypisanymi replikami, aby używały współczynnika replikacji równego 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}}'

Ustawiam je z powrotem na 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}}'

Uwaga: nie uruchamiaj tego, jeśli masz różne współczynniki replikacji dla różnych indeksów. Spowodowałoby to utrwalenie współczynnika replikacji dla wszystkich indeksów na 1.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.