Technique

Les bonnes pratiques d'Elasticsearch en matière de sniffing : on vous dit tout

Elasticsearch optimise les expériences d'un très grand nombre d'outils et d'applications actuels, depuis les tableaux de bord analytiques opérationnels jusqu'aux cartes affichant les restaurants les plus proches avec les chemins que vous pouvez emprunter. Quelle que soit la mise en œuvre, la connexion entre l'application et le cluster est assurée par un client Elasticsearch.

Il est extrêmement important pour l'expérience utilisateur d'optimiser la connexion entre le client et le cluster Elasticsearch. La configuration type d'un client Elasticsearch est l'URL du nœud auquel vous devez vous connecter. Mais vous pouvez aller plus loin. Pour optimiser cette connexion, l'une des solutions consiste à utiliser le sniffing.

Nous allons à présent voir comment le sniffing marche, quand l'utiliser et quand l'éviter. On vous dit tout !

Qu'est-ce que le sniffing ?

Elasticsearch est un système distribué, ce qui signifie que ses index sont répartis dans différents nœuds connectés les uns aux autres, qui forment tous ensemble un cluster. L'un des grands avantages d'avoir un système distribué (en plus de la tolérance aux pannes), c'est que les données sont partitionnées sur plusieurs nœuds, ce qui permet d'effectuer des recherches bien plus efficaces que si vous aviez un seul grand nœud.

Une configuration type d'un client se présente sous la forme d'une URL unique pointant vers un nœud du cluster Elasticsearch. Même s'il s'agit de la configuration la plus simple, elle présente un inconvénient : toutes les requêtes que vous effectuerez seront envoyées à ce nœud de coordination spécifique. Résultat : ce nœud unique se retrouve sous pression, ce qui risque de nuire à la performance générale.

Une solution pour éviter ce problème consiste à fournir une liste statique de nœuds au client, pour que vos requêtes soient distribuées de manière égale sur les différents nœuds.

Une autre solution consiste à activer une fonctionnalité : le sniffing.

Si vous utilisez une liste statique de nœuds, il n'est pas garanti que ces nœuds seront tout le temps opérationnels. Par exemple, que se passe-t-il si vous interrompez un nœud pour le mettre à niveau ? Ou si vous en ajoutez de nouveaux ?

Si vous activez le sniffing, le client commencera par appeler le point de terminaison _nodes/_all/http. Vous obtiendrez en réponse une liste de tous les nœuds présents dans le cluster, en plus de leurs adresses IP. Le client mettra alors à jour son pool de connexions pour utiliser tous les nouveaux nœuds et veillera à maintenir le cluster en synchronisation avec son pool de connexions. Notez que même si les clients téléchargent la liste complète des nœuds, les nœuds de type maître uniquement ne seront pas utilisés pour les appels d'API génériques.

Le sniffing permet de résoudre ce problème de découverte. Dans ce cas, pourquoi cette fonctionnalité n'est-elle pas activée par défaut ? C'est une excellente question !

Quand faut-il utiliser le sniffing ?

Le sniffing peut être à double tranchant. Si vous essayez d'appeler le point de terminaison _nodes/_all/http, vous obtiendrez une liste des nœuds et de leurs points de terminaison respectifs. Mais il faut d'abord prendre quelques points en considération.

  • Que se passe-t-il si votre cluster Elasticsearch réside dans son propre réseau ?
  • Et si votre cluster Elasticsearch se trouve derrière un équilibreur de charges ?

Dans ces deux cas, la réponse est simple : vous aurez des adresses IP complètement inutiles car le réseau est différent.

Vous pouvez faire le test par vous-même en utilisant Docker. Exécutez une instance Elasticsearch (une seule suffit) et appelez _nodes/_all/http à partir de votre machine locale. Vous constaterez que l'adresse IP de votre nœud n'est pas la même que celle que vous venez d'utiliser.

Exécutez la commande suivante pour amorcer une instance Elasticsearch :

docker run \ 
-p 9200:9200 \
-e "discovery.type=single-node" \
docker.elastic.co/elasticsearch/elasticsearch:7.8.0

Vous pouvez désormais lire l'adresse IP du nœud avec la commande suivante. (Dans l'extrait suivant, nous utilisons jq pour faciliter la lecture de la réponse :)

curl -s localhost:9200/_nodes/_all/http | jq .nodes[].http.publish_address

Pour finir, vous pouvez copier l'adresse IP indiquée dans le terminal et essayer d'y envoyer une requête :

curl {ip_address}:9200 | jq .

Comme vous pouvez le voir, la réponse obtenue n'est pas correcte.

Concrètement, cela veut dire que si vous activez le sniffing dans un client alors que le cluster se trouve sur un autre réseau, le client ajoutera tous les nouveaux nœuds à son pool de connexions. Pourquoi ? Parce qu'il n'a aucun moyen de comprendre que ces adresses IP sont erronées. Par conséquent, toutes les requêtes effectuées sur ces nœuds échoueront.

Étant donné que le nœud initial ayant la bonne adresse IP ne se trouve plus dans l'état du cluster, il sera écarté. Vous obtiendrez rapidement un message d'erreur vous indiquant qu'il n'y a pas de connexions valides.

La bonne nouvelle, c'est que nous pouvons y remédier.

Pour résoudre ce problème, vous pouvez configurer Elasticsearch afin qu'il reste lié à son hôte tout en en promouvant un autre. Et c'est exactement ce que permet de faire l'option de configuration http.publish_host. À présent, essayez d'exécuter la commande Docker ci-dessus avec cette nouvelle configuration :

docker run \ 
-p 9200:9200 \
-e "discovery.type=single-node" \
-e "http.publish_host=localhost" \
docker.elastic.co/elasticsearch/elasticsearch:7.8.0

Si vous exécutez à nouveau la commande suivante :

curl -s localhost:9200/_nodes/_all/http | jq .nodes[].http.publish_address

Dans le terminal, vous verrez apparaître ce qui suit :

"localhost/{ip_address}:9200"

Si vous configurez l'hôte "publish", les clients officiels (à partir de la version 7) seront suffisamment intelligents pour comprendre qu'ils doivent utiliser l'adresse de l'hôte, et non pas l'adresse IP.

Ce qu'il faut retenir de cette procédure, c'est que vous devez connaître votre infrastructure avant d'activer le sniffing. Il existe de nombreuses solutions pour résoudre le problème des adresses IP, mais il n'en existe pas une qui soit universelle, car tout dépend de la configuration de votre système.

Dans la configuration type d'un développement, le cluster Elasticsearch se trouve dans le même réseau que votre client. Mais il n'est pas possible de répliquer cette configuration dans la réalité car cela conduirait à des problèmes de sécurité et parce que votre infrastructure est probablement plus complexe. Vous pouvez configurer l'équilibreur de charges pour qu'il prenne ces adresses IP en charge. Ou si vous préférez, vous pouvez faire comme Elastic dans Elastic Cloud : laissez le proxy se charger des nœuds en échec et faites en sorte que le client envoie systématiquement les requêtes au proxy, qui les redirigera ensuite vers le nœud approprié.

Quand faut-il éviter le sniffing ?

Il existe de nombreuses situations dans lesquelles le sniffing pourrait provoquer des problèmes, par exemple :

  • L'utilisateur Elasticsearch avec lequel votre client cherche à s'authentifier ne dispose pas des droits appropriés (rôle monitoring_user) pour accéder à l'API des nœuds.
  • Vous utilisez des fournisseurs cloud.

En général, les fournisseurs cloud placent Elasticsearch derrière un proxy, ce qui rend l'opération de sniffing inutile, étant donné que les adresses et les noms d'hôte renvoyés n'auront aucune signification dans votre réseau. En général, ce sont ces fournisseurs cloud qui gèrent le sniffing et le pooling pour vous. Vous n'avez donc pas à vous en préoccuper.

Si vous utilisez Elastic Cloud, les clients officiels court-circuiteront la plupart des opérations en interne, comme la gestion du pool de connexions, pour éviter de perdre du temps sur des opérations déjà effectuées.

D'autres problèmes peuvent se produire lorsqu'on utilise Docker ou Kubernetes, comme nous l'avons vu auparavant. Si vous ne configurez pas l'option d'hôte "publish", le résultat du sniffing sera inutilisable.

En règle générale : Si Elasticsearch ne se trouve pas dans le même réseau que votre client, ou s'il y a un équilibreur de charges, il est préférable de désactiver le sniffing, sauf s'il existe une configuration dans votre infrastructure qui permette de l'utiliser avec précision.

Comment faire pour utiliser le sniffing ?

Les clients proposent différentes stratégies de sniffing. Voyons ce qu'il en est :

Le sniffing au démarrage

Comme son nom l'indique, lorsque vous activez cette option, le client tente d'exécuter une requête de sniffing une seule fois seulement lors de l'initialisation du client ou à la première utilisation.

Le sniffing lors de l'échec de la connexion

Lorsque vous choisissez cette option, le client tente d'exécuter une requête de sniffing à chaque fois qu'un nœud est défaillant, c'est-à-dire lorsqu'une connexion est interrompue ou qu'un nœud ne fonctionne plus.

Intervalle de sniffing

En plus du sniffing au démarrage et en cas d'échec de la connexion, le fait de procéder au sniffing de façon périodique peut être intéressant dans les cas où des clusters sont régulièrement scalés de manière horizontale lors des pics d'affluence. Une application peut avoir une vue saine sur un sous-ensemble de ses nœuds. Mais si elle ne procède pas périodiquement au sniffing, elle ne trouvera jamais les nœuds qui ont été ajoutés lors du scaling horizontal.

Configurations personnalisées

Dans certains cas, il peut être intéressant d'avoir un contrôle plus granulaire sur la procédure de sniffing. Les clients sont suffisamment flexibles pour vous permettre de configurer un point de terminaison de sniffing personnalisé. Si vous préférez, vous pouvez également remplacer la logique de sniffing en intégralité et appliquer celle de votre choix.

Conclusions

Lorsque vous activez le sniffing, votre application devient plus résiliente et est parée pour s'adapter aux changements. Néanmoins, avant de vous servir de cette fonctionnalité, vous devez avoir une bonne connaissance de votre infrastructure pour décider quelle est la meilleure solution à adopter. Il peut être préférable parfois de ne pas utiliser le sniffing.

Si vous n'avez pas envie de vous creuser la tête pour déterminer comment configurer le sniffing et le pool de connexions, essayez Elastic Cloud gratuitement pendant 14 jours avec Elasticsearch Service.