ElasticSearch: frammenti non assegnati, come risolvere?


165

Ho un cluster ES con 4 nodi:

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

Ho dovuto riavviare search03, e quando è tornato, è rientrato nel cluster senza problemi, ma ha lasciato in giro 7 frammenti non assegnati.

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

Ora il mio cluster è in stato giallo. Qual è il modo migliore per risolvere questo problema?

  • Eliminare (annullare) i frammenti?
  • Spostare i frammenti su un altro nodo?
  • Allocare i frammenti al nodo?
  • Aggiorna "number_of_replicas" su 2?
  • Qualcos'altro interamente?

È interessante notare che, quando è stato aggiunto un nuovo indice, quel nodo ha iniziato a lavorarci su e si è comportato bene con il resto del cluster, lasciando semplicemente in giro i frammenti non assegnati.

Segui la domanda: sto facendo qualcosa di sbagliato per far sì che ciò accada in primo luogo? Non ho molta fiducia in un cluster che si comporta in questo modo al riavvio di un nodo.

NOTA: se si esegue un cluster a nodo singolo per qualche motivo, potrebbe essere necessario semplicemente eseguire le seguenti operazioni:

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

Risposte:


117

Per impostazione predefinita, Elasticsearch riassegna dinamicamente i frammenti ai nodi. Tuttavia, se hai disabilitato l'allocazione dei frammenti (forse hai fatto un riavvio a rotazione e hai dimenticato di riattivarlo), puoi riattivare l'allocazione dei frammenti.

# 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 riassegnerà i frammenti normalmente. Questo può essere lento, considera l'innalzamento indices.recovery.max_bytes_per_sece cluster.routing.allocation.node_concurrent_recoveriesper accelerarlo.

Se riscontri ancora problemi, probabilmente c'è qualcos'altro che non va, quindi cerca errori nei registri di Elasticsearch. Se vedi che i EsRejectedExecutionExceptiontuoi pool di thread potrebbero essere troppo piccoli .

Infine, puoi riassegnare esplicitamente un frammento a un nodo con l' API di reinstradamento .

# 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
Quando l'ho fatto ho ottenuto: { "error" : "ElasticsearchIllegalArgumentException[[allocate] failed to find [logstash-2015.01.05][1] on the list of unassigned shards]", "status" : 400 } anche se posso vedere che il frammento è uno di quelli non allocati in ES-Head
wjimenez5271,

Per inciso, altri frammenti funzionavano che erano elencati come non allocati, e poi i rimanenti si riparavano da soli.
wjimenez5271,

questo è un ottimo consiglio
Yehosef,

1
Dalla versione 5.0, il comando "allocate" è cambiato per fornire più opzioni - l'esempio sopra ora sarebbe "allocate_empty_primary", omettendo il parametro "allow_primary".
jmb,

4
è necessario aggiungere -H 'Content-Type: application/json'se si ottiene l'erroreContent-Type header [application/x-www-form-urlencoded] is not supported
luckydonald

56

OK, l'ho risolto con l'aiuto del supporto ES. Emetti il ​​seguente comando all'API su tutti i nodi (o sui nodi che ritieni siano la causa del problema):

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

dov'è <index>l'indice che ritieni sia il colpevole. Se non hai idea, esegui questo su tutti i nodi:

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

Ho anche aggiunto questa linea alla mia configurazione di yaml e da allora ogni riavvio del server / servizio è stato privo di problemi. I frammenti vengono riassegnati immediatamente.

FWIW, per rispondere a una domanda spesso richiesta, impostare MAX_HEAP_SIZE su 30G a meno che la macchina non abbia meno di 60G RAM, nel qual caso impostarla su metà della memoria disponibile.

Riferimenti


2
per risolverlo nella versione 1.1.1, dovrei usare cluster.routing.allocation.enable = none?
user3175226

1
La disabilitazione allocazione non è più documentata lì, almeno non a partire dal 20 novembre.

3
Si noti che l'allocazione del routing è un'impostazione a livello di cluster, quindi non importa a quale nodo si invia il comando.
Wilfred Hughes,

Ho aggiunto entrambi nel mio file es yml. index.routing.allocation.disable_allocation : false cluster.routing.allocation.enable: noneMa continuano a mostrare i frammenti non assegnati. Quale può essere la ragione?
Bagui,

1
Nella versione 6.8 ottengo un errore:{ "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

Questo piccolo script bash ridurrà la forza, potresti perdere dati.

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

Ha funzionato come un fascino. Grazie!
Paulo Pires,

Ho ricevuto questo errore: <br> {"errore": "JsonParseException [carattere imprevisto r (',' (codice 44)): previsto un valore valido (numero, stringa, matrice, oggetto, 'vero', 'falso' o 'null') \ n at [Fonte: [B @ 3b1fadfb; riga: 6, colonna: 27]] "," status ": 500} <br> cosa devo fare per risolverlo
biolinh

Grazie mille! Ha risparmiato tempo prezioso !!
Sathish,

La sceneggiatura genera l'errore:{"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

L'unica cosa che ha funzionato per me è stato cambiare il numero_di_replicas (avevo 2 repliche, quindi l'ho cambiato in 1 e poi cambiato di nuovo in 2).

Primo:

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

Poi:

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

(L'ho già risposto a questa domanda )


9

Elasticsearch alloca automaticamente i frammenti se la configurazione di seguito è impostata su tutto. Questa configurazione può essere impostata usando un'API di riposo e cluster.routing.allocation.enable: all

Se anche dopo l'applicazione della seguente configurazione, es non riesce ad assegnare automaticamente i frammenti, allora devi forzare l'assegnazione dei frammenti da solo. Link ufficiale ES per questo

Ho scritto una sceneggiatura per forzare l'assegnazione di tutti i frammenti non assegnati nel cluster.

array sotto contiene un elenco di nodi tra i quali si desidera bilanciare i frammenti non assegnati

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

Questo script non funzionava, cioè dopo averlo eseguito, avevo ancora frammenti NON ASSEGNATI.
Chris F,

@ChrisF Nella riga 1: è necessario sostituire node1, node2, node3 con i nomi dei nodi effettivi. Puoi ottenerli con un localhost arricciato: 9200 / _cat / nodes.
sabato

6

Oggi mi sono bloccato con lo stesso problema di allocazione dei frammenti. La sceneggiatura che W. Andrew Loe III ha proposto nella sua risposta non ha funzionato per me, quindi l'ho modificata un po 'e alla fine ha funzionato:

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

Ora, non sono una specie di guru di Bash, ma la sceneggiatura ha funzionato davvero per il mio caso. Tieni presente che dovrai specificare i valori appropriati per le variabili "ES_HOST" e "NODE".


sfortunatamente ES5x ha rotto la compatibilità: elastic.co/guide/en/elasticsearch/reference/5.1/…
Fawix,

2
Affinché lo script sopra funzioni con ES5x, sostituire allocatecon allocate_empty_primarye sostituire \"allow_primary\": truecon\"accept_data_loss\": true
Fawix

Ottenere {"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}anche dopo aver applicato il suggerimento di
Fawix

6

Nel mio caso, è stato raggiunto il limite superiore dello spazio sul disco rigido.

Guarda questo articolo: https://www.elastic.co/guide/en/elasticsearch/reference/current/disk-allocator.html

Fondamentalmente, ho corso:

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

In modo che alloca se viene utilizzato <90% di spazio su disco rigido e sposta un frammento su un'altra macchina nel cluster se viene utilizzato> 95% di spazio su disco rigido; e controlla ogni 1 minuto.


4

Forse aiuta qualcuno, ma ho avuto lo stesso problema ed era a causa della mancanza di spazio di archiviazione causato da un registro che diventava troppo grande.

Spero che aiuti qualcuno! :)


4

Nel mio caso, quando creo un nuovo indice, il numero_of_replicas predefinito è impostato su 1. E il numero di nodi nel mio cluster era solo uno, quindi non c'era un nodo aggiuntivo per creare la replica, quindi lo stato stava diventando giallo. Quindi, quando ho creato l'indice con la proprietà settings e impostato number_of_replicas su 0. Quindi ha funzionato bene. Spero che questo ti aiuti.

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

3

Ho avuto lo stesso problema ma la causa principale era una differenza nei numeri di versione (1.4.2 su due nodi (con problemi) e 1.4.4 su due nodi (ok)). La prima e la seconda risposta (impostando "index.routing.allocation.disable_allocation" su false e impostando "cluster.routing.allocation.enable" su "all") non funzionavano.

Tuttavia, la risposta di @Wilfred Hughes (impostando "cluster.routing.allocation.enable" su "all" usando transitorio) mi ha dato un errore con la seguente dichiarazione:

[NO (versione del nodo di destinazione [1.4.2] precedente alla versione del nodo di origine [1.4.4])]

Dopo aver aggiornato i vecchi nodi alla 1.4.4, questi nodi hanno iniziato a eseguire la ricnc con gli altri buoni nodi.


3

Avevo anche questo problema e ho trovato un modo semplice per risolverlo.

  • Ottieni l'indice dei frammenti non assegnati

    $ curl -XGET http://172.16.4.140:9200/_cat/shards
    
  • Installa gli strumenti del curatore e usalo per eliminare l'indice

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

    NOTA: nel mio caso, l'indice è logstash del giorno 21-04-2016

  • Quindi controlla nuovamente i frammenti, tutti i frammenti non assegnati scompaiono!

1
@sim, grazie per la tua modifica per la mia risposta. Sono molto povero in fase di modifica, presterò maggiore attenzione ad esso.
user3391471,

Per me era:curator_cli --host 127.0.0.1 delete_indices --filter_list '[{"filtertype":"pattern","kind":"prefix","value":"logstash-"}]'
Gaui,

2

Incontro anche questa situazione e alla fine l'ho risolta.

In primo luogo, descriverò la mia situazione. Ho due nodi nel cluster ElasticSearch, possono trovarsi a vicenda, ma quando ho creato un indice con le impostazioni "number_of_replicas": 2 , "number_of_shards": 5, ES mostra il segnale giallo e unassigned_shards è 5.

Il problema si verifica perché il valore di number_of_replicas , quando imposto il suo valore con 1 , va tutto bene.


4
Il numero di repliche dovrebbe sempre essere N-1 il numero di nodi che hai. Quindi nel tuo scenario con 2 nodi, 1 dei nodi contiene il frammento primario, mentre l'altro nodo ha la replica, quindi il tuo numero di repliche dovrebbe essere impostato su 1. N = 2, N - 1 = 1.
slm

1

Nel mio caso un vecchio nodo con vecchie condivisioni si stava unendo al cluster, quindi abbiamo dovuto chiudere il vecchio nodo ed eliminare gli indici con frammenti non assegnati.


1

Ho provato molti dei suggerimenti sopra riportati e sfortunatamente nessuno di loro ha funzionato. Abbiamo un indice "Log" nel nostro ambiente inferiore in cui le app scrivono i loro errori. È un cluster a nodo singolo. Ciò che ha risolto per me è stato controllare il file di configurazione YML per il nodo e vedere che aveva ancora l'impostazione predefinita "gateway.expected_nodes: 2". Questo stava scavalcando qualsiasi altra impostazione che avevamo. Ogni volta che creeremmo un indice su questo nodo, proverebbe a spargere 3 su 5 frammenti sul secondo nodo fantasma. Questi apparirebbero quindi come non assegnati e non potrebbero mai essere spostati nel primo e unico nodo.

La soluzione stava modificando la configurazione, cambiando l'impostazione "gateway.expected_nodes" su 1, quindi avrebbe smesso di cercare il fratello non trovato nel cluster e riavviare l'istanza del servizio Elastic. Inoltre, ho dovuto eliminare l'indice e crearne uno nuovo. Dopo aver creato l'indice, i frammenti sono comparsi sul primo e unico nodo e nessuno è stato assegnato.

# 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

Per me, questo è stato risolto eseguendolo dalla console di sviluppo: "POST / _cluster / reroute? Retry_failed"

.....

Ho iniziato guardando l'elenco degli indici per vedere quali indici erano rossi e poi ho funzionato

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

e ho visto che i frammenti erano bloccati nello stato ALLOCATION_FAILED, quindi l'esecuzione del nuovo tentativo sopra li ha costretti a riprovare l'allocazione.


A partire dalla versione 5.6.3 il comando dovrebbe essere get /_cat/shards/[INDEXNAME[?h=,shard,prirep,state,unassigned.reason
fasantos

0

Potrebbe essere d'aiuto, ma ho riscontrato questo problema durante il tentativo di eseguire ES in modalità integrata. La correzione consisteva nell'assicurarsi che il nodo avesse un set locale (vero).



0

Ho riscontrato esattamente lo stesso problema. Ciò può essere prevenuto impostando temporaneamente l'allocazione del frammento su false prima di riavviare elasticsearch, ma ciò non risolve i frammenti non assegnati se sono già presenti.

Nel mio caso è stato causato dalla mancanza di spazio libero su disco sul nodo dati. I frammenti non assegnati si trovavano ancora sul nodo dati dopo il riavvio ma non erano riconosciuti dal master.

Solo la pulizia di 1 dei nodi dal disco ha avviato il processo di replica per me. Questo è un processo piuttosto lento perché tutti i dati devono essere copiati da un nodo di dati all'altro.


0

Ho provato a eliminare i frammenti non assegnati o assegnarli manualmente a un determinato nodo di dati. Non ha funzionato perché continuavano ad apparire frammenti non assegnati e lo stato di salute era "rosso" più e più volte. Poi ho notato che uno dei nodi di dati era bloccato nello stato di "riavvio". Riduco il numero di nodi di dati, l'ho ucciso. Il problema non è più riproducibile.


0

Avevo due indici con frammenti non assegnati che non sembravano auto-guarigione. Alla fine l'ho risolto aggiungendo temporaneamente un ulteriore nodo dati [1] . Dopo che gli indici sono diventati sani e tutto si è stabilizzato al verde, ho rimosso il nodo aggiuntivo e il sistema è stato in grado di riequilibrare (di nuovo) e stabilizzarsi su uno stato sano.

È una buona idea evitare di uccidere più nodi di dati contemporaneamente (ed è così che sono entrato in questo stato). Probabilmente, non ero riuscito a conservare copie / repliche per almeno uno dei frammenti. Fortunatamente, Kubernetes ha mantenuto lo spazio su disco e lo ha riutilizzato quando ho riavviato il nodo dati.


... è passato del tempo ...

Bene, questa volta l'aggiunta di un nodo non sembrava funzionare (dopo aver atteso diversi minuti perché accadesse qualcosa), quindi ho iniziato a frugare nell'API REST.

GET /_cluster/allocation/explain

Questo ha mostrato il mio nuovo nodo con "decision": "YES".

A proposito, tutti i nodi preesistenti erano "decision": "NO"dovuti a "the node is above the low watermark cluster setting". Quindi questo è stato probabilmente un caso diverso da quello che avevo affrontato in precedenza.

Poi ho realizzato il seguente semplice POST [2] senza corpo , che ha messo le cose in marcia ...

POST /_cluster/reroute

Altre note:


[1] Abbastanza facile da fare in Kubernetes se hai abbastanza spazio per la testa: basta ridimensionare il set con stato tramite la dashboard.

[2] Usando l'interfaccia "Dev Tools" di Kibana, non ho dovuto preoccuparmi delle shell SSH / exec.


0

Ho appena aumentato il

"index.number_of_replicas"

di 1 (attendere fino alla sincronizzazione dei nodi), quindi diminuito di 1 in seguito, il che rimuove efficacemente i frammenti non assegnati e il cluster diventa di nuovo verde senza il rischio di perdere dati.

Credo che ci siano modi migliori ma questo è più facile per me.

Spero che questo ti aiuti.


0

Quando si ha a che fare con frammenti danneggiati è possibile impostare il fattore di replica su 0 e quindi ripristinarlo al valore originale. Questo dovrebbe chiarire la maggior parte, se non tutti, i frammenti danneggiati e riposizionare le nuove repliche nel cluster.

Impostazione degli indici con repliche non assegnate per utilizzare un fattore di replica di 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}}'

Riportandoli su 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}}'

Nota: non eseguirlo se si hanno diversi fattori di replica per indici diversi. Questo codifica il fattore di replica per tutti gli indici su 1.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.