[WIP] portage de la page Elasticsearch
This commit is contained in:
parent
1e5a1ee301
commit
2a329100e4
|
@ -0,0 +1,464 @@
|
|||
---
|
||||
title: Howto Elasticsearch : installation et usage courant
|
||||
---
|
||||
|
||||
_Page en cours de vérification._
|
||||
|
||||
* Site officiel : https://www.elastic.co/fr/products/elasticsearch
|
||||
* Documentation : https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
|
||||
* Forum communautaire : https://discuss.elastic.co/c/elasticsearch
|
||||
|
||||
Pour une installationde basique la suite ELK, voir l'article [HowtoELK].
|
||||
|
||||
## Installation
|
||||
|
||||
Nous utilisons les paquets Debian distribués par Elasticsearch, les paquets officiels Debian n'étant pas à jour (Elasticsearch est en développement actif…) :
|
||||
|
||||
~~~
|
||||
# echo "deb http://packages.elastic.co/elasticsearch/2.x/debian stable main" | tee -a /etc/apt/sources.list.d/elasticsearch-2.x.list
|
||||
# wget -qO - https://packages.elastic.co/GPG-KEY-elasticsearch | apt-key add -
|
||||
# aptitude update
|
||||
# aptitude install elasticsearch openjdk-7-jre
|
||||
~~~
|
||||
|
||||
Il faut penser à mettre `http://packages.elastic.co/.*` dans la whitelist de Squid si nécessaire.
|
||||
|
||||
Pour que le démon soit géré automatiquement par SysV init :
|
||||
|
||||
~~~
|
||||
# update-rc.d elasticsearch defaults 95 10
|
||||
~~~
|
||||
|
||||
Pour systemd :
|
||||
|
||||
~~~
|
||||
# systemctl enable elasticsearch
|
||||
~~~
|
||||
|
||||
## Configuration
|
||||
|
||||
Il est conseillé de ne pas activer le logging stdout vers la console. Mais de conserver seulement vers les logs. (/var/log/elasticsearch).
|
||||
Dans `/etc/elasticsearch/logging.yml`
|
||||
|
||||
~~~
|
||||
-rootLogger: ${es.logger.level}, console, file
|
||||
+rootLogger: ${es.logger.level}, file
|
||||
~~~
|
||||
|
||||
|
||||
Si on a un `/tmp` en _noexec_, il faut changer le chemin, au risque d'avoir l'erreur suivante.
|
||||
|
||||
~~~
|
||||
[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
|
||||
~~~
|
||||
|
||||
Dans `/etc/default/elasticsearch` :
|
||||
|
||||
~~~
|
||||
ES_JAVA_OPTS="-Djava.io.tmpdir=/var/lib/elasticsearch/tmp"
|
||||
~~~
|
||||
|
||||
Assurez-vous de créer le répertoire :
|
||||
|
||||
~~~
|
||||
# mkdir /var/lib/elasticsearch/tmp
|
||||
# chown elasticsearch: /var/lib/elasticsearch/tmp
|
||||
~~~
|
||||
|
||||
## Plugins utiles
|
||||
|
||||
### Kopf - web admin interface for elasticsearch
|
||||
|
||||
https://github.com/lmenezes/elasticsearch-kopf
|
||||
|
||||
~~~
|
||||
/usr/share/elasticsearch/bin/plugin install lmenezes/elasticsearch-kopf
|
||||
~~~
|
||||
|
||||
## Mode cluster
|
||||
|
||||
Exemples avec 3 instances nommés **elastic1**, **elastic2** et **elastic3**. Avec le mode d'auto découverte.
|
||||
|
||||
Spécifier un nom de cluster dans `elasticsearch.yml` sur chaque machine.
|
||||
|
||||
~~~
|
||||
cluster.name: mycluster
|
||||
~~~
|
||||
|
||||
On donnera un nom aux nœuds avec la directive suivante :
|
||||
|
||||
~~~
|
||||
node.name: "elastic1"
|
||||
~~~
|
||||
|
||||
En analysant les logs de **elastic2** on verra ceci :
|
||||
|
||||
~~~
|
||||
/var/log/elasticsearch/mycluster.log:
|
||||
[2013-10-03 15:52:59,863][INFO ][transport ] [elastic2] bound_add
|
||||
ress {inet[/0:0:0:0:0:0:0:0:9300]}, publish_address {inet[/192.168.4.205:9300]}
|
||||
[2013-10-03 15:53:03,247][INFO ][cluster.service ] [elastic2] detected_
|
||||
master [elastic1][3tn7uHSHR8-donXO6JXFRA][inet[/192.168.4.201:9300]], added {[el
|
||||
astic1][3tn7uHSHR8-donXO6JXFRA][inet[/192.168.4.201:9300]],}, reason: zen-disco-
|
||||
receive(from master [[elastic1][3tn7uHSHR8-donXO6JXFRA][inet[/192.168.4.201:9300
|
||||
]]])
|
||||
[2013-10-03 15:53:03,338][INFO ][discovery ] [elastic2] mycluster
|
||||
/aFsNsA7pRa2_injvAU5Hwg
|
||||
[2013-10-03 15:53:03,362][INFO ][http ] [elastic2] bound_add
|
||||
ress {inet[/0:0:0:0:0:0:0:0:9200]}, publish_address {inet[/192.168.4.205:9200]}
|
||||
[2013-10-03 15:53:03,362][INFO ][node ] [elastic2] started
|
||||
~~~
|
||||
|
||||
Indiquant que le master a été détecté.
|
||||
|
||||
Et sur **elastic1**, le master :
|
||||
|
||||
~~~
|
||||
[2013-10-03 15:53:03,176][INFO ][cluster.service ] [elastic1] added {[e
|
||||
lastic2][aFsNsA7pRa2_injvAU5Hwg][inet[/192.168.4.205:9300]],}, reason: zen-disco
|
||||
-receive(join from node[[elastic2][aFsNsA7pRa2_injvAU5Hwg][inet[/192.168.4.205:9
|
||||
300]]])
|
||||
[2013-10-03 15:54:37,112][INFO ][cluster.service ] [elastic1] added {[e
|
||||
lastic3][CLCB_hU5TeGXLziFcLjY8w][inet[/192.168.4.204:9300]],}, reason: zen-disco
|
||||
-receive(join from node[[elastic3][CLCB_hU5TeGXLziFcLjY8w][inet[/192.168.4.204:9
|
||||
300]]])
|
||||
~~~
|
||||
|
||||
Indique que les deux slaves ont été ajoutés.
|
||||
|
||||
On peut consulter le status en faisant des requêtes de types RESTFul. :
|
||||
|
||||
~~~
|
||||
curl 'http://localhost:9200/_nodes?pretty=true'
|
||||
~~~
|
||||
|
||||
|
||||
Si le master passe en DOWN, un autre est élu.
|
||||
|
||||
|
||||
~~~
|
||||
[2013-10-03 16:15:53,892][INFO ][discovery.zen ] [elastic2] master_le
|
||||
ft [[elastic1][3tn7uHSHR8-donXO6JXFRA][inet[/192.168.4.201:9300]]], reason [shut
|
||||
_down]
|
||||
|
||||
[2013-10-03 16:15:53,920][INFO ][cluster.service ] [elastic2] master {n
|
||||
ew [elastic3][CLCB_hU5TeGXLziFcLjY8w][inet[/192.168.4.204:9300]], previous [elas
|
||||
tic1][3tn7uHSHR8-donXO6JXFRA][inet[/192.168.4.201:9300]]}, removed {[elastic1][3
|
||||
tn7uHSHR8-donXO6JXFRA][inet[/192.168.4.201:9300]],}, reason: zen-disco-receive(f
|
||||
rom master [[elastic3][CLCB_hU5TeGXLziFcLjY8w][inet[/192.168.4.204:9300]]])
|
||||
~~~
|
||||
|
||||
Pour éviter de faire des requêtes multicast (mode auto-découverte). On spécifiera la liste des nœuds dans la configuration des instances.
|
||||
|
||||
~~~
|
||||
discovery.zen.ping.multicast.enabled: false
|
||||
discovery.zen.ping.unicast.hosts: ["elastic2", "elastic3"]
|
||||
~~~
|
||||
|
||||
## Check Nagios
|
||||
|
||||
On check sur la page `/_cluster/health` si le status n'est pas en **red**.
|
||||
|
||||
~~~
|
||||
/usr/lib/nagios/plugins/check_http -H localhost -u /_cluster/health -p 9200 -r '"status":"red",' --invert-regex
|
||||
~~~
|
||||
|
||||
## Backup
|
||||
|
||||
Une sauvegarde simple peut être de sauvegarder `/var/lib/elasticsearch/`
|
||||
|
||||
Il est néanmoins conseillé de désactiver/flusher les translogs avant la sauvegarde, puis de les réactiver :
|
||||
|
||||
~~~
|
||||
$ curl -s -X PUT 'localhost:9200/_settings' -d '{"index.translog.disable_flush": true}' >/dev/null
|
||||
$ curl -s 'localhost:9200/_flush' | grep -qe '"ok":true'
|
||||
$ if [ $? -eq 0 ]; then
|
||||
rsync -a --delete /var/lib/elasticsearch/ /home/backup/elasticsearch/
|
||||
else
|
||||
echo "Error when flushing ES translog indexes."
|
||||
fi
|
||||
$ curl -s -XPUT 'localhost:9200/_settings' -d '{"index.translog.disable_flush": false}' > /dev/null
|
||||
~~~
|
||||
|
||||
Une sauvegarde plus avancée est d'utiliser les snaphosts, un exemple :
|
||||
|
||||
~~~
|
||||
$ cd /srv/snapshots
|
||||
$ for i in $(ls -1d snapshot-* | head -n -10 | sed s'/snapshot-snapshot_//g'); do curl -s -XDELETE "localhost:9200/_snapshot/backup/snaps hot_${i}"; done
|
||||
$ date=$(date +%Y-%m-%d)
|
||||
$ curl -s -XDELETE "localhost:9200/_snapshot/backup/snapshot_${date}" | grep -v acknowledged..true
|
||||
$ curl -s -XPUT "localhost:9200/_snapshot/backup/snapshot_${date}?wait_for_completion=true" -o /tmp/es_snapshot_${date}.log
|
||||
~~~
|
||||
|
||||
Attention, en mode cluster il faut gérer des montages NFS sur les nœuds slaves car chacun écrit uniquement les données qu'il a !
|
||||
|
||||
## Principe de fonctionnement
|
||||
|
||||
_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 BDD 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 BDD
|
||||
|
||||
#### Opérations CRUD
|
||||
|
||||
Créer un index (équivalent d'une base de données) nommé « planet ».
|
||||
|
||||
~~~
|
||||
curl -X PUT localhost:9200/planet
|
||||
~~~
|
||||
|
||||
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}'
|
||||
~~~
|
||||
|
||||
Voir son contenu.
|
||||
|
||||
~~~
|
||||
curl localhost:9200/planet/hacker/1?pretty=true
|
||||
~~~
|
||||
|
||||
Mise à jour du champ âge.
|
||||
|
||||
~~~
|
||||
curl -X POST localhost:9200/planet/hacker/1/_update -d @- <<< '{"doc": {"age": 19}}'
|
||||
~~~
|
||||
|
||||
Suppression du document.
|
||||
|
||||
~~~
|
||||
curl -X DELETE localhost:9200/planet/hacker/1
|
||||
~~~
|
||||
|
||||
#### Recherche basique
|
||||
|
||||
Recréons un index de test :
|
||||
|
||||
~~~
|
||||
curl -X DELETE localhost:9200/planet
|
||||
~~~
|
||||
|
||||
~~~
|
||||
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 -X POST 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 ?).
|
||||
|
||||
## snapshots
|
||||
|
||||
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshots.html
|
||||
|
||||
Création d'un répertoire pour accueillir les snapshots :
|
||||
|
||||
~~~
|
||||
# mkdir /home/backup-elasticsearch
|
||||
# chown elasticsearch:elasticsearch /home/backup-elasticsearch
|
||||
# chmod 750 /home/backup-elasticsearch
|
||||
# vim /etc/elasticsearch/elasticsearch.yml
|
||||
|
||||
path.repo: ["/home/backup-elasticsearch"]
|
||||
|
||||
$ curl -XPUT 'http://localhost:9200/_snapshot/backup' -d '{
|
||||
"type": "fs",
|
||||
"settings": {
|
||||
"location": "/home/backup-elasticsearch",
|
||||
"compress": true
|
||||
}
|
||||
}'
|
||||
{"acknowledged":true}
|
||||
~~~
|
||||
|
||||
ATTENTION, dans le cadre d'un cluster, chaque noeud écrira ses données
|
||||
dans son répertoire local… et ne les effacera pas en cas de DELETE.
|
||||
Il faut donc centraliser ce répertoire via un montage NFS !
|
||||
|
||||
Vérifier les infos du répertoire pour les snapshots :
|
||||
|
||||
~~~
|
||||
$ curl -XGET 'http://localhost:9200/_snapshot/?pretty'
|
||||
|
||||
---
|
||||
{
|
||||
"backup" : {
|
||||
"type" : "fs",
|
||||
"settings" : {
|
||||
"compress" : "true",
|
||||
"location" : "/home/backup-elasticsearch"
|
||||
}
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
Supprimer les infos sur le répertoire des snapshots :
|
||||
|
||||
~~~
|
||||
$ curl -s -XDELETE "localhost:9200/_snapshot/backup?pretty"
|
||||
|
||||
---
|
||||
{"acknowledged":true}
|
||||
~~~
|
||||
|
||||
Créer un snapshot :
|
||||
|
||||
~~~
|
||||
$ curl -s -XPUT "localhost:9200/_snapshot/backup/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
|
||||
~~~
|
||||
|
||||
Supprimer un snapshot :
|
||||
|
||||
~~~
|
||||
$ curl -s -XDELETE "localhost:9200/_snapshot/backup/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 -XGET "localhost:9200/_snapshot/backup/_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 faire des backups on pourra utiliser un script comme celui-ci :
|
||||
|
||||
~~~
|
||||
# Clean old snapshots (keep 10 snaps).
|
||||
cd /home/backup-elasticsearch
|
||||
for i in $(ls -1d snapshot-* | head -n -10 | sed s'/snapshot-snapshot_//g'); do curl -s -XDELETE "localhost:9200/_snapshot/backup/snaps
|
||||
hot_${i}"; done
|
||||
# Take a snapshot on master node.
|
||||
date=$(date +%Y-%m-%d)
|
||||
curl -s -XDELETE "localhost:9200/_snapshot/backup/snapshot_${date}" | grep -v acknowledged..true
|
||||
curl -s -XPUT "localhost:9200/_snapshot/backup/snapshot_${date}?wait_for_completion=true" -o /tmp/es_snapshot_${date}.log
|
||||
~~~
|
Loading…
Reference in New Issue