web-dev-qa-db-fra.com

ElasticSearch: Eclats non affectés, comment les réparer?

J'ai un cluster ES avec 4 nœuds:

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

J'ai dû redémarrer search03, et quand il est revenu, il a rejoint le cluster sans problème, mais il a laissé 7 fragments non affectés pondant. 

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

Maintenant, mon cluster est à l'état jaune. Quel est le meilleur moyen de résoudre ce problème?

  • Supprimer (annuler) les fragments?
  • Déplacer les fragments vers un autre noeud?
  • Allouer les fragments au nœud?
  • Mettre à jour 'number_of_replicas' à 2?
  • Quelque chose d'autre entièrement?

Fait intéressant, quand un nouvel index a été ajouté, ce nœud a commencé à travailler dessus et a joué à Nice avec le reste du cluster.

Suite à la question: est-ce que je fais quelque chose de mal pour que cela se produise en premier lieu? Je n'ai pas beaucoup de confiance dans un cluster qui se comporte de la sorte lorsqu'un nœud est redémarré. 

REMARQUE: Si vous utilisez un seul cluster pour une raison quelconque, vous devrez peut-être simplement procéder comme suit:

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

OK, j'ai résolu ce problème avec l'aide du support ES. Émettez la commande suivante à l'API sur tous les nœuds (ou les nœuds que vous croyez être à l'origine du problème):

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

<index> est l'indice que vous croyez être le coupable. Si vous n'en avez aucune idée, exécutez ceci sur tous les nœuds:

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

J'ai également ajouté cette ligne à ma configuration yaml et depuis lors, tout redémarrage du serveur/service s'est déroulé sans problème. Les fragments sont réaffectés immédiatement.

FWIW, pour répondre à une question souvent recherchée, définissez MAX_HEAP_SIZE sur 30G sauf si votre ordinateur dispose de moins de 60G de RAM, auquel cas définissez-le sur la moitié de la mémoire disponible.

Références

49
Spanky

Par défaut, Elasticsearch réaffectera les fragments aux nœuds de manière dynamique. Toutefois, si vous avez désactivé l'allocation de fragments (vous avez peut-être déjà effectué un redémarrage rolling et avez oublié de le réactiver), vous pouvez réactiver l'allocation de fragments.

# 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 réaffectera ensuite les fragments comme d'habitude. Cela peut être lent, envisagez de lever indices.recovery.max_bytes_per_sec et cluster.routing.allocation.node_concurrent_recoveries pour l'accélérer.

Si vous rencontrez toujours des problèmes, il y a probablement autre chose qui ne va pas. Consultez donc les journaux Elasticsearch pour rechercher les erreurs éventuelles. Si vous voyez EsRejectedExecutionException, vos pools de threads sont peut-être trop petits .

Enfin, vous pouvez explicitement réaffecter un fragment à un nœud avec l'API reroute .

# 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
        }
    }]
}'
105
Wilfred Hughes

Ce petit script bash va brusquement réaffecter la force, vous risquez de perdre des données.

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
37

La seule chose qui a fonctionné pour moi a été de changer le nombre de répliques (j'avais 2 répliques, alors je l'ai changé en 1, puis de nouveau en 2).

Premier:

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

Ensuite:

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

(Je l'ai déjà répondu dans cette question )

13
Edi

Elasticsearch alloue automatiquement les fragments si la configuration ci-dessous est définie sur all. Cette configuration peut également être définie à l’aide de l’application restcluster.routing.allocation.enable: all

Si même après l’application de la configuration ci-dessous, es ne parvient pas à attribuer les fragments automatiquement, vous devez forcer l’affectation des partitions vous-même. ES lien officiel pour cela

J'ai écrit un script pour forcer l'affectation de tous les fragments non attribués d'un cluster à l'autre.

le tableau ci-dessous contient la liste des nœuds parmi lesquels vous souhaitez équilibrer les fragments non attribués.

#!/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
9
Nischal Kumar

Aujourd'hui, je suis aux prises avec le même problème d'allocation de fragments. Le script que W. Andrew Loe III a proposé dans sa réponse n'a pas fonctionné pour moi, alors je l'ai un peu modifié et cela a finalement fonctionné:

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

Maintenant, je ne suis pas un peu un gourou Bash, mais le script a vraiment fonctionné pour mon cas. Notez que vous devrez spécifier les valeurs appropriées pour les variables "ES_Host" et "NODE".

6
Splanger

Dans mon cas, la limite supérieure de l'espace disque a été atteinte.

Regardez cet article: https://www.elastic.co/guide/fr/elasticsearch/reference/current/disk-allocator.html

En gros, j'ai couru:

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

Pour qu'il alloue si <90% d'espace disque utilisé, et déplace un fragment vers une autre machine du cluster si> 95% d'espace disque utilisé; et il vérifie toutes les minutes.

5
manyways

Cela peut peut-être aider quelqu'un, mais j'ai eu le même problème et c'était dû à un manque d'espace de stockage causé par un journal devenant trop volumineux.

J'espère que ça aide quelqu'un! :)

4

Dans mon cas, lorsque je crée un nouveauindex, la valeur par défautnumber_of_replicasest définie sur 1. Et le nombre de nœuds dans mon cluster était un, il n'y avait donc pas noeud supplémentaire pour créer le réplica, donc la santé devenait jaune. Ainsi, lorsque j’ai créé l’index avecsettingsproperty et défini le number_of_replicas sur 0, il a bien fonctionné. J'espère que cela t'aides.

PUT /customer
{
    "settings": {
        "number_of_replicas": 0
    }
}
3
Apoorv Nag

J'ai eu le même problème, mais la cause principale était une différence dans les numéros de version (1.4.2 sur deux nœuds (avec des problèmes) et 1.4.4 sur deux nœuds (ok)). Les première et deuxième réponses (définir "index.routing.allocation.disable_allocation" sur false et définir "cluster.routing.allocation.enable" sur "tout") ne fonctionnaient pas. 

Cependant, la réponse de @Wilfred Hughes (en définissant "cluster.routing.allocation.enable" sur "all" en utilisant transitoire) m'a donné une erreur avec la déclaration suivante:

[NON (la version du noeud cible [1.4.2] est antérieure à la version du noeud source [1.4.4])]

Après la mise à jour des anciens noeuds vers la version 1.4.4, ces noeuds ont commencé à se connecter avec les autres bons noeuds.

3
Jörg Rech

J'avais aussi ce problème et j'ai trouvé un moyen facile de le résoudre.

  • Obtenir l'index des fragments non attribués

    $ curl -XGET http://172.16.4.140:9200/_cat/shards
    
  • Installez les outils de curateur et utilisez-les pour supprimer l'index

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

    NOTE: Dans mon cas, l'index est le journal journal du jour 2016-04-21

  • Puis vérifiez à nouveau les fragments, tous les fragments non attribués disparaissent!
3
user3391471

J'ai également rencontré cette situation et finalement résolu.

Tout d'abord, je vais décrire ma situation. J'ai deux nœuds dans le cluster ElasticSearch, ils peuvent se trouver, mais lorsque j'ai créé un index avec les paramètres "number_of_replicas": 2 , "number_of_shards": 5, ES affiche le signal jaune et non attribué (s) est 5.

Le problème se produit parce que la valeur de number_of_replicas , lorsque je règle sa valeur avec 1 , tout va bien.

2
Armstrongya

Dans mon cas, un ancien nœud avec d'anciens partages rejoignait le cluster. Nous avons donc dû fermer l'ancien nœud et supprimer les index avec des fragments non attribués. 

1
alwe

J'ai essayé plusieurs des suggestions ci-dessus et, malheureusement, aucune d'entre elles n'a fonctionné. Nous avons un index "Log" dans notre environnement inférieur où les applications écrivent leurs erreurs. C'est un cluster à un seul noeud. Ce qui a résolu le problème pour moi était de vérifier le fichier de configuration YML pour le noeud et de voir qu'il avait toujours le paramètre par défaut "gateway.expected_nodes: 2". Cela remplaçait tous les autres paramètres que nous avions. Chaque fois que nous créerions un index sur ce noeud, il essaierait de répartir 3 fragments sur 5 vers le 2ème noeud fantôme. Ceux-ci apparaîtront donc comme non attribués et ils ne pourraient jamais être déplacés vers le 1er et unique noeud.

La solution consistait à modifier la configuration et à remplacer le paramètre "gateway.expected_nodes" par 1. Il cessait donc de rechercher son frère introuvable dans le cluster et de redémarrer l'instance de service Elastic. En outre, je devais supprimer l'index et en créer un nouveau. Après la création de l'index, les fragments sont tous apparus sur le premier et unique nœud et aucun n'a été attribué.

# 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
Daniel Knowlton

Pour moi, cela a été résolu en exécutant ceci à partir de la console de développement: "POST/_cluster/reroute? Retry_failed"

.....

J'ai commencé par regarder la liste des index pour voir quels index étaient en rouge et ensuite couru 

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

et a constaté que des fragments étaient bloqués dans l'état ALLOCATION_FAILED. L'exécution de la tentative ci-dessus les a forcés à réessayer l'allocation.

1
ScottFoster1000

J'avais deux indices avec des fragments non affectés qui ne semblaient pas se guérir d'eux-mêmes. J'ai finalement résolu ce problème en ajoutant temporairement un extra data-node [1]. Une fois que les indices sont devenus sains et que tout s'est stabilisé au vert, j'ai enlevé le nœud supplémentaire et le système a été capable de rééquilibrer (à nouveau) et de retrouver un état sain.

C’est une bonne idée d’éviter de tuer plusieurs nœuds de données en même temps (c’est ainsi que je suis entré dans cet état). J'ai probablement omis de conserver des copies/répliques d'au moins un des fragments. Heureusement, Kubernetes a conservé le stockage sur disque et l'a réutilisé lorsque j'ai relancé le nœud de données.


... Un peu de temps a passé ...

Eh bien, cette fois, ajouter un nœud ne semblait pas fonctionner (après plusieurs minutes d'attente), j'ai donc commencé à fouiller dans l'API REST.

GET /_cluster/allocation/explain

Cela a montré mon nouveau noeud avec "decision": "YES".

Au fait, tous les nœuds préexistants avaient "decision": "NO" en raison de "the node is above the low watermark cluster setting". Il s’agissait donc probablement d’une affaire différente de celle que j’avais abordée précédemment.

Puis j'ai fait le post simple suivant[2] sans corps, ce qui a accéléré ...

POST /_cluster/reroute

[1] C'est assez facile à faire dans Kubernetes si vous avez assez de marge: augmentez simplement le nombre des états avec le tableau de bord.

[2] En utilisant l'interface "Dev Tools" de Kibana, je n'ai pas eu à me soucier des shells SSH/exec.

0
nobar

Lorsque vous traitez avec des fragments corrompus, vous pouvez définir le facteur de réplication sur 0, puis le ramener à la valeur d'origine. Ceci devrait effacer la plupart, sinon tous vos fragments corrompus, et déplacer les nouveaux réplicas dans le cluster.

Définition d'index avec des réplicas non affectés pour utiliser un facteur de réplication 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}}'

Les ramenant à 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}}'

Remarque: N'exécutez pas cette opération si vous avez différents facteurs de réplication pour différents index. Cela coderait le facteur de réplication pour tous les index sur 1.

0
bonzofenix

J'ai essayé de supprimer des fragments non attribués ou de les attribuer manuellement à un nœud de données particulier. Cela n'a pas fonctionné car les fragments non affectés continuaient d'apparaître et que l'état d'intégrité était «rouge» à plusieurs reprises… .. Puis j'ai remarqué qu'un des nœuds de données était bloqué dans l'état de «redémarrage». Je réduis le nombre de nœuds de données, tué. Le problème n'est plus reproductible.

0
thepolina

Peut aider, mais j'ai eu ce problème en essayant d'exécuter ES en mode intégré. Le correctif consistait à s'assurer que le nœud avait un ensemble local (vrai).

0
JARC

J'ai juste d'abord augmenté le

"index.numéro_de_replicas"

par 1 (attendez que les noeuds soient synchronisés) puis l'a diminué de 1 par la suite, ce qui supprime efficacement les fragments non attribués et le cluster redevient vert sans risque de perte de données.

Je crois qu'il y a de meilleurs moyens mais c'est plus facile pour moi.

J'espère que cela t'aides.

0
Yusuf Demirag

Une autre raison possible des fragments non attribués est que votre cluster exécute plusieurs versions du binaire Elasticsearch.

réplication de la partition de la version la plus récente à la précédente les versions ne fonctionneront pas

Cela peut être une cause fondamentale des fragments non attribués. 

Documentation Elastic - Processus de mise à niveau progressive

0
Marc Tamsky

J'ai rencontré exactement le même problème. Cela peut être évité en définissant temporairement l'allocation de fragments sur false avant de redémarrer elasticsearch, mais cela ne résout pas les fragments non attribués s'ils sont déjà présents.

Dans mon cas, cela était dû à un manque d'espace disque disponible sur le nœud de données. Les fragments non attribués étaient toujours sur le nœud de données après le redémarrage, mais ils n'étaient pas reconnus par le maître. 

Le nettoyage de l'un des nœuds du disque a démarré le processus de réplication pour moi. C'est un processus plutôt lent car toutes les données doivent être copiées d'un noeud à l'autre. 

0
Brian van Rooijen