ElasticSearch: fragmentos no asignados, ¿cómo solucionarlo?


165

Tengo un clúster ES con 4 nodos:

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

Tuve que reiniciar search03, y cuando regresó, se unió al clúster sin problemas, pero dejó 7 fragmentos sin asignar por ahí.

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

Ahora mi grupo está en estado amarillo. ¿Cuál es la mejor manera de resolver este problema?

  • ¿Eliminar (cancelar) los fragmentos?
  • ¿Mover los fragmentos a otro nodo?
  • ¿Asignar los fragmentos al nodo?
  • ¿Actualizar 'number_of_replicas' a 2?
  • Algo más por completo?

Curiosamente, cuando se agregó un nuevo índice, ese nodo comenzó a trabajar en él y jugó bien con el resto del clúster, simplemente dejó los fragmentos no asignados por ahí.

Siga la pregunta: ¿estoy haciendo algo mal para que esto suceda en primer lugar? No tengo mucha confianza en un clúster que se comporta de esta manera cuando se reinicia un nodo.

NOTA: Si está ejecutando un clúster de nodo único por alguna razón, es posible que simplemente necesite hacer lo siguiente:

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

Respuestas:


117

Por defecto, Elasticsearch reasignará fragmentos a los nodos dinámicamente. Sin embargo, si ha deshabilitado la asignación de fragmentos (tal vez hizo un reinicio continuo y olvidó volver a habilitarlo), puede volver a habilitar la asignación de fragmentos.

# 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 reasignará fragmentos de forma normal. Esto puede ser lento, considere subir indices.recovery.max_bytes_per_secy cluster.routing.allocation.node_concurrent_recoveriesacelerarlo.

Si todavía ve problemas, probablemente hay algo más que está mal, así que busque errores en sus registros de Elasticsearch. Si ve que EsRejectedExecutionExceptionsus grupos de hilos pueden ser demasiado pequeños .

Finalmente, puede reasignar explícitamente un fragmento a un nodo con la API de redireccionamiento .

# 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
Cuando hice eso, obtuve: { "error" : "ElasticsearchIllegalArgumentException[[allocate] failed to find [logstash-2015.01.05][1] on the list of unassigned shards]", "status" : 400 } Aunque puedo ver que el fragmento es uno de los no asignados en ES-Head
wjimenez5271

Por cierto, otros fragmentos hicieron trabajos que se enumeraron como no asignados, y luego los restantes se arreglaron.
wjimenez5271

Este es un gran consejo.
Yehosef

1
Desde la versión 5.0, el comando "asignar" ha cambiado para proporcionar más opciones : el ejemplo anterior ahora sería "allocate_empty_primary", omitiendo el parámetro "allow_primary".
jmb

44
necesita agregar -H 'Content-Type: application/json'si obtiene el errorContent-Type header [application/x-www-form-urlencoded] is not supported
luckydonald

56

OK, he resuelto esto con ayuda del soporte de ES. Emita el siguiente comando para la API en todos los nodos (o los nodos que cree que son la causa del problema):

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

¿Dónde <index>está el índice que crees que es el culpable? Si no tiene idea, simplemente ejecute esto en todos los nodos:

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

También agregué esta línea a mi configuración de yaml y desde entonces, cualquier reinicio del servidor / servicio no ha tenido problemas. Los fragmentos se reasignaron de inmediato.

FWIW, para responder una pregunta frecuente, configure MAX_HEAP_SIZE en 30G a menos que su máquina tenga menos de 60G RAM, en cuyo caso configúrelo en la mitad de la memoria disponible.

Referencias


2
para resolver esto en la versión 1.1.1, ¿debería usar cluster.routing.allocation.enable = none?
user3175226

1
Desactivar la asignación ya no está documentado que hay, al menos no como del NoV 20.

3
Tenga en cuenta que la asignación de enrutamiento es una configuración de todo el clúster, por lo que no importa a qué nodo envíe el comando.
Wilfred Hughes

Agregué ambos en mi archivo es yml. index.routing.allocation.disable_allocation : false cluster.routing.allocation.enable: nonePero todavía se muestran los fragmentos no asignados ... ¿Cuál puede ser la razón?
bagui

1
En la versión 6.8 me sale un error:{ "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

Este pequeño script bash reasignará la fuerza bruta, puede perder datos.

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

Trabajado como un encanto. ¡Gracias!
Paulo Pires

Recibí este error: <br> {"error": "JsonParseException [Carácter inesperado r (',' (código 44)): esperaba un valor válido (número, cadena, matriz, objeto, 'verdadero', 'falso' o 'nulo') \ n en [Fuente: [B @ 3b1fadfb; línea: 6, columna: 27]] "," estado ": 500} <br> qué debo hacer para solucionarlo
biolinh

¡Gracias una tonelada! Se ahorró un tiempo precioso!
Sathish

El guión arroja el error:{"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

Lo único que funcionó para mí fue cambiar el número de réplicas (tenía 2 réplicas, así que lo cambié a 1 y luego volví a cambiar a 2).

Primero:

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

Luego:

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

(Ya lo respondí en esta pregunta )


9

Elasticsearch asigna automáticamente fragmentos si la siguiente configuración está establecida en todos. Esta configuración se puede configurar usando una API de descanso también cluster.routing.allocation.enable: all

Si incluso después de la aplicación de la siguiente configuración, es no puede asignar los fragmentos automáticamente, entonces debe forzar la asignación de los fragmentos usted mismo. Enlace oficial de ES para esto

He escrito un script para forzar la asignación de todos los fragmentos no asignados a través del clúster.

la matriz a continuación contiene una lista de nodos entre los que desea equilibrar los fragmentos no asignados

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

Este script no funcionó, es decir, después de ejecutarlo, todavía tenía fragmentos SIN ASIGNAR.
Chris F

@ChrisF En la línea 1: debe reemplazar node1, node2, node3 con los nombres reales de los nodos. Puede obtenerlos con un curl localhost: 9200 / _cat / nodo.
sidi

6

Hoy me he quedado con el mismo problema de asignación de fragmentos. El guión que W. Andrew Loe III propuso en su respuesta no funcionó para mí, así que lo modifiqué un poco y finalmente funcionó:

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

Ahora, no soy una especie de gurú de Bash, pero el guión realmente funcionó para mi caso. Tenga en cuenta que deberá especificar los valores apropiados para las variables "ES_HOST" y "NODE".


por desgracia, el ES5x rompió la compatibilidad: elastic.co/guide/en/elasticsearch/reference/5.1/...
Fawix

2
Para que el script anterior funcione con ES5x, reemplace allocatecon allocate_empty_primaryy reemplace \"allow_primary\": truecon\"accept_data_loss\": true
Fawix

Conseguir {"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}incluso después de aplicar la sugerencia de Fawix
Janáč Meena

6

En mi caso, se alcanzó el límite superior del espacio del disco duro.

Mira este artículo: https://www.elastic.co/guide/en/elasticsearch/reference/current/disk-allocator.html

Básicamente, corrí:

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

De modo que se asignará si se usa <90% de espacio en el disco duro y moverá un fragmento a otra máquina en el clúster si se usa> 95% de espacio en el disco duro; y verifica cada 1 minuto.


4

Tal vez ayude a alguien, pero tuve el mismo problema y se debió a la falta de espacio de almacenamiento debido a que un registro se hizo demasiado grande.

Espero que ayude a alguien! :)


4

En mi caso, cuando creo un nuevo índice , el número predeterminado de réplicas se establece en 1. Y el número de nodos en mi clúster era solo uno, por lo que no había ningún nodo adicional para crear la réplica, por lo que el estado se estaba volviendo amarillo. Entonces, cuando creé el índice con la propiedad de configuración y configuré el número de réplicas en 0. Entonces funcionó bien. Espero que esto ayude.

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

3

Tuve el mismo problema, pero la causa raíz fue una diferencia en los números de versión (1.4.2 en dos nodos (con problemas) y 1.4.4 en dos nodos (ok)). La primera y la segunda respuesta (establecer "index.routing.allocation.disable_allocation" en falso y establecer "cluster.routing.allocation.enable" en "all") no funcionó.

Sin embargo, la respuesta de @Wilfred Hughes (estableciendo "cluster.routing.allocation.enable" a "all" usando transitoria) me dio un error con la siguiente declaración:

[NO (la versión del nodo de destino [1.4.2] es anterior a la versión del nodo de origen [1.4.4])]

Después de actualizar los nodos anteriores a 1.4.4, estos nodos comenzaron a resincronizarse con los otros nodos buenos.


3

También tenía este problema y encontré una manera fácil de resolverlo.

  • Obtenga el índice de fragmentos no asignados

    $ curl -XGET http://172.16.4.140:9200/_cat/shards
    
  • Instala las herramientas de curador y úsalas para eliminar el índice

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

    NOTA: en mi caso, el índice es logstash del día 2016-04-21

  • Luego revise los fragmentos nuevamente, ¡todos los fragmentos no asignados desaparecen!

1
@ sim, muchas gracias por tu edición por mi respuesta. Soy muy pobre en edición, le prestaré más atención.
user3391471

Para mí, fue:curator_cli --host 127.0.0.1 delete_indices --filter_list '[{"filtertype":"pattern","kind":"prefix","value":"logstash-"}]'
Gaui

2

También me encuentro con esta situación y finalmente la arreglé.

En primer lugar, describiré mi situación. Tengo dos nodos en el clúster ElasticSearch, se pueden encontrar, pero cuando creé un índice con la configuración "número_de_plicaciones": 2 , "número_de_harinas": 5, ES muestra una señal amarilla y un_ashards sin asignar es 5.

El problema ocurre porque el valor de number_of_replicas , cuando configuro su valor con 1 , todo está bien.


44
El número de réplicas siempre debe ser N-1 el número de nodos que tiene. Entonces, en su escenario con 2 nodos, 1 de los nodos contiene el fragmento primario, mientras que el otro nodo tiene la réplica, por lo tanto, su número de réplicas debe establecerse en 1. N = 2, N - 1 = 1.
slm

1

En mi caso, un nodo antiguo con recursos compartidos antiguos se unía al clúster, por lo que tuvimos que cerrar el nodo antiguo y eliminar los índices con fragmentos no asignados.


1

Intenté varias de las sugerencias anteriores y desafortunadamente ninguna funcionó. Tenemos un índice de "Registro" en nuestro entorno inferior donde las aplicaciones escriben sus errores. Es un clúster de nodo único. Lo que me resolvió fue comprobar el archivo de configuración YML para el nodo y ver que todavía tenía la configuración predeterminada "gateway.expected_nodes: 2". Esto anulaba cualquier otra configuración que teníamos. Siempre que creáramos un índice en este nodo, intentaría extender 3 de 5 fragmentos al segundo nodo fantasma. Por lo tanto, aparecerían como no asignados y nunca podrían moverse al primer y único nodo.

La solución fue editar la configuración, cambiar la configuración "gateway.expected_nodes" a 1, por lo que dejaría de buscar su hermano nunca encontrado en el clúster y reiniciaría la instancia del servicio Elastic. Además, tuve que eliminar el índice y crear uno nuevo. Después de crear el índice, todos los fragmentos aparecieron en el primer y único nodo, y ninguno estaba sin asignar.

# 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

Para mí, esto se resolvió ejecutando esto desde la consola de desarrollo: "POST / _cluster / reroute? Retry_failed"

.....

Comencé mirando la lista de índices para ver qué índices eran rojos y luego ejecuté

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

y vi que tenía fragmentos atascados en el estado ALLOCATION_FAILED, por lo que ejecutar el reintento anterior hizo que volvieran a intentar la asignación.


A partir de la versión 5.6.3, el comando debería ser /_cat/shards/[INDEXNAMEfont>?h=,shard,prirep,state,unassigned.reason
fasantos

0

Podría ayudar, pero tuve este problema al intentar ejecutar ES en modo incrustado. La solución era asegurarse de que el Nodo tuviera un conjunto local (verdadero).



0

Me encontré exactamente con el mismo problema. Esto se puede evitar configurando temporalmente la asignación de fragmentos en falso antes de reiniciar elasticsearch, pero esto no repara los fragmentos no asignados si ya están allí.

En mi caso, fue causado por la falta de espacio libre en disco en el nodo de datos. Los fragmentos no asignados todavía estaban en el nodo de datos después del reinicio pero no fueron reconocidos por el maestro.

Simplemente limpiando 1 de los nodos del disco, el proceso de replicación comenzó para mí. Este es un proceso bastante lento porque todos los datos deben copiarse de un nodo de datos al otro.


0

Traté de eliminar fragmentos no asignados o asignarlos manualmente a un nodo de datos en particular. No funcionó porque los fragmentos no asignados seguían apareciendo y el estado de salud era "rojo" una y otra vez. Entonces noté que uno de los nodos de datos se atascó en el estado "reiniciar". Reduje el número de nodos de datos, lo maté. El problema ya no es reproducible.


0

Tenía dos índices con fragmentos no asignados que no parecían autocurativos. Finalmente resolví esto agregando temporalmente un nodo de datos adicional [1] . Después de que los índices se volvieron saludables y todo se estabilizó en verde, eliminé el nodo adicional y el sistema pudo reequilibrarse (nuevamente) y establecer un estado saludable.

Es una buena idea evitar matar múltiples nodos de datos a la vez (que es como llegué a este estado). Probablemente, no pude preservar ninguna copia / réplica de al menos uno de los fragmentos. Afortunadamente, Kubernetes mantuvo el almacenamiento en disco y lo reutilizó cuando relancé el nodo de datos.


... Ha pasado algún tiempo ...

Bueno, esta vez solo agregar un nodo no parecía funcionar (después de esperar varios minutos a que sucediera algo), así que comencé a hurgar en la API REST.

GET /_cluster/allocation/explain

Esto mostró mi nuevo nodo con "decision": "YES".

Por cierto, todos los nodos preexistentes se "decision": "NO"debieron a "the node is above the low watermark cluster setting". Así que este fue probablemente un caso diferente al que había abordado anteriormente.

Luego hice el siguiente POST simple [2] sin cuerpo , que puso las cosas en marcha ...

POST /_cluster/reroute

Otras notas:


[1] Es bastante fácil de hacer en Kubernetes si tienes suficiente espacio para la cabeza: simplemente escala el conjunto con estado a través del tablero.

[2] Utilizando la interfaz "Dev Tools" de Kibana, no tuve que molestarme con shells SSH / exec.


0

Acabo de aumentar el

"index.number_of_replicas"

en 1 (espere hasta que los nodos se sincronicen) y luego lo disminuyó en 1 después, lo que elimina efectivamente los fragmentos no asignados y el clúster vuelve a ser verde sin el riesgo de perder ningún dato.

Creo que hay mejores formas, pero esto es más fácil para mí.

Espero que esto ayude.


0

Cuando se trata de fragmentos dañados, puede establecer el factor de replicación en 0 y luego volver a establecerlo en el valor original. Esto debería aclarar la mayoría, si no todos, los fragmentos dañados y reubicar las nuevas réplicas en el clúster.

Establecer índices con réplicas no asignadas para usar un factor de replicación de 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}}'

Volviéndolos a 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: No ejecute esto si tiene diferentes factores de replicación para diferentes índices. Esto codificaría el factor de replicación para todos los índices a 1.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.