[Elasticsearch](https://www.elastic.co/fr/products/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](HowtoELK).
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](https://www.elastic.co/guide/en/elasticsearch/reference/current/es-release-notes.html), en particulier les sections [breaking changes](https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking-changes.html).
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. :
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 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_` …
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`).
* 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` :
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.
À 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.
**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
* 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 :
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
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 elastic) 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 elastic pour pouvoir vérifier la validité du certificat donné par le serveur.
*Note* : 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.
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}
# echo 'Cannot make a snapshot of elasticsearch, at least one node is not mounting the repository.'
# fi
# for snapshot in $(curl -s -XGET "localhost:9200/_snapshot/snaprepo/_all?pretty=true" | grep -Eo 'snapshot_[0-9]{4}-[0-9]{2}-[0-9]{2}' | head -n -10); do
> *Note* : si vous avez un message d'erreur du type `{"error":"SnapshotRestoreException[[snaprepo:snapshot.daily] cannot restore index [foo] because it's open]","status":500}` vous pouvez fermer l'index en faisant `curl -XPOST "localhost:9200/foo/_close`
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 :
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) :
[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 :
[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]] ...]).
**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 :
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.
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 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.
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.
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.)
Elasticsearch expose une API depremier niveau appelée "cat". Elle permet d'obtenir des informations sur un cluster avec un formattage texte facile à manipuler en ligne de commande là où les sorties JSON le sont moins.
Toute "la documentation est ici":https://www.elastic.co/guide/en/elasticsearch/reference/current/cat.html
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 :
### 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](https://www.elastic.co/guide/en/shield/current/installing-shield.html) est activé.
Si on utilise Elasticsearch pour des logs, voici une solution pour supprimer d'anciennes données avec [Curator](https://www.elastic.co/guide/en/elasticsearch/client/curator/current/index.html), mais lorsque ça n'est pas possible (à cause de compatibilité avec le système) on peut recourir à une approche manuelle:
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
On utilise un [template](https://www.elastic.co/guide/en/elasticsearch/reference/7.8/indices-templates.html) qui définira la valeur par défaut du nombre de replicas de tous les nouveaux index :
### 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 :
### Réinitialiser le mot de passe de `elastic` (sans accès à un utilisateur `superuser`)
Pour réinitialisé 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 role superuser dans les fichiers `/etc/elasticsearch/users` de chaque node (il doit être créé sur chaque node) :
Il est ensuite possible d'utilisé cet utilisateur pour réinitialisé 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](https://www.elastic.co/guide/en/elasticsearch/reference/7.15/security-api-change-password.html) 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 supprimé l'utilisateur créé après cette action :