Installer une stack ELK (ElasticSearch / Logstash / Kibana) et Elastic Agent avec Docker

Temps de lecture estimé: 11 minutes

Ça fait maintenant quelques années que j’en parle, mais je ne m’étais pas encore penché dessus. Je commence à avoir plusieurs systèmes qui tournent à la maison avec plusieurs VM et plusieurs containers Docker (même si ça a un peu évolué depuis, tu trouveras un rappel sur mon infra et l’organisation de mes containers Docker). Ça fait pas mal d’accès à gérer et surtout pas mal de fichiers de log.

Aujourd’hui, nous allons voir comment installer une stack ELK avec Docker pour centraliser les logs de mes machines et pouvoir les parcourir et les analyser plus facilement.

Cet article est en majorité basé sur la documentation d’installation officielle d’ElasticSearch.

ElasticSearch

Set vm.max_map_count to at least 262144

Ok, c’est un homelab, mais ça reste un environnement de production que j’héberge chez moi, donc je suis quelques-unes des préconisations indiquées sur la doc pour utiliser l’image Docker d’ElasticSearch en production. Je ne les suivrai pas toutes, donc je te laisse choisir les tiennes. D’autres recommandations seront aussi faites dans les autres étapes.

Donc, sur mon hôte Ubuntu, je vérifie le setting vm.max_map_count avec :

J’ai la valeur par défaut:

Donc, j’applique directement les changements au système:

Et j’en profite pour éditer le fichier de configuration sysctl pour garder ces paramètres même après un redémarrage.

Pour y rajouter donc, le paramètre de manière persistante:

Préparer les volumes / dossiers sur mon hote

Je vais gérer les données d’ElasticSearch et la config en dehors du container Docker pour les persister (ça m’évitera de perdre toutes les données à chaque redémarrage du container Docker).

Donc, dans le dossier qui m’arrange, je crée 2 nouveaux dossiers : un pour la config, un pour les données.

Ensuite, comme recommandé

Lancer le container Docker ElasticSearch

Dans mon cas, je ne pars pas d’une installation fraîche de Docker. Mes networks sont déjà définis et je l’ai détaillé dans une série d’articles sur ma migration d’un serveur monolithique à des services containerisés.

Toujours dans mon cas, je me sers d’un script deploy.sh dans lequel je mets ma commande docker run.

(Une fois que j’aurai récupéré la configuration de base, j’y ajouterai le volume du fichier de configuration comme indiqué ici : -v /home/docker-infra/docker-elasticsearch/config/custom_elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml)

Dans les logs du container, tu devrais voir apparaître le mot de passe généré pour l’utilisateur elastic et les tokens d’enrollment pour Kibana ou un autre nœud Elastic.

Les tokens ne sont valides que 30 minutes. Une fois ce délai passé, tu devras ensuite en régénérer un.

Réinitialiser le mot de passe

Si jamais tu ne te souviens plus du mot de passe, tu pourras toujours le réinitialiser avec:

Créer un nouveau Token d’enrollment pour Kibana

De même, si tu as perdu le token ou qu’il a dépassé ses 30 minutes de validité, tu peux en régénérer un avec :

Créer un nouveau Token d’enrollment pour un nouveau nœud Elastic

Et pour finir, pareil avec le token d’enrollment pour un nouveau nœud Elastic. Si tu l’as perdu ou qu’il a dépassé ses 30 minutes de validité, tu peux en régénérer un avec:

Vérifier l’installation et le bon fonctionnement

À ce stade, le container devrait être up and running ! Pour le vérifier, on va télécharger le certificat d’Elastic et faire un appel simple à l’API.

Pour récupérer le certificat :

Puis, on passe l’appel à l’API avec le mot de passe généré et récupéré plus haut.

Si tout va bien, tu devrais avoir une réponse de ce genre:

Récupérer les fichiers de configuration

Comme je l’ai dit plus haut, je souhaite récupérer les fichiers de configuration en local sur mon hôte pour ensuite pouvoir les binder et les redéployer.

Pour les récupérer, c’est simple:

je peux ensuite mettre à jour mon script de déploiement avec -v /home/docker-infra/docker-elasticsearch/config/:/usr/share/elasticsearch/config/ \

Kibana

Maintenant qu’Elastic est lancé, on s’occupe maintenant de l’interface Web Kibana. Ça va être sensiblement la même chose qu’Elastic.

Préparer les volumes / dossiers sur mon hote

Je vais gérer les données de Kibana et la config en dehors du container Docker pour les persister (ça m’évitera de perdre toutes les données à chaque redémarrage du container Docker).

Donc, dans le dossier qui m’arrange, je crée 2 nouveaux dossiers : un pour la config, un pour les données.

Lancer le container Docker Kibana

De la même manière que pour chaque container Docker, j’ai un script deploy.sh

Au premier lancement, tout se passe bien et on est invité à configurer Kibana:

Je lance donc mon navigateur avec l’ip de mon serveur hôte sur le port d’écoute 5601 de Kibana : http://192.168.10.110:5601/ et je configure Kibana avec le token d’enrollment généré avec la commande plus haut

Code de vérification

Et voilà, je n’ai plus qu’à me loguer une première fois avec l’utilisateur elastic:

Récupérer les fichiers de configuration

Et de la même manière que pour Elastic, je récupère les fichier de configuration en local sur mon hôte pour ensuite pouvoir le binder et le redéployer.

Pour les récupérer c’est simple:

Je peux ensuite mettre à jour mon script de déploiement avec -v /home/docker-infra/docker-kibana/config/:/usr/share/kibana/config/ \

J’ai fait une modification dans le fichier kibana.yml. Par défaut, il s’est généré avec l’IP du container Docker du nœud ElasticSearch. Le problème, c’est que Docker peut changer l’IP du container, et ensuite, forcement, Kibana perd sa connexion (ce qui m’est arrivé). J’ai donc changé le paramètre elasticsearch.hosts:

Configurer le ssl (httpS)

Pour activer le SSL, il faut ajouter la configuration dans le fichier kibana.yml et spécifier ses clés et certificats:

De mon côté, j’utilise un reverse proxy apache. Je ne garde que server.publicBaseUrl dans mon fichier kibana.yml et je définis mon fichier de configuration Apache pour mon container reverse proxy Apache.

Intégrer les logs avec Elastic Agent

J’ai un moteur Elastic prêt à intégrer des logs, j’ai l’interface Kibana, il ne me reste maintenant plus qu’à récupérer les logs et les faire manger à Elastic.

Avant de commencer, je comptais utiliser Logstash ou Filebeat comme je l’avais déjà fait dans des expériences professionnelles précédentes. En creusant la documentation et en regardant l’interface Kibana, je m’aperçois qu’il existe Fleet et Elastic Agent.

Je tâtonne sur cette partie et je ne vais sûrement pas le mettre en place dans les règles de l’art… mais j’arriverai à une solution technique fonctionnelle (pour moi, en tout cas !)

Ajouter un serveur Fleet

Je commence par déclarer un serveur Fleet:

Ce qui me permet de récupérer un token d’enrollment.

Lancer le container Docker Elastic Agent

Ensuite, tu connais la chanson, je vais lancer une première fois le container Docker d’Elastic Agent. La documentation est . Cet Elastic Agent fera aussi office de serveur Fleet.

Préparer les volumes / dossiers sur mon hote

Je vais gérer les données d’Elastic Agent et la config en dehors du container Docker pour les persister (ça m’évitera de perdre toutes les données à chaque redémarrage du container Docker).

Et je récupère les données et les fichiers de configuration seulement après le premier run.

Donc, dans le dossier qui m’arrange, je crée 2 nouveaux dossiers:

Récupérer les fichiers de configuration

Et de la même manière que pour Elastic, je récupère les fichiers de configuration en local sur mon hôte pour ensuite pouvoir les binder et les redéployer.

Pour les récupérer, c’est simple:

Et:

Je peux ensuite mettre à jour mon script de déploiement avec -v /home/docker-infra/docker-elasticagent/config/state/:/usr/share/elastic-agent/state/ \ et -v /home/docker-infra/docker-elasticagent/config/elastic-agent.yml:/usr/share/elastic-agent/elastic-agent.yml \

Et pareil que pour Kibana, j’ai fait une modification dans le fichier elastic-agent.yml. Par défaut, il s’est généré avec l’IP du container Docker du nœud Elasticsearch. Le problème, c’est que Docker peut changer l’IP du container, et ensuite Kibana perd sa connexion forcément (ce qui m’est arrivé). J’ai donc changé le paramètre hosts.

(La valeur définie est le fallback de ${ELASTICSEARCH_HOSTS}, qui lui-même est écrasé si l’on fournit FLEET_SERVER_ELASTICSEARCH_HOST. Donc normalement, dans mon cas, cela ne sera pas utilisé, c’est juste pour la forme.)

Utiliser les integrations d’Elastic pour se faciliter la tâche

Et voilà, maintenant que l’agent tourne sur mon hôte, je peux facilement configurer l’intégration des logs sans me prendre la tête avec Grok et Logstash (au moins pour 90 % de mes besoins).

Exemple pour récupérer les logs et metrics de Docker

Je fais quelques modifications pour le déploiement d’Elastic Agent. Pour que mon agent ait accès aux données du Docker engine dans un container, je rajoute un volume de la même manière que pour Portainer.

Je fournis également les logs avec:

Et ensuite, depuis Kibana, j’ai juste à rechercher l’intégration souhaitée, comme Docker dans mon exemple ici:

Tu peux éventuellement configurer quelques paramètres:

Et une fois l’intégration ajoutée, j’ai juste à naviguer et filtrer sur les logs qui m’intéressent ou à consulter les dashboards déjà fournis:

Exemple pour récupérer les logs de mon reverse proxy apache

Je fais quelques modifications pour le déploiement d’Elastic Agent. Pour que mon agent ait accès aux logs Apache de mon reverse proxy, et étant donné que mon reverse proxy est un container Docker, j’ai choisi d’avoir un dossier de logs monté en tant que volume sur mon reverse proxy Docker.

Une fois que c’est en place côté reverse proxy (c’est-à-dire une fois que les logs Apache de mon reverse proxy Docker sont accessibles depuis mon hôte), je rajoute un volume pour les fournir à mon agent Elastic.

Ce qui donne schématiquement :
Fichiers logs Container -> Fichiers logs hôte -> Fichiers logs Elastic Agent

Et ensuite, depuis Kibana, j’ai juste à rechercher l’intégration souhaitée, comme Apache HTTP Server dans mon exemple ici:

Tu peux éventuellement configurer quelques paramètres. Dans mon cas, je change l’emplacement de mes logs.

Et une fois l’integration ajoutée, il ne me reste plus qu’à naviguer et filtrer sur les logs qui m’intéressent ou à consulter les dashboards déjà fournis:

Exemple pour récupérer les logs d’un système hote

Je fais quelques modifications pour le déploiement d’Elastic Agent afin qu’il ait accès aux logs de mon système hôte.

Et ensuite, depuis Kibana, j’ai juste à rechercher l’intégration souhaitée, comme System dans mon exemple ici.

Tu peux éventuellement configurer quelques paramètres. Dans mon cas, je change l’emplacement de mes logs:

Et une fois l’intégration ajoutée, j’ai juste à naviguer et filtrer sur les logs qui m’intéressent ou à consulter les dashboards déjà fournis:

Pour aller plus loin

Pour ma part, j’en ai fini avec le cœur du réacteur. Je vais maintenant installer de la même manière des agents sur d’autres hôtes, soit avec la méthode Docker (comme ici), soit avec l’archive Tar directement. Je le documenterai peut-être s’il y a des particularités.

Encore une fois, le sujet est large et je n’ai sûrement pas tout fait dans les règles de l’art.
Au niveau de Docker, je dois me pencher sur la transcription de mes scripts bash en fichier docker-compose.yml et généraliser mon utilisation des secrets Docker. Au niveau d’Elastic, je dois encore explorer quelques réglages (notamment sur la sécurité et le keystore).

En tout cas, ça faisait un moment que je devais mettre en place cette stack pour monitorer plus facilement mes serveurs. Ça me permet, par exemple, de plus facilement repérer ce genre de chose :

tentatives d’intrusions

D’ailleurs, à ce propos, j’avais fais une série d’articles:

Voilà ! J’espère que ce contenu pourra t’être utile. N’hésite pas à me faire un retour. En attendant, je te dis à bientôt pour de nouvelles aventures !!

Partagez l'article:
FacebookTwitterEmailLinkedIn

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.