Howto Elasticsearch
- Installation
- Mise à jour
- Configuration de base
- Configuration avancée
- Monitoring
- Sécurisation
- Snapshots et sauvegardes
- cluster
- Plugins
- Principe de fonctionnement d’Elasticsearch
- Curator
- API “cat”
- FAQ
- Erreur “failed to map segment from shared object: Operation not permitted”
- Lancer plusieurs instances sur un même système pour du test
- Erreur “missing authentication token for REST request”
- Supprimer proprement des vieux index
- Lister les index
- Lister le statut des index
- Relancer l’allocation des shards
- Modifier en masse le nombre de replica :
- Nombre de replicas par défaut
- Consulter l’état du recovery
- Licence X-Pack
- Pas de réponse au curl ou erreur “Empty reply from server”
- Réinitialiser
le mot de passe de
elastic
(sans accès à un utilisateursuperuser
) - OutOfMemoryError: Java heap space
- Erreur
no_valid_shard_copy
- Erreur
Failed to authenticate user 'elastic'
avecelasticsearch-setup-passwords
- Documentation : https://www.elastic.co/guide/en/elasticsearch/reference/7.17/index.html
- Forum : https://discuss.elastic.co/c/elasticsearch
Elasticsearch est un serveur de base de données écrit en Java disposant d’une interface REST HTTP. Elasticsearch est notamment utilisé dans la stack Elastic avec Logstash et Kibana.
Installation
Vu le développement actif d’Elasticsearch, nous préconisons l’installation des paquets Debian distribués par Elasticsearch :
# apt install apt-transport-https
# echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" >> /etc/apt/sources.list.d/elastic.list
# wget -O /etc/apt/trusted.gpg.d/elastic.asc https://artifacts.elastic.co/GPG-KEY-elasticsearch
# dos2unix /etc/apt/trusted.gpg.d/elastic.asc
# chmod 644 /etc/apt/trusted.gpg.d/elastic.asc
# apt update
# apt install elasticsearch
Infos basiques sur le cluster (nom, version, etc.) :
$ curl 127.0.0.1:9200
{
"name" : "my_node",
"cluster_name" : "my_cluster",
"cluster_uuid" : "RwTUfzym2fTq-URwSNGaeg",
"version" : {
"number" : "7.17.0",
"build_flavor" : "default",
"build_type" : "deb",
"build_hash" : "bee86328705acaa9a6daede7140defd4d9ec56bd",
"build_date" : "2022-01-28T08:36:04.875279988Z",
"build_snapshot" : false,
"lucene_version" : "8.11.1",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
Démarrage
Pour activer le démarrage automatique :
# systemctl enable elasticsearch.service
Synchronizing state of elasticsearch.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable elasticsearch
Created symlink /etc/systemd/system/multi-user.target.wants/elasticsearch.service → /lib/systemd/system/elasticsearch.service.
# systemctl start elasticsearch
Mise à jour
Selon la version de départ et la version d’arrivée, la procédure peut être triviale et sans coupure ou bien plus complexe et avec coupure. La grille des versions est disponible ici : https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-upgrade.html.
Lors de changements de versions, certaines fonctionnalités peuvent changer ou disparaître. Il faut donc consulter attentivement les notes de versions, en particulier les sections breaking changes.
Il est important de noter qu’il n’est pas possible (sauf exceptions) de revenir en arrière après une montée de version.
Mise à jour depuis une version inférieure à 5.0
Si vous faites la mise à jour depuis une version inférieure à 5.0, il faut penser à supprimer tous les plugins de type “site” comme head ou kopf qu’il faudra réinstaller différemment. :
# rm -rf /usr/share/elasticsearch/plugins/{kopf,head}
La liste complète des changements est diponible sur https://www.elastic.co/guide/en/elasticsearch/reference/5.0/breaking-changes.html.
Configuration de base
Les paramètres système se trouvent dans le fichier
/etc/default/elasticsearch
, les paramètres liés à la JVM
sont dans /etc/elasticsearch/jvm.options
et
/etc/elasticsearch/jvm.options.d/*.options
(Note:
on privilégiera le deuxième - Attention, l’extention .options est
importante pour que les réglages soient pris en compte) et les options
applicatives (nom du cluster, nom du nœud, mémoire, réseau) se trouvent
dans le fichier /etc/elasticsearch/elasticsearch.yml
.
Il faut activer le redémarrage automatique en cas de mise à jour
(classique sous Debian) dans /etc/default/elasticsearch
:
RESTART_ON_UPGRADE=true
Via le fichier /etc/elasticsearch/elasticsearch.yml
vous
devez au minimum configurer :
Changement du dossier temporaire
On peut aussi définir un tmpdir spécifique
(important quand /tmp
est en noexec
). Dans ce
cas, assurez-vous de créer le répertoire avec les bons droits :
# mkdir /var/lib/elasticsearch/tmp
# chown elasticsearch: /var/lib/elasticsearch/tmp
# chmod 750 /var/lib/elasticsearch/tmp
Version >= 6.x
Le tmpdir se change dans
/etc/default/elasticsearch
:
ES_TMPDIR=/var/lib/elasticsearch/tmp
Cette variable est ensuite utilisée par
/etc/elasticsearch/jvm.options
qui contient normalement la
directive suivante :
-Djava.io.tmpdir=${ES_TMPDIR}
Version < 6.x
On force directement dans les options de la JVM via le fichier
/etc/elasticsearch/jvm.options.d/evolinux.options
:
ES_JAVA_OPTS="-Djava.io.tmpdir=/var/lib/elasticsearch/tmp"
Mémoire allouée
La mémoire allouée au tas de la JVM pour ElasticSearch sont les
lignes -Xms
et -Xmx
dans
/etc/elasticsearch/jvm.options.d/evolinux.options
.
Les deux valeurs doivent être égales.
Pour plus d’informations sur la mémoire allouée au tas de la JVM : HowtoJava#gestion-de-la-mémoire.
Configuration réseau
Par défaut, Elasticsearch écoute sur 127.0.0.1 sur TCP/9200 pour son interface client REST HTTP.
La directive de configuration suivante peut être positionnée pour qu’il écoute sur plusieurs interfaces réseau :
Il est possible d’utiliser des adresses virtuelles, telles que
_local_
(127.0.0.1 et ::1), _site_
(IPs
spécifiques à un réseau privé), _global_
…
Tous les détails sont sur https://www.elastic.co/guide/en/elasticsearch/reference/7.17/modules-network.html#network-interface-values.
Mode “production”
Lorsqu’Elasticsearch est configuré pour écouter sur une IP non locale, il passe en mode “production”.
Il active alors un certain nombre de “bootstrap checks” qui bloquent
le démarrage s’ils ne sont pas tous respectés. Les éventuels échecs sont
lisibles dans le fichier de log (généralement dans
/var/log/elasticsearch/_cluster_name_.log
).
On peut aussi forcer l’exécution de ces contrôles en activant
es.enforce.bootstrap.checks
à true dans les
options de la JVM
Rotation et compression des logs
ElasticSearch fait de lui-même une rotation des logs en datant le fichier du jour et en créant un nouveau fichier. Par contre, aucune compression ni nettoyage n’est fait. Il est possible de déclencher une tâche tous les jours pour faire cela :
#!/bin/sh
LOG_DIR=/var/log/elasticsearch
USER=elasticsearch
MAX_AGE=365
find ${LOG_DIR} -type f -user ${USER} \( -name "*.log.????-??-??" -o -name "*-????-??-??.log" \) -exec gzip --best {} \;
find ${LOG_DIR} -type f -user ${USER} \( -name "*.log.????-??-??.gz" -o -name "*-????-??-??.log.gz" \) -ctime +${MAX_AGE} -delete
En l’indiquant dans une crontab elle sera exécutée quand vous le souhaitez, exemple :
# crontab -l
10 1 * * * /path/to/rotate_elasticsearch_logs.sh
On désactive aussi les logs du ramasse-miettes de la JVM, qui peut être très verbeux :
/etc/elasticsearch/jvm.options
### JDK 8 GC logging
#8:-XX:+PrintGCDetails
#8:-XX:+PrintGCDateStamps
#8:-XX:+PrintTenuringDistribution
#8:-XX:+PrintGCApplicationStoppedTime
#8:-Xloggc:/var/log/elasticsearch/gc.log
#8:-XX:+UseGCLogFileRotation
#8:-XX:NumberOfGCLogFiles=32
#8:-XX:GCLogFileSize=64m
## JDK 9+ GC logging
#9-:-Xlog:gc*,gc+age=trace,safepoint:file=/var/log/elasticsearch/gc.log:utctime,pid,tags:filecount=32,filesize=64m
Puis redémarrer ElasticSearch (l’unité systemd ne propose pas de
reload) : systemctl restart elasticsearch
.
On peut ensuite faire le ménage et compresser les anciens
/var/log/elasticsearch/gc.log.??
, par exemple avec :
for f in $(ls -1 /var/log/elasticsearch/gc*[!.gz]); do gzip -f $f; done
Pour logstash
:
LOG_DIR=/var/log/logstash/
USER=logstash
MAX_AGE=365
find ${LOG_DIR} -type f -user ${USER} -name "logstash-*-????-??-??.log" -exec gzip --best {} \;
Configuration avancée
- Si on veut lancer Elasticsearch avec une JVM différente que celle
par défaut sur le système, on peut définir JAVA_HOME dans
/etc/default/elasticsearch
:
JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre/
Le wrapper qui lance Elasticsearch est
/usr/share/elasticsearch/bin/elasticsearch
voici les
options possibles :
-Edefault.path.XXX=/foo/
: répertoire à utiliser (XXX peut être conf, data, logs etc.)-d
: lancer en mode daemon-p /var/run/elasticsearch/elasticsearch.pid
: chemin du fichier PID--quiet
: mode silencieux
Occupation disque
Elasticsearch prend en considération l’espace disque disponible avant d’allouer des shards sur un nœud (pour des nouveaux index ou des déplacements). Par défaut il stoppe les nouvelles allocations à 85% d’occupation (“low watermark”), tente de déplacer des shards vers d’autres nœuds à 90% (“high watermark”) et enfin passe les index en lecture seule à 95% (“flood watermark”). Plus d’info sur https://www.elastic.co/guide/en/elasticsearch/reference/current/disk-allocator.html
Si le cluster (qu’il y ait un ou plusieurs nœuds) se trouve dans l’incapacité d’allouer des shards pour des données entrantes, il passera alors en état “RED” et les données de ces index ne seront pas écrites.
Les seuils peuvent être adaptés (en pourcentage ou en valeur absolue). Il est conseillé de régler les niveaux d’alerte de l’occupation disque à des seuils cohérents avec les choix faits pour Elastisearch (par exemple 80% par défaut) afin d’avoir une alerte de monitoring avant d’avoir un cluster dégradé. Il est également possible de désactiver complètement cette fonctionnalité, mais c’est à réserver à des situations très maîtrisées.
Changer le thread_pool
https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-threadpool.html
À la manière d’une base de données tel que MySQL ou PostgreSQL, Elasticsearch dispose de plusieurs pools de connexions selon le type de requêtes. Par exemple, le pool pour les requêtes de type « search ». Par défaut il y a une auto-configuration qui est basé sur le nombre de CPU de la machine.
L’auto-configuration n’est pas toujours pertinente, car on peut saturer les pools alors qu’on ne sature pas les ressources de la machine.
Exemple de message indiquant une saturation (49 threads sur 49) :
[Running, pool size = 49, active threads = 49, queued tasks = 2279, completed tasks = 122546879]]
On peut définir nous-même les paramètres à la hausse ou à la baisse, exemple avec le pool « search » :
thread_pool:
search:
size: 128
queue_size: 4096
Monitoring
Nagios
On check sur la page /_cat/health
si le status n’est pas
en red.
/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -u /_cat/health?h=st -p 9200 -r 'red' --invert-regex
Attention : Il faut compléter cette commande avec les options suivantes si les options de sécurisation d’Elasticsearch son activées ! (ie: Authentification HTTP & Chiffrement avec TLS) :
--authorization 'remote_monitoring_user:xxxx'
- Pour l’authentification HTTP-S
- Utilisation de TLS
On obtient ainsi :
/usr/lib/nagios/plugins/check_http -I 127.0.0.1 -S -u /_cat/health?h=st -p 9200 -r 'red' --invert-regex --authorization 'remote_monitoring_user:xxxx'
Munin
Versions 5.x à 7.x
Un plugin Munin est compatible jusqu’à la version 7 d’Elasticsearch :
# apt install ruby-json
# mkdir -p /usr/local/share/munin/plugins
# chmod 755 /usr/local/share/munin /usr/local/share/munin/plugins
# wget https://raw.githubusercontent.com/claygregory/munin-elasticsearch/master/elasticsearch_ -O /usr/local/share/munin/plugins/elasticsearch_
# chmod 755 /usr/local/share/munin/plugins/elasticsearch_
# for p in jvm gc gc_time cache docs ops store; do ln -s /usr/local/share/munin/plugins/elasticsearch_ /etc/munin/plugins/elasticsearch_${p}; done
# systemctl restart munin-node
On peut éventuellement configurer le plugin dans
/etc/munin/plugin-conf.d/elasticsearch
[elasticsearch_*]
env.host 10.1.2.14
env.port 9200
env.node pinky rat
env.user johnsmith
env.user passw0rd
Version 1.x à 5.x
Un plugin pour Munin (compatibles jusqu’à la version 5 d’Elasticsearch) est disponible sur ce dépot Github : https://github.com/y-ken/munin-plugin-elasticsearch/
Procedure d’installation :
# apt install libjson-perl
# git clone https://github.com/y-ken/munin-plugin-elasticsearch.git
# cp -a munin-plugin-elasticsearch /usr/local/src/
# chmod go+rx /usr/local/src/munin-plugin-elasticsearch
# chmod 755 /usr/local/src/munin-plugin-elasticsearch/elasticsearch_*
# ln -s /usr/local/src/munin-plugin-elasticsearch/elasticsearch_* /etc/munin/plugins/
# systemctl restart munin-node.service
Puis tester quelques sondes :
# munin-run elasticsearch_cache
field_size.value 1410084
query_size.value 659968
# munin-run elasticsearch_jvm_memory
heap_max.value 2130051072
heap_used.value 1368633616
non_heap_committed.value 187817984
non_heap_used.value 175388648
heap_committed.value 2130051072
Sécurisation
Elastic définit 3 niveaux de sécurisation :
- Minimal : Authentification HTTP
- Basique (Environnement de production) : Authentification HTTP + Chiffrement inter-nœuds
- Basique avec chiffrement des connexion clients : Authentification HTTP + Chiffrement inter-nœuds + HTTPS sur l’interface REST
Pour aller plus loin, c’est expliqué en détail dans la documentation d’Elasticsearch https://www.elastic.co/guide/en/elasticsearch/reference/7.17/secure-cluster.html
Authentification HTTP
Il faut d’abord activer les fonctions de sécurité dans
/etc/elasticsearch/elasticsearch.yml
sur tous les membres
du cluster :
xpack.security.enabled: true
Après un redémarrage d’Elasticsearch pour la prise en compte de
l’activation de xpack, on utilisera la commande
/usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto
pour créer un mot de passe pour tous les comptes par défaut.
# /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto
Initiating the setup of passwords for reserved users elastic,apm_system,kibana_system,logstash_system,beats_system,remote_monitoring_user.
The passwords will be randomly generated and printed to the console.
Please confirm that you would like to continue [y/N]y
Changed password for user apm_system
PASSWORD apm_system = PASSWORD
Changed password for user kibana_system
PASSWORD kibana_system = PASSWORD
Changed password for user logstash_system
PASSWORD logstash_system = PASSWORD
Changed password for user beats_system
PASSWORD beats_system = PASSWORD
Changed password for user remote_monitoring_user
PASSWORD remote_monitoring_user = PASSWORD
Changed password for user elastic
PASSWORD elastic = PASSWORD
On conservera ces mots de passe avec précaution. Les comptes ont tous des rôles (et donc des permissions) différents.
Chacun son usage :
- elastic : Super-utilisateur, administration du cluster
- kibana_system : Compte système pour le fonctionnement de Kibana
- remote_monitoring_user : Compte pour le monitoring du cluster
- etc
Par la suite, il faut s’assurer que tous les outils de la suite elastic (Kibana, logstash…), mais aussi le monitoring utilisent bien un compte pour s’authentifier, si non ils ne vont plus fonctionner !
Par la suite la gestion des comptes (ajout/suppression/…) se fait au travers de Kibana (après connexion) : Stack management > Users On pourra ainsi créer des comptes applicatifs, avec
Ajustement configuration monitoring
On ajoutera l’argument suivant à la commande de check_http pour
s’authentifier
--authorization 'remote_monitoring_user:PASSWORD'
Ajustement configuration Kibana
Dans /etc/kibana/kibana.yml
, on spécifie le compte a
utiliser :
--- a/etc/kibana/kibana.yml
+++ b/etc/kibana/kibana.yml
@@ -44,7 +44,7 @@ elasticsearch.hosts: ["https://localhost:9200"]
# the username and password that the Kibana server uses to perform maintenance on the Kibana
# index at startup. Your Kibana users still need to authenticate with Elasticsearch, which
# is proxied through the Kibana server.
+elasticsearch.username: "kibana_system"
-#elasticsearch.username: "kibana_system"
#elasticsearch.password: "pass"
# Kibana can also authenticate to Elasticsearch via "service account tokens".
Pour le mot de passe, pour ne pas l’enregistrer en clair dans la configuration, on utilisera le keystore de Kibana
# /usr/share/kibana/bin/kibana-keystore add elasticsearch.password
Enter value for elasticsearch.password: PASSWORD
Puis redémarrer Kibana systemctl restart kibana
Passage en HTTPS
Il y a plusieurs options pour. Le plus simple est de générer une PKI spéciale au cluster Elasticsearch avec les outils proposés.
Amorce de la PKI
# /usr/share/elasticsearch/bin/elasticsearch-certutil ca --days 7300
This tool assists you in the generation of X.509 certificates and certificate
signing requests for use with SSL/TLS in the Elastic stack.
The 'ca' mode generates a new 'certificate authority'
This will create a new X.509 certificate and private key that can be used
to sign certificate when running in 'cert' mode.
Use the 'ca-dn' option if you wish to configure the 'distinguished name'
of the certificate authority
By default the 'ca' mode produces a single PKCS#12 output file which holds:
* The CA certificate
* The CA's private key
If you elect to generate PEM format certificates (the -pem option), then the output will
be a zip file containing individual files for the CA certificate and private key
Please enter the desired output file [elastic-stack-ca.p12]:
Enter password for elastic-stack-ca.p12 :
Le certificat est enregistré par défaut dans
/usr/share/elasticsearch/elastic-stack-ca.p12
. Comme ce
n’est pas un dossier conventionnel, on peut choisir de le déplacer dans
/etc/elasticsearch/
# mv /usr/share/elasticsearch/elastic-stack-ca.p12 /etc/elasticsearch/elastic-stack-ca.p12
Communication inter-nœuds
Pour chaque nœud Elasticsearch, il faut générer un certificat avec
l’outil
/usr/share/elasticsearch/bin/elasticsearch-certutil
On peut essayer, pour garder les choses au clair, d’avoir la
nomenclature suivante pour les noms de certificats
$(hostname).$(service).p12
# /usr/share/elasticsearch/bin/elasticsearch-certutil cert --ca /etc/elasticsearch/elastic-stack-ca.p12 --days 7300
This tool assists you in the generation of X.509 certificates and certificate
signing requests for use with SSL/TLS in the Elastic stack.
The 'cert' mode generates X.509 certificate and private keys.
* By default, this generates a single certificate and key for use
on a single instance.
* The '-multiple' option will prompt you to enter details for multiple
instances and will generate a certificate and key for each one
* The '-in' option allows for the certificate generation to be automated by describing
the details of each instance in a YAML file
* An instance is any piece of the Elastic Stack that requires an SSL certificate.
Depending on your configuration, Elasticsearch, Logstash, Kibana, and Beats
may all require a certificate and private key.
* The minimum required value for each instance is a name. This can simply be the
hostname, which will be used as the Common Name of the certificate. A full
distinguished name may also be used.
* A filename value may be required for each instance. This is necessary when the
name would result in an invalid file or directory name. The name provided here
is used as the directory name (within the zip) and the prefix for the key and
certificate files. The filename is required if you are prompted and the name
is not displayed in the prompt.
* IP addresses and DNS names are optional. Multiple values can be specified as a
comma separated string. If no IP addresses or DNS names are provided, you may
disable hostname verification in your SSL configuration.
* All certificates generated by this tool will be signed by a certificate authority (CA)
unless the --self-signed command line option is specified.
The tool can automatically generate a new CA for you, or you can provide your own with
the --ca or --ca-cert command line options.
By default the 'cert' mode produces a single PKCS#12 output file which holds:
* The instance certificate
* The private key for the instance certificate
* The CA certificate
If you specify any of the following options:
* -pem (PEM formatted output)
* -keep-ca-key (retain generated CA key)
* -multiple (generate multiple certificates)
* -in (generate certificates from an input file)
then the output will be be a zip file containing individual certificate/key files
Enter password for CA (elastic-stack-ca.p12) :
Please enter the desired output file [elastic-certificates.p12]: HOSTNAME.elasticsearch.p12
Enter password for HOSTNAME.elasticsearch.p12 :
Certificates written to /usr/share/elasticsearch/HOSTNAME.elasticsearch.p12
This file should be properly secured as it contains the private key for
your instance.
This file is a self contained file and can be copied and used 'as is'
For each Elastic product that you wish to configure, you should copy
this '.p12' file to the relevant configuration directory
and then follow the SSL configuration instructions in the product guide.
For client applications, you may only need to copy the CA certificate and
configure the client to trust this certificate.
Par la suite on va mv
le certificat généré vers
/etc/elasticsearch
(ou le scp vers les nœud distants)
# mv /usr/share/elasticsearch/HOSTNAME.elasticsearch.p12 /etc/elasticsearch/
# chgrp elasticsearch /etc/elasticsearch/HOSTNAME.elasticsearch.p12
# chmod g+r /etc/elasticsearch/HOSTNAME.elasticsearch.p12
Puis on ajout la configuration de Elasticsearch :
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: HOSTNAME.elasticsearch.p12
xpack.security.transport.ssl.truststore.path: HOSTNAME.elasticsearch.p12
Après, redémarrage avec
systemctl restart elasticsearch
Communication client-serveur
Pour chaque nœud elastic, il faut générer un certificat avec l’outil
/usr/share/elasticsearch/bin/elasticsearch-certutil
On peut essayer, pour garder les choses au clair, d’avoir la
nomenclature suivante pour les noms de certificats
$(hostname).http.p12
Dans le cas d’un déploiement de
nombreux noeuds, on peut avoir recours a un certificat wildcard
qu’on déploiera partout.
Ici exemple pour créer un seul certificat pour notre instance :
# /usr/share/elasticsearch/bin/elasticsearch-certutil http
## Elasticsearch HTTP Certificate Utility
The 'http' command guides you through the process of generating certificates
for use on the HTTP (Rest) interface for Elasticsearch.
This tool will ask you a number of questions in order to generate the right
set of files for your needs.
## Do you wish to generate a Certificate Signing Request (CSR)?
A CSR is used when you want your certificate to be created by an existing
Certificate Authority (CA) that you do not control (that is, you don't have
access to the keys for that CA).
If you are in a corporate environment with a central security team, then you
may have an existing Corporate CA that can generate your certificate for you.
Infrastructure within your organisation may already be configured to trust this
CA, so it may be easier for clients to connect to Elasticsearch if you use a
CSR and send that request to the team that controls your CA.
If you choose not to generate a CSR, this tool will generate a new certificate
for you. That certificate will be signed by a CA under your control. This is a
quick and easy way to secure your cluster with TLS, but you will need to
configure all your clients to trust that custom CA.
Generate a CSR? [y/N]n
## Do you have an existing Certificate Authority (CA) key-pair that you wish to use to sign your certificate?
If you have an existing CA certificate and key, then you can use that CA to
sign your new http certificate. This allows you to use the same CA across
multiple Elasticsearch clusters which can make it easier to configure clients,
and may be easier for you to manage.
If you do not have an existing CA, one will be generated for you.
Use an existing CA? [y/N]y
## What is the path to your CA?
Please enter the full pathname to the Certificate Authority that you wish to
use for signing your new http certificate. This can be in PKCS#12 (.p12), JKS
(.jks) or PEM (.crt, .key, .pem) format.
CA Path: /etc/elasticsearch/elastic-stack-ca.p12
Reading a PKCS12 keystore requires a password.
It is possible for the keystore's password to be blank,
in which case you can simply press <ENTER> at the prompt
Password for elastic-stack-ca.p12:
## How long should your certificates be valid?
Every certificate has an expiry date. When the expiry date is reached clients
will stop trusting your certificate and TLS connections will fail.
Best practice suggests that you should either:
(a) set this to a short duration (90 - 120 days) and have automatic processes
to generate a new certificate before the old one expires, or
(b) set it to a longer duration (3 - 5 years) and then perform a manual update
a few months before it expires.
You may enter the validity period in years (e.g. 3Y), months (e.g. 18M), or days (e.g. 90D)
For how long should your certificate be valid? [5y]
## Do you wish to generate one certificate per node?
If you have multiple nodes in your cluster, then you may choose to generate a
separate certificate for each of these nodes. Each certificate will have its
own private key, and will be issued for a specific hostname or IP address.
Alternatively, you may wish to generate a single certificate that is valid
across all the hostnames or addresses in your cluster.
If all of your nodes will be accessed through a single domain
(e.g. node01.es.example.com, node02.es.example.com, etc) then you may find it
simpler to generate one certificate with a wildcard hostname (*.es.example.com)
and use that across all of your nodes.
However, if you do not have a common domain name, and you expect to add
additional nodes to your cluster in the future, then you should generate a
certificate per node so that you can more easily generate new certificates when
you provision new nodes.
Generate a certificate per node? [y/N]y
## What is the name of node #1?
This name will be used as part of the certificate file name, and as a
descriptive name within the certificate.
You can use any descriptive name that you like, but we recommend using the name
of the Elasticsearch node.
node #1 name: HOSTNAME.example.net
## Which hostnames will be used to connect to HOSTNAME.example.net?
These hostnames will be added as "DNS" names in the "Subject Alternative Name"
(SAN) field in your certificate.
You should list every hostname and variant that people will use to connect to
your cluster over http.
Do not list IP addresses here, you will be asked to enter them later.
If you wish to use a wildcard certificate (for example *.es.example.com) you
can enter that here.
Enter all the hostnames that you need, one per line.
When you are done, press <ENTER> once more to move on to the next step.
HOSTNAME.example.net
localhost
You entered the following hostnames.
- HOSTNAME.example.net
- localhost
Is this correct [Y/n]
## Which IP addresses will be used to connect to HOSTNAME.example.net?
If your clients will ever connect to your nodes by numeric IP address, then you
can list these as valid IP "Subject Alternative Name" (SAN) fields in your
certificate.
If you do not have fixed IP addresses, or not wish to support direct IP access
to your cluster then you can just press <ENTER> to skip this step.
Enter all the IP addresses that you need, one per line.
When you are done, press <ENTER> once more to move on to the next step.
192.0.2.10
2001:DB8::10
127.0.0.1
::1
You entered the following IP addresses.
- 192.0.2.10
- 2001:DB8::10
- 127.0.0.1
- ::1
Is this correct [Y/n]y
## Other certificate options
The generated certificate will have the following additional configuration
values. These values have been selected based on a combination of the
information you have provided above and secure defaults. You should not need to
change these values unless you have specific requirements.
Key Name: HOSTNAME.example.net
Subject DN: CN=HOSTNAME, DC=example, DC=net
Key Size: 2048
Do you wish to change any of these options? [y/N]
Generate additional certificates? [Y/n]n
## What password do you want for your private key(s)?
Your private key(s) will be stored in a PKCS#12 keystore file named "http.p12".
This type of keystore is always password protected, but it is possible to use a
blank password.
If you wish to use a blank password, simply press <enter> at the prompt below.
Provide a password for the "http.p12" file: [<ENTER> for none]
## Where should we save the generated files?
A number of files will be generated including your private key(s),
public certificate(s), and sample configuration options for Elastic Stack products.
These files will be included in a single zip archive.
What filename should be used for the output zip file? [/usr/share/elasticsearch/elasticsearch-ssl-http.zip]
Zip file written to /usr/share/elasticsearch/elasticsearch-ssl-http.zip
On récupère ainsi une archive zip contenant tous les fichiers nécessaires :
~/tmp# unzip elasticsearch-ssl-http.zip
~/tmp# tree .
.
├── elasticsearch
│ ├── http.p12
│ ├── README.txt
│ └── sample-elasticsearch.yml
├── elasticsearch-ssl-http.zip
└── kibana
├── elasticsearch-ca.pem
├── README.txt
└── sample-kibana.yml
2 directories, 7 files
Le dossier elasticsearch
contient le fichier certificat
+ clé au format p12 pour Elasticsearch ainsi qu’un extrait de
configuration d’exemple pour configurer le HTTPS client. Le dossier
kibana
contient le certificat de la CA (pour pouvoir
valider le certificat donné par le serveur Elasticsearch) ainsi qu’un
extrait de configuration d’exemple pour activer le tls client.
Note On pourra ré-utiliser le certificat CA
kibana/elasticsearch-ca.pem
avec tous les services/logiciels clients du cluster Elasticsearch pour pouvoir vérifier la validité du certificat donné par le serveur.
On déplace les fichiers aux bons endroits ~~~ ~/tmp# mv
elasticsearch/http.p12 /etc/elasticsearch/HOSTNAME.http.p12 ~/tmp# chgrp
elasticsearch /etc/elasticsearch/HOSTNAME.http.p12 ~/tmp# chmod g+r
/etc/elasticsearch/HOSTNAME.http.p12 ~/tmp#
~/tmp# mv kibana/elasticsearch-ca.pem /etc/kibana/elasticsearch-ca.pem
~/tmp# chgrp kibana /etc/kibana/elasticsearch-ca.pem ~/tmp# chmod g+r
/etc/kibana/elasticsearch-ca.pem ~~~
Puis on ajoute l’extrait de configuration suivant pour elasticsearch :
Après, redémarrage avec
systemctl restart elasticsearch
Ajustement configuration monitoring
On ajoutera l’argument suivant à la commande de check_http pour
passer en HTTPS -S
Ajustement configuration Kibana
Dans /etc/kibana/kibana.yml
, on doit faire les
changelents suivants :
--- a/kibana/kibana.yml
+++ b/kibana/kibana.yml
@@ -31,7 +31,7 @@ server.basePath: "/kibana"
#server.name: "your-hostname"
# The URLs of the Elasticsearch instances to use for all your queries.
-#elasticsearch.hosts: ["http://localhost:9200"]
+elasticsearch.hosts: ["https://localhost:9200"]
# Kibana uses an index in Elasticsearch to store saved searches, visualizations and
# dashboards. Kibana creates a new index if the index doesn't already exist.
@@ -65,7 +65,7 @@ server.basePath: "/kibana"
# Optional setting that enables you to specify a path to the PEM file for the certificate
# authority for your Elasticsearch instance.
-#elasticsearch.ssl.certificateAuthorities: [ "/path/to/your/CA.pem" ]
+elasticsearch.ssl.certificateAuthorities: [ "/etc/kibana/elasticsearch-ca.pem" ]
# To disregard the validity of SSL certificates, change this setting's value to 'none'.
#elasticsearch.ssl.verificationMode: full
Puis redémarrer Kibana systemctl restart kibana
Snapshots et sauvegardes
Configuration des snapshots
Documentation : http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshots.html
Il faut définir un répertoire où enregistrer les snapshots :
# install -d -o elasticsearch -g elasticsearch -m 750 /home/backup-elasticsearch
Attention : en cas de cluster multi-nœuds, le répertoire de snapshots doit impérativement être partagé entre chaque nœud, classiquement via NFS, car chaque nœud ne gère que ses propres données.
Après avoir créé le répertoire à snapshots pour
l’utilisateur et le groupe elasticsearch
, on précise le
répertoire dans la fichier
/etc/elasticsearch/elasticsearch.yml
:
path.repo: /home/backup-elasticsearch
Il faut redémarrer Elasticsearch et créer un dépôt de snapshots :
$ curl -H 'Content-Type: application/json' -XPUT 'http://localhost:9200/_snapshot/snaprepo' -d '{"type": "fs", "settings": {"location": "/home/backup-elasticsearch", "compress": true}}'
{"acknowledged":true}
Pour vérifier :
$ curl 'http://localhost:9200/_snapshot/?pretty'
{
"snaprepo" : {
"type" : "fs",
"settings" : {
"compress" : "true",
"location" : "/home/backup-elasticsearch"
}
}
}
Si l’on veut supprimer un dépôt de snapshots :
$ curl -s -XDELETE "localhost:9200/_snapshot/snaprepo?pretty"
{"acknowledged":true}
Gestion des snapshots
Pour créer un snapshot dans le dépôt snaprepo
:
$ curl -s -XPUT "localhost:9200/_snapshot/snaprepo/snapshot_test?wait_for_completion=true"
$ ls -l /home/backup-elasticsearch
-rw-r--r-- 1 elasticsearch elasticsearch 34 Apr 11 01:35 index
drwxr-xr-x 22 elasticsearch elasticsearch 4096 Apr 11 01:35 indices
-rw-r--r-- 1 elasticsearch elasticsearch 3006 Apr 11 01:35 metadata-snapshot_test
-rw-r--r-- 1 elasticsearch elasticsearch 419 Apr 11 01:35 snapshot-snapshot_test
Si l’on tente de créer un snapshot déjà existant, on obtiendra :
{"error":"InvalidsnapshotNameException[[backup:snapshot_test] Invalid snapshot name [snapshot_test], snapshot with such name already exists]","status":400}
Lister les snapshots :
$ curl "localhost:9200/_snapshot/snaprepo/_all?pretty=true"
[...]
"snapshots" : [ {
"snapshot" : "snapshot_201403190415",
"indices" : [...],
"state" : "SUCCESS",
"start_time" : "2014-03-19T03:15:03.380Z",
"start_time_in_millis" : 1395198903380,
"end_time" : "2014-03-19T03:16:33.381Z",
"end_time_in_millis" : 1395198993381,
"duration_in_millis" : 90001,
[...]
"snapshot" : "snapshot_201403201222",
"indices" : [...],
"state" : "SUCCESS",
"start_time" : "2014-03-20T11:22:07.441Z",
"start_time_in_millis" : 1395314527441,
"end_time" : "2014-03-20T11:22:56.176Z",
"end_time_in_millis" : 1395314576176,
"duration_in_millis" : 48735,
"failures" : [ ],
"shards" : {
"total" : 86,
"failed" : 0,
"successful" : 86
Pour supprimer un snapshot :
$ curl -s -XDELETE "localhost:9200/_snapshot/snaprepo/snapshot_test"
Sauvegarde via snapshots
On suppose qu’on a déjà configuré un dépôt de snapshots.
On peut ainsi régulièrement des snapshots pour les sauvegardes. Pour créer un snapshot toutes les heures et en conserver 24 en permanence (notion de snapshots “roulants”) :
$ date=$(date +%H)
$ curl -s -X DELETE "127.0.0.1:9200/_snapshot/snaprepo/h${date}" | grep -v -Fx '{"acknowledged":true}'
$ curl -s -X PUT "127.0.0.1:9200/_snapshot/snaprepo/h${date}?wait_for_completion=true" -o /tmp/es_snapshot_h${date}.log
Plus classiquement pour avoir un snapshot par jour :
$ date=$(date +%F)
$ curl -s -XDELETE "localhost:9200/_snapshot/snaprepo/snapshot_${date}" | grep -v -Fx '{"acknowledged":true}'
$ curl -s -XPUT "localhost:9200/_snapshot/snaprepo/snapshot_${date}?wait_for_completion=true" -o /tmp/es_snapshot_${date}.log
On peut ensuite purger les snapshots vieux de plus de 10 jours ainsi :
$ cd /home/backup-elasticsearch/snaprepo
$ for i in $(ls -1d snapshot-* | head -n -10 | sed s'/snapshot-snapshot_//g'); do curl -s -XDELETE "localhost:9200/_snapshot/snaprepo/snaps
hot_${i}"; done
Dans le cas de snapshot pour un Elasticsearch clusterisé :
# if ss | grep ':nfs' | grep -q 'ip\.add\.res\.s1' && ss | grep ':nfs' | grep -q 'ip\.add\.res\.s2'
# then
# curl -s -XDELETE "localhost:9200/_snapshot/snaprepo/snapshot.daily" -o /tmp/es_delete_snapshot.daily.log
# curl -s -XPUT "localhost:9200/_snapshot/snaprepo/snapshot.daily?wait_for_completion=true" -o /tmp/es_snapshot.daily.log
# else
# echo 'Cannot make a snapshot of elasticsearch, at least one node is not mounting the repository.'
# fi
# for snapshot in $(curl -s "localhost:9200/_snapshot/snaprepo/_all?pretty=true" | grep -Eo 'snapshot_[0-9]{4}-[0-9]{2}-[0-9]{2}' | head -n -10); do
# curl -s -XDELETE "localhost:9200/_snapshot/snaprepo/${snapshot}" | grep -v -Fx '{"acknowledged":true}'
# done
# date=$(date +%F)
# curl -s -XPUT "localhost:9200/_snapshot/snaprepo/snapshot_${date}?wait_for_completion=true" -o /tmp/es_snapshot_${date}.log
Si on veut tester la présence d’un snapshot du jour avant de
le faire (attention, il faut avoir jq
installé) :
ES_HOST="http://localhost:9200"
ES_CURL_COMMON_OPTIONS="--insecure -u USER:PASSWORD --silent"
ES_SNAPSHOT_REPO="snaprepo"
ES_SNAPSHOT_NAME="snapshot.daily"
ES_CURL_BASE_URL="${ES_HOST}/_snapshot/${ES_SNAPSHOT_REPO}/${ES_SNAPSHOT_NAME}"
last_daily_raw=$(curl ${ES_CURL_COMMON_OPTIONS} --fail "${ES_CURL_BASE_URL}/" | jq ".snapshots[] | select(.snapshot | contains(\"${ES_SNAPSHOT_NAME}\")) | .end_time" | tr -d '"')
last_daily=$(date --iso-8601=date --date="${last_daily_raw:-"@0"}")
today=$(date --iso-8601=date)
if [ "${last_daily}" != "${today}" ]; then
# Don't display errors for the delete command
curl ${ES_CURL_COMMON_OPTIONS} -XDELETE "${ES_CURL_BASE_URL}" > /dev/null
curl ${ES_CURL_COMMON_OPTIONS} --fail --show-error -XPUT "${ES_CURL_BASE_URL}?wait_for_completion=true" > /dev/null
fi
Restauration d’un snapshot
Le snapshot doit être listé dans le dépôt de snapshot.
Pour restaurer le snapshot snapshot.daily
:
$ curl -XPOST "localhost:9200/_snapshot/snaprepo/snapshot.daily/_restore"
{"accepted":true}
Note : si vous avez un message d’erreur du type
{"error":"SnapshotRestoreException[[snaprepo:snapshot.daily] cannot restore index [snaprepo] because it's open]","status":500}
vous pouvez fermer l’index en faisantcurl -XPOST "localhost:9200/snaprepo/_close
cluster
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/modules-cluster.html
Si l’on compare à d’autres services (MySQL, PostgreSQL, MongoDB…) la gestion d’un cluster Elasticsearch est vraiment simple. Il faut lancer plusieurs instances Elasticsearch sur un réseau avec le même cluster.name et un node.name différent, et il suffit d’indiquer une (ou plusieurs) adresse(s) IP qui va permettre à l’instance de communiquer avec un (ou plusieurs) autre(s) nœud(s) :
cluster.name: foo
node.name: bar0
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["192.0.2.42"]
En démarrant un 2ème nœud bar1 on verra ainsi dans les logs de l’instance master bar0 que le cluster passe de YELLOW à GREEN :
[INFO ][o.e.c.s.ClusterService ] [bar0] added {{bar1}{_jwXmQsAQEyseSOc4pG2IA}{PTpsbMBAQEKTs_OFgW_RYw}{192.0.2.42}{192.0.2.42:9301},}, reason: zen-disco-node-join[{bar1}{_jwXmQsAQEyseSOc4pG2IA}{PTpsbMBAQEKTs_OFgW_RYw}{192.0.2.42}{192.0.2.42:9301}]
[WARN ][o.e.d.z.ElectMasterService] [bar0] value for setting "discovery.zen.minimum_master_nodes" is too low. This can result in data loss! Please set it to at least a quorum of master-eligible nodes (current value: [-1], total number of master-eligible nodes used for publishing in this round: [2])
[INFO ][o.e.c.r.a.AllocationService] [bar0] Cluster health status changed from [YELLOW] to [GREEN] (reason: [shards started [[.monitoring-data-2][0]] ...]).
On peut consulter le statut du cluster via la requête :
$ curl 'http://localhost:9200/_nodes?pretty=true'
{
"_nodes" : {
"total" : 3,
"successful" : 3,
"failed" : 0
},
"cluster_name" : "foo",
"nodes" : {
"4Tt8FlV4TG2Hf_1T4EayQg" : {
"name" : "bar0",
[...]
On voit ainsi qu’il y a 3 nœuds dans le cluster.
Si l’on coupe le master, un autre est élu :
[INFO ][o.e.d.z.ZenDiscovery ] [bar2] master_left [{bar0}{4Tt8FlV4TG2Hf_1T4EayQg}{5nbXw3F5RWCWjUSiRzv9DA}{192.0.2.42}{192.0.2.42:9300}], reason [shut_down]
[WARN ][o.e.d.z.ZenDiscovery ] [bar2] master left (reason = shut_down), current nodes: {{bar2}{5wUhAI79SsyY-DKv4va26Q}{_VQTiZXxTCi2KIsijyQBpg}{192.0.2.42}{192.0.2.42:9302},{bar1}{_jwXmQsAQEyseSOc4pG2IA}{_pQMtkFLSTe3p-eDHMkalw}{192.0.2.42}{192.0.2.42:9301},}
[INFO ][o.e.c.s.ClusterService ] [bar2] removed {{bar0}{4Tt8FlV4TG2Hf_1T4EayQg}{5nbXw3F5RWCWjUSiRzv9DA}{192.0.2.133}{192.0.2.133:9300},}, reason: master_failed ({bar0}{4Tt8FlV4TG2Hf_1T4EayQg}{5nbXw3F5RWCWjUSiRzv9DA}{192.0.2.42}{192.0.2.42:9300})
[INFO ][o.e.c.r.a.AllocationService] [bar2] Cluster health status changed from [GREEN] to [YELLOW] (reason: [removed dead nodes on election]).
[INFO ][o.e.c.s.ClusterService ] [bar2] new_master {bar2}{5wUhAI79SsyY-DKv4va26Q}{_VQTiZXxTCi2KIsijyQBpg}{192.0.2.133}{192.0.2.133:9302}, reason: zen-disco-elected-as-master ([0] nodes joined)
[INFO ][o.e.c.r.DelayedAllocationService] [bar2] scheduling reroute for delayed shards in [59.8s] (2 delayed shards)
[INFO ][o.e.c.r.a.AllocationService] [bar2] Cluster health status changed from [YELLOW] to [GREEN] (reason: [shards started [[.monitoring-es-2-2016.11.06][0]] ...]).
Plugins
Elasticsearch dispose d’un système de plugins, certains officiels et d’autres communautaires. Un redémarrage du service est nécessaire pour prendre en comptes ces changements.
Installation, suppression
Les plugins officiels peuvent être installés en indiquant simplement leur nom :
# /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-phonetic
Pour installer une nouvelle version d’un plugin, il faut d’abord le supprimer :
# /usr/share/elasticsearch/bin/elasticsearch-plugin remove analysis-phonetic
# /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-phonetic
Liste
# /usr/share/elasticsearch/bin/elasticsearch-plugin list
analysis-phonetic
Blocage suite à mise à jour
Attention : certains plugins (ex. : analysis-icu et analysis-phonetic) sont étroitement liés à une version d’Elasticsearch et peuvent bloquer son démarrage en cas d’incohérence. On aura alors une erreur de ce type dans les logs du cluster :
[2017-10-30T09:51:46,918][ERROR][o.e.b.Bootstrap ] Exception
java.lang.IllegalArgumentException: plugin [analysis-phonetic] is incompatible with version [5.6.3]; was designed for version [5.6.2]
On peut utiliser ce script pour automatiser la mise à jour de tous les plugins et le redémarrage d’Elasticsearch :
#!/bin/bash
set -e
set -u
PLUGIN_BIN=/usr/share/elasticsearch/bin/elasticsearch-plugin
NEED_RESTART=""
for plugin in $(${PLUGIN_BIN} list); do
"${PLUGIN_BIN}" remove "${plugin}"
"${PLUGIN_BIN}" install "${plugin}"
NEED_RESTART="1"
done
if [ -n "${NEED_RESTART}" ]; then
systemctl restart elasticsearch
fi
exit 0
Principe de fonctionnement d’Elasticsearch
Basé sur le livre http://exploringelasticsearch.com/book
On utilisera l’outil cURL pour faire les requêtes. En plaçant à la
fin d’une URI ?pretty=true
on pourra obtenir un JSON
formaté, plus lisible pour les humains.
Avec une base de données d’exemple
Nous allons utiliser une base de données d’exemple pour faire des tests.
Télécharger, https://github.com/andrewvc/ee-datasets/archive/master.zip, décompresser l’archive et exécuter le programme Java qui va injecter la BDD “movie_db” dans votre cluster ES.
$ java -jar elastic-loader.jar http://localhost:9200 datasets/movie_db.eloader
La BDD movie_db contient quelques noms de films, avec leurs informations associés (genre, date, acteurs, …).
Pour consulter tout son contenu :
$ curl http://localhost:9200/movie_db/_search?pretty=true
En créant une base de données
Opérations CRUD
Créer un index (équivalent d’une base de données) nommé planet :
$ curl -X PUT localhost:9200/planet
{"acknowledged":true,"shards_acknowledged":true}
Créer un type de donnée nommé « hacker » :
$ curl -X PUT localhost:9200/planet/hacker/_mapping -d '
{
"hacker": {
"properties": {
"handle": {
"type": "string"
},
"age": {
"type": "long"
}
}
}
}
'
Créer un document de type hacker avec l’ID 1 :
$ curl -X PUT localhost:9200/planet/hacker/1 -d '{"handle": "jean-michel", "age": 18}'
{"_index":"planet","_type":"hacker","_id":"1","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"created":true
Voir son contenu :
$ curl localhost:9200/planet/hacker/1?pretty=true
{
"_index" : "planet",
"_type" : "hacker",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"handle" : "jean-michel",
"age" : 18
}
}
Mise à jour du champ âge :
$ curl localhost:9200/planet/hacker/1/_update -d '{"doc": {"age": 19}}'
{"_index":"planet","_type":"hacker","_id":"1","_version":2,"result":"updated","_shards":{"total":2,"successful":1,"failed":0}}
Suppression du document :
$ curl -X DELETE localhost:9200/planet/hacker/1
{"found":true,"_index":"planet","_type":"hacker","_id":"1","_version":3,"result":"deleted","_shards":{"total":2,"successful":1,"failed":0}}
Recherche basique
Recréons un index de test :
$ curl -X DELETE localhost:9200/planet
{"acknowledged":true}
$ curl -X PUT localhost:9200/planet -d '
{
"mappings": {
"hacker": {
"properties": {
"handle": {
"type": "string"
},
"hobbies": {
"type": "string",
"analyzer": "snowball"
}
}
}
}
}
'
Ajoutons quelques documents :
$ curl -X PUT localhost:9200/planet/hacker/1 -d '
{
"handle": "mark",
"hobbies": ["rollerblading", "hacking", "coding"]
}
'
$ curl -X PUT localhost:9200/planet/hacker/2 -d '
{
"handle": "gondry",
"hobbies": ["writing", "skateboarding"]
}
'
$ curl -X PUT localhost:9200/planet/hacker/3 -d '
{
"handle": "jean-michel",
"hobbies": ["coding", "rollerblades"]
}
'
Recherchons ceux qui ont pour hobby rollerblading :
$ curl localhost:9200/planet/hacker/_search?pretty=true -d '
{
"query": {
"match": {
"hobbies": "rollerblading"
}
}
}
'
On obtiens 2 résultats, jean-michel et mark. Pourtant le hobby de jean-michel n’est pas rollerblading mais rollerblades, alors comment Elastic Search l’a trouvé ? C’est parce qu’il comprend que rollerblading et rollerblades sont très similaires ! Cela grâce à l’analyseur de type « snowball » que nous avons indiqué lors de la création du type hobbies. Cela indique à ES qu’il s’agit non pas d’une chaîne de caractère banale mais du texte Anglais (Gestion des autres langues ?).
Curator
Curator est un outil indépendant d’Elasticsearch qui permet de réaliser des opérations diverses sur un cluster, le plus souvent déclenchées par des taches cron, un peu à la manière de logrotate.
Documentation : https://www.elastic.co/guide/en/elasticsearch/client/curator/current/index.html
Installation
# echo "deb https://packages.elastic.co/curator/5/debian9 stable main" >> /etc/apt/sources.list.d/elastic.list
# apt update
# apt install curator
Configuration
Curator s’appuie sur un fichier de configuration qui contient toutes les informations pour se connecter au cluster Elasticsearch (adresse, authentification, chiffrement…).
Dans le de l’exécution via cron, il est conseillé d’envoyer les logs dans un fichier plutôt que dans la sortie standard.
[…]
logging:
loglevel: INFO
logfile: /var/log/curator/curator.log
[…]
Note : ne pas oublier le logrotate :
# cat /etc/logrotate.d/curator
/var/log/curator/*.log {
monthly
rotate 12
compress
delaycompress
missingok
notifempty
}
Actions
Curator utilise également un fichier d’action (potentiellement différent à chaque appel). Il doit contenir les filtres permettant de déterminer quels index sont concernés (motif sur le nom, âge, taille ou nombre de documents…), puis une série d’actions (compression, déplacement, optimisation.)
API “cat”
Elasticsearch expose une API de premier niveau appelée « cat ». Elle permet d’obtenir des informations sur un cluster avec un formatage texte facile à manipuler en ligne de commande là où les sorties JSON le sont moins.
La documentation amont est disponible.
État général du cluster
$ curl -s 127.0.0.1:9200/_cat/health
1545659505 14:51:45 cluster-name green 4 4 418 207 0 0 0 0 - 100.0%
L’option v
permet d’afficher les en-têtes de colonnes
:
$ curl -s 127.0.0.1:9200/_cat/health?v
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1545659712 14:55:12 cluster-name green 4 4 418 207 0 0 0 0 - 100.0%
Liste des nœuds
$ curl -s 127.0.0.1:9200/_cat/nodes?v
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
10.0.0.13 52 83 3 0.01 0.14 0.16 mdi * node3
10.0.0.11 32 92 0 0.09 0.07 0.09 mdi - node1
10.0.0.10 51 87 0 0.36 0.20 0.12 mdi - node0
10.0.0.12 29 87 9 0.31 0.38 0.31 mdi - node2
Dans l’avant-dernière colonne, l’étoile indique le nœud master. Cette
information est aussi disponible par _cat/master
:
$ curl -s 127.0.0.1:9200/_cat/master
C6blxAg5SrmkCx8C80qiig 10.0.0.13 10.0.0.13 node3
Liste des index
On peut récupérer la liste de tous les index, classés par nom :
$ curl -s 127.0.0.1:9200/_cat/indices | sort -k 3
green open index1 vewTWN8WRB-2V6xIgE7oQQ 1 1 2190434 0 2gb 1gb
green open index2 k0a2yjwSS_CKKSydoVzcoQ 1 1 2164950 0 1.9gb 1020.5mb
green yellow index3 rMtU36wXSNS9q9w6BDp0sA 1 1 3156725 0 2.9gb 1.4gb
[…]
On peut limiter la liste selon la valeur de certaines colones
(exemple :health
) :
$ curl -s 127.0.0.1:9200/_cat/indices?health=yellow
green yellow index3 rMtU36wXSNS9q9w6BDp0sA 1 1 3156725 0 2.9gb 1.4gb
Consulter l’état des shards
On peut voir si les shards sont correctement alloués
(STARTED
) ou pas.
$ curl -s 127.0.0.1:9200/_cat/shards
index3 1 p STARTED 0 191b 10.0.0.13 node3
index3 1 r STARTED 0 191b 10.0.0.12 node2
index3 1 r UNASSIGNED
Ici on voit que index3
a un shard non alloué. Pour
savoir pourquoi on eput interroger l’état de l’index à propos de ses
chards :
$ curl 127.0.0.1:9200/index3/_shard_stores?pretty
{
"indices" : {
"index3" : {
"shards" : {
"1" : {
"stores" : [
{
"wPZvU6MUQkmhSb4YrszYeA" : {
"name" : "node3",
"ephemeral_id" : "6EK7veXhQrKAi42UB_97Zw",
"transport_address" : "10.0.0.13:9300",
"attributes" : { }
},
"allocation_id" : "RkL8f2wNS5CVL-MJYVHDaA",
"allocation" : "primary"
},
{
"yuF0yDqHTeyj7Z3rDt9HXw" : {
"name" : "node2",
"ephemeral_id" : "sIkpMVcGTyCkXx4RDd_mgA",
"transport_address" : "10.0.0.12:9300",
"attributes" : { }
},
"allocation_id" : "-piepczfSEiyTV9vN-l5MQ",
"allocation" : "replica"
}
]
}
}
}
}
}
On voir qu’il y a bien un primary mais un seul replica. On peut alors interroger le cluster sur l’état des allocations :
$ curl '127.0.0.1:9200/_cluster/allocation/explain?pretty'
La sortie est en JSON et peut être assez verbeuse. Elle contiendra des explications a priori assez claires sur d’éventuels soucis d’allocations de shards. Dans cet exemple (tronqué) un shard replica ne peut pas être alloué sur un nœud dont la version d’Elasticsearch n’est pas cohérente.
{
"index" : "index3",
"shard" : 1,
"primary" : false,
"current_state" : "unassigned",
"unassigned_info" : {
"reason" : "REPLICA_ADDED",
"at" : "2019-07-31T07:04:15.845Z",
"last_allocation_status" : "no_attempt"
},
"can_allocate" : "no",
"allocate_explanation" : "cannot allocate because allocation is not permitted to any of the nodes",
"node_allocation_decisions" : [
{
"node_id" : "--e8PpGsSKifZ5lFlDkW3A",
"node_name" : "node1",
"transport_address" : "10.0.0.11:9300",
"node_decision" : "no",
"deciders" : [
{
"decider" : "node_version",
"decision" : "NO",
"explanation" : "target node version [5.6.6] is older than the source node version [5.6.15]"
}
]
}
]
}
FAQ
Erreur “failed to map segment from shared object: Operation not permitted”
Si vous obtenez une erreur du type :
[2016-06-15 14:53:05,714][WARN ][bootstrap ] unable to load JNA native support library, native methods will be disabled.
java.lang.UnsatisfiedLinkError: /tmp/jna--1985354563/jna3461912487982682933.tmp: /tmp/jna--1985354563/jna3461912487982682933.tmp: failed
to map segment from shared object: Operation not permitted
C’est peut-être que vous avez votre partition /tmp
en
noexec, il faut alors changer le chemin comme indiqué sur #configuration-de-base
Lancer plusieurs instances sur un même système pour du test
Il faut définir 3 paramètres minimum pour lancer une instance Elasticsearch : * default.path.conf (répertoire de configuration) * default.path.data (répertoire pour les données) * default.path.logs (répertoire pour les logs)
# cp -pr /etc/elasticsearch /usr/local/etc/elasticsearch0
# mkdir -p /srv/es-data/bar0 /srv/es-log/bar0
# chown elasticsearch: /srv/es-data/bar0 /srv/es-log/bar0
Configuration via
/usr/local/etc/elasticsearch0/elasticsearch.yml
:
cluster.name: foo
node.name: bar0
node.master: true
node.data: true
On peut ensuite lancer cette nouvelle instance en ligne de commande :
# su -s /bin/sh elasticsearch
$ /usr/share/elasticsearch/bin/elasticsearch -Edefault.path.conf=/usr/local/etc/elasticsearch0 \
-Edefault.path.data=/srv/es-data/bar0 -Edefault.path.logs=/srv/es-log/bar0
Note : si Elasticsearch nécessite une version de Java différent (Java 8 pour Elasticsearch 5.0), il suffit d’ajouter la variable JAVA_HOME en début de ligne de commande :
$ JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/jre/ /usr/share/elasticsearch/bin/elasticsearch [...]
Erreur “missing authentication token for REST request”
Si vous obtenez une erreur HTTP 401 Unauthorized avec le détail “missing authentication token for REST request…”, c’est probablement que le plugin shield est activé.
Supprimer proprement des vieux index
Si on utilise Elasticsearch pour des logs, voici une solution pour supprimer d’anciennes données avec Curator, mais lorsque ça n’est pas possible (à cause de compatibilité avec le système) on peut recourir à une approche manuelle:
Voici un exemple pour conserver que les 20 derniers index nommés
logstash-*
:
#!/bin/bash
#garder les 10 plus récent
indices=$(curl http://127.0.0.1:9200/_cat/indices/logstash-*?h=i | sort | head -n -10)
for index in ${indices}; do
# echo Delete ${index}
curl --silent --fail --show-error -XDELETE http://127.0.0.1:9200/${index} > /dev/null
done
Lister les index
Cette commande est pratique pour voir la taille que prennent les index
$ curl "http://localhost:9200/_cat/shards?v"
Lister le statut des index
$ curl 'http://127.0.0.1:9200/_cluster/health?level=indices&pretty'
Relancer l’allocation des shards
Dans certains cas le cluster ne parvient pas à allouer des shards (primaires ou réplicas). Il est possible de forcer le reroutage avec cette commande :
$ curl -XPOST 'http://127.0.0.1:9200/_cluster/reroute?retry_failed'
Modifier en masse le nombre de replica :
Par exemple sur un cluster avec un seul nœud, on ne veut pas de replica. On prend alors tous les index en état “yellow” et on passe le nombre de replica à “0”.
# for index in $(curl 127.0.0.1:9200/_cat/indices/?h=index&health=yellow); do curl -X PUT 127.0.0.1:9200/$index/_settings -H 'Content-Type: application/json' -d '{ "index": {"number_of_replicas": 0} }'; done
Nombre de replicas par défaut
On utilise un template qui définira la valeur par défaut du nombre de replicas de tous les nouveaux index :
# curl -X PUT "localhost:9200/_template/template_1?pretty" -H 'Content-Type: application/json' -d'
{
"index_patterns": ["*"],
"settings": {
"number_of_replicas": 0
}
}'
Consulter l’état du recovery
Cette requête donnera une vision sur l’état des synchro et d’éntuelles opérations de recovery :
# curl -s 127.0.0.1:9200/_cat/recovery?v
Licence X-Pack
Le module propriétaire X-Pack nécessite une licence pour une utilisation avancée, voici la procédure :
$ curl -XPUT 'http://127.0.0.1:9200/_xpack/license' -H "Content-Type: application/json" -d @license.json
{"acknowledged":true,"license_status":"valid"}
$ curl 'http://127.0.0.1:9200/_xpack/license'
Note : si l’authentification est activée, on ajoutera l’option pour préciser un utilisateur
-u jdoe
Pas de réponse au curl ou erreur “Empty reply from server”
Si lorsque on tente un curl pour voir l’état du cluster ES, et qu’on a pas de réponse ou alors si en mode verbose on a l’erreur suivante “Empty reply from server” :
# curl -vs 127.0.0.1:9200/_cat/indices
* Expire in 0 ms for 6 (transfer 0x55efb2682530)
* Trying 127.0.0.1...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x55efb2682530)
* Connected to 127.0.0.1 (127.0.0.1) port 9200 (#0)
> GET /_cat/indices HTTP/1.1
> Host: 127.0.0.1:9200
> User-Agent: curl/7.64.0
> Accept: */*
>
* Empty reply from server
* Connection #0 to host 127.0.0.1 left intact
C’est probablement que les requêtes au serveur ES doivent se faire en https, avec authentification, on peut se connecter comme ceci avec la commande suivante :
curl -s -k https://127.0.0.1:9200/_cat/indices --user user:password
Réinitialiser
le mot de passe de elastic
(sans accès à un utilisateur
superuser
)
Pour réinitialiser le mot de passe de elastic
(ou de
tout autre utilisateur) lorsqu’on n’a pas déjà accès à un utilisateur
ayant le rôle superuser
, il faut créer un utilisateur ayant
le rôle superuser dans les fichiers
/etc/elasticsearch/users
de chaque node (il doit être créé
sur chaque node) :
# sudo -g elasticsearch /usr/share/elasticsearch/bin/elasticsearch-users useradd <admin> -r superuser
Il est ensuite possible d’utiliser cet utilisateur pour réinitialiser
le mot de passe de n’importe quel utilisateur (par le biais de kibana ou
de l’API). Dans le cas de kibana, la gestion des utilisateur est dans
“[Hamburger Menu]”>Management>“Stack
Management”>Security>Users. Pour l’API
il s’agit d’une requête POST
vers
/_security/user/<username>/_password
avec un json
contenant soit une entrée nommée “password” (mot de passe en clair) soit
une entrée nommée password_hash
(le hash du mot de
passe).
Il est fortement conseillé de supprimer l’utilisateur créé après cette action :
# sudo -g elasticsearch /usr/share/elasticsearch/bin/elasticsearch-users userdel <admin>
OutOfMemoryError: Java heap space
Solution : augmenter la mémoire allouée à la pile d’appel dans les
arguments Xms et Xmx de la JVM dans
/etc/elasticsearch/jvm.options
:
# Xms represents the initial size of total heap space
-Xms3g
# Xmx represents the maximum size of total heap space
-Xmx3g
Les deux valeurs doivent être égales.
Erreur
no_valid_shard_copy
On peut rencontrer ce problème sur un cluster.
L’explication donnée par Elastic est : « cannot allocate because a
previous copy of the primary shard existed but can no longer be found on
the nodes in the cluster » (sortie de
curl '127.0.0.1:9200/_cluster/allocation/explain?pretty'
).
Il est possible que le shard se trouvait sur un noeud du cluster inaccessible ou mal enlevé du cluster, ou qu’il y ait eu un problème matériel là ou se trouvait le shard.
Erreur
Failed to authenticate user 'elastic'
avec
elasticsearch-setup-passwords
Si en exécutant elasticsearch-setup-passwords
vous rencontrez cette erreur :
# /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto
Failed to authenticate user 'elastic' against https://172.20.3.233:9200/_security/_authenticate?pretty
Possible causes include:
* The password for the 'elastic' user has already been changed on this cluster
* Your elasticsearch node is running against a different keystore
This tool used the keystore at /etc/elasticsearch/elasticsearch.keystore
You can use the `elasticsearch-reset-password` CLI tool to reset the password of the 'elastic' user
ERROR: Failed to verify bootstrap password, with exit code 78
D’abord, if faut savoir que l’utilisation de
elasticsearch-setup-passwords
est dépréciée à partir
d’Elasticsearch 8 en faveur de elasticsearch-reset-passwords
.
Cet utilitaire utilise le mot de passe « boostrap » créé à l’installation d’Elasticseach. S’il a été changé ou que vous ne l’avez pas (installation via Ansible par exemple), alors vous ne pouvez pas utiliser cet utilitaire.
Alternativement, vous pouvez changer les mots de passe via via elasticsearch-setup-passwords
,
Kibana ou l’API de
changement des mots de passe.
Par exemple, avec elasticsearch-setup-passwords
:
# /usr/share/elasticsearch/bin/elasticsearch-reset-password --auto --user <USER>
This tool will reset the password of the [<USER>] user to an autogenerated value.
The password will be printed in the console.
Please confirm that you would like to continue [y/N] y
Password for the [<USER>] user successfully reset.
New value: <PASSWORD>