19
0
Fork 0
wiki/HowtoElasticsearch.md

13 KiB
Raw Blame History

title: Howto Elasticsearch : installation et usage courant

Page en cours de vérification.

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 quil 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