On ne présente plus Elasticsearch, ce moteur de recherche open source distribué et surtout très accessible.
Elasticsearch est très simple à mettre en oeuvre et à utiliser, mais la mise en place d’un cluster peut tout de même poser problème, en particulier pour la gestion du « master node ».
Le master node est le noeud du cluster qui est chargé de l’allocation des « shards » parmi les différents noeuds. Il est donc important qu’à un instant T, il y ait un et un seul master node.
————— Les master nodes et le split-brain —————
Imaginons qu’une interruption réseau empêche temporairement les noeuds de votre cluster de communiquer entre eux.
Certains noeuds ne pouvant plus parler au « master node » vont déclencher spontanément l’élection d’un nouveau master.
Le résultat de cette élection sera ce qu’on appelle un split-brain : le cluster se trouve séparé en deux avec deux « master node » différents (et donc une désynchronisation des indexations).
Il s’agit bien sûr d’une situation à éviter absolument. Heureusement, il existe une solution : modifier le paramètre discovery.zen.minimum_master_nodes, défini de la manière suivante :
The discovery.zen.minimum_master_nodes allows to control the minimum number of master eligible nodes a node should « see » in order to operate within the cluster.
La solution au « split-brain » consiste donc à définir discovery.zen.minimum_master_nodes avec le nombre de noeuds du cluster / 2 + 1. S’il y a 8 noeuds dans votre cluster, vous renseignerez alors cette valeur à 5.
Ainsi, 5 noeuds votants sont nécessaires à l’élection d’un nouveau master. 2 machines ne peuvent donc pas obtenir suffisamment de votes pour être élues en simultané.
————— MasterNotDiscoveredException —————
Voilà, tout va pour le mieux dans le meilleur des mondes, votre cluster fonctionne et … vous souhaitez déconnecter une partie de vos noeuds.
Imaginons que nous ayons 8 noeuds sur notre cluster et que nous souhaitions passer sur 4 noeuds. Le paramètre discovery.zen.minimum_master_nodes de départ vaut 5.
Il faut alors modifier à nouveau le paramètre discovery.zen.minimum_master_nodes pour prendre en compte le nouveau nombre de noeuds nécessaires à l’élection (4 / 2 + 1, donc 3). Cette modification peut s’effectuer avec curl via l’API settings :
curl -XPUT localhost:9200/_cluster/settings -d '{ "persistent" : { "discovery.zen.minimum_master_nodes" : 3 } }'
Voilà. Si on stoppe maintenant nos noeuds, le cluster continuera de tourner, n’est-ce pas ?
Oui … seulement si on ne coupe pas le master.
Si jamais le master node fait partie des noeuds arrêtés, les requêtes que vous effectuerez retourneront MasterNotDiscoveredException :
curl -XGET "http://localhost:9200/_cluster/health?pretty=true" { "error" : "MasterNotDiscoveredException[waited for [30s]]", "status" : 503 }
————— Mais que se passe-t-il ? —————
Résumons :
- Notre cluster comprenait 8 noeuds
- Le « discovery.zen.minimum_master_nodes » vaut 5
- Nous souhaitons passer à 4 noeuds
- Nous avons modifié le « discovery.zen.minimum_master_nodes » à 3 (4 / 2 + 1)
- On stoppe des noeuds quelconques pour se ramener à 4 noeuds => pas de soucis
- Si le master est parmi les noeuds stoppés => MasterNotDiscoveredException
Tout se passe comme si le cluster n’appliquait plus le bon quota, puisqu’un nouveau master n’a pas été élu.
Voici mon analyse du problème :
- La modification dynamique du paramètre « discovery.zen.minimum_master_nodes » via l’API « /_cluster/settings » est prise en compte par le master. C’est lui qui est chargé de redispatcher ce paramètre entre les noeuds
- Si le master est stoppé, il ne peut plus servir de référence pour les paramètres dynamiques « /_cluster/settings », les noeuds utilisent donc le paramétrage par défaut (issu du elasticsearch.yml)
Bref, dans la mesure du possible, il est préférable de passer par le elasticsearch.yml pour modifier le « discovery.zen.minimum_master_nodes ».