Lors de l’installation d’un Cluster Solrcloud, il est nécessaire de disposer d’un ensemble Zookeeper opérationnel. On appelle ensemble Zookeeper, un groupe de serveurs Zookeeper qui fonctionnent de concert (« ensemble » donc).
Dans cet article qui décrit l’installation d’un ensemble Zookeeper, sont également abordées les bonnes pratiques qui doivent être impérativement suivies.
Nombre de serveurs dans l’ensemble
La réponse rapide est au minimum trois et idéalement cinq.
Le but est de fournir un service hautement disponible ou l’arrêt pour panne ou maintenance d’un des serveurs de l’ensemble ne perturbe pas le service. Le principe de base pour qu’un ensemble fonctionne est que la moitié plus un des serveurs qui le composent soient disponibles, c’est ce l’on appelle disposer du quorum. Un ensemble de trois serveurs permet donc l’indisponibilité d’un serveur, alors qu’un ensemble de cinq serveurs permet l’indisponibilité de deux serveurs soit la possibilité de stopper un serveur pour une maintenance ou une mise à jour tout en pouvant accepter la perte d’un second serveur pour cause de panne.
Pré-requis
Logiciel
Zookeeper est une application Java. Le seul vrai pré-requis est de disposer d’un environnement Java. Nous préconisons les versions Oracle ou OpenJDK 1.8 ou 1.9.
Hardware
Zookeeper ne requiert pas des serveurs très puissants, les caractéristiques de base conseillées afin de supporter une grande majorité de cas d’usages sont généralement ceux indiqués ci-dessous. Il va de soi que selon l’usage réel de SolrCloud, le monitoring des serveurs Zookeeper (CPU, espace disque, JVM, …) doit amener à adapter ces caractéristiques.
- Processeurs quad-core
- 2 Go de RAM
- 100 Go d’espace disque
- des I/O disques très performantes en écriture
- un réseau gigabits très performant avec une très faible latence entre les membres de l’ensemble Zookeeper et les noeuds Solr
Bonnes pratiques
L’ensemble Zookeeper est un point critique de la stabilité et des performances de SolrCloud. Pour atteindre cette objectif, les bonnes pratiques impératives sont :
- Utilisé des serveurs dédiés
- Désactiver le swap des serveurs (vm.swappiness=1)
- Augmenter la limite « nofile » à 8192 (1024 par défaut) dans « /etc/security/limits.conf »
- Rendre Zookeeper indépendant des DNS en utilisant le fichier « /etc/hosts »
- Allouer à la mémoire heap de Zookeeper au maximum la quantité de mémoire disponible moins 1 Go (Xmx=1g pour 2 Go de RAM disponible). Dans la pratique une Heap de 512 Mo doit couvrir les besoins. Il faut monitorer la JVM et ses GC afin de valider la bonne taille de heap.
- Utiliser des volumes disques distincts pour les données et les logs de transaction (paramètres dataDir et dataLogDir dans zoo.cfg)
- Activer les logs de GC de la JVM et les analyser régulièrement avec le site gceasy.io
- Installer des outils de monitoring du système (CPU, I/O disques, …) afin des contrôler le bon fonctionnement et les performances du système. Nous préconisons « sar » qui fait parti du package sysstat
I/O disque
Il est nécessaire d’expliquer pourquoi il est demandé de disposer d’I/O disque très performants en écriture et d’utiliser des volumes distincts pour le stockage des données et des logs de transaction de Zookeeper. Zookeeper réponds à des requêtes de ses clients (les noeuds Solr). Systématiquement, avant de retourner une réponse, Zookeeper synchronise les transactions sur disque. On comprend alors que si ces écritures sont peu rapides, elles deviennent le goulet d’étranglement qui va provoquer des temps de réponses insuffisants et conduire à une instabilité de SolrCloud.
Utiliser des disques SSD est-il conseillé pour le stockage des logs de transaction ?
Tout d’abord, il faut savoir de quoi on parle. S’agit-il d’un datastore d’un système virtualisé construit sur des disques SSD ou de disques SSD directement et physiquement rattachés au serveur. Dans le premier cas, le gain n’est malheureusement pas forcément significatif. Dans le second cas, le gain doit être très significatif et utiliser des disques SSD pourrait sembler être un bon choix. Malheureusement, les disques SSD très performants en lecture peuvent être pénalisés par ponctuellement des latences importantes en écriture, hors ce sont les performances en écriture qui sont critiques pour Zookeeper ! Pour cette raison et uniquement si on a la certitude de ne pas être victime (même très ponctuellement) de problèmes de latence en écriture, l’usage de disque SSD est possible, sinon l’usage de disques SSD est déconseillé !
Installation de Zookeeper
Il s’agit d’une procédure d’installation sur la base de 5 membres.
Cette opération est a répéter sur chaque serveur de l’ensemble.
- créer un utilisateur zookeeper
$ sudo useradd zookeeper
- mettre en place le fichier /etc/hosts avec le contenu suivant. Le but est d’être totalement indépendant des DNS (pannes ou configuration)
xxx.xxx.xxx.xxa zk1 xxx.xxx.xxx.xxb zk2 xxx.xxx.xxx.xxc zk3 xxx.xxx.xxx.xxd zk4 xxx.xxx.xxx.xxe zk5
- extraire l’archive dans /opt/zookeeper-3.x.x et créer un lien symbolique générique “/opt/zookeeper” indépendant de la version. Les mises à jours seront plus faciles
En version 3.4.x
$ cd /opt $ sudo tar xzf zookeeper-3.4.x.tar.gz $ sudo ln -s zookeeper-3.4.x zookeeper $ sudo chown -R zookeeper: zookeeper-3.4.x
En version 3.5.x
$ cd /opt $ sudo tar xzf apache-zookeeper-3.5.x-bin.tar.gz $ sudo ln -s apache-zookeeper-3.5.x-bin zookeeper $ sudo chown -R zookeeper: apache-zookeeper-3.5.x-bin
- créer des répertoires pour les données, les logs de transactions et le logs de Zookeeper sur des volumes si possible distincts
$ sudo mkdir /<volume_dedie_aux_donnees>/zookeeper-data $ sudo mkdir /<volume_dedie_aux_logs_de_transaction>/zookeeper-data-log $ sudo mkdir /var/log/zookeeper $ sudo chown -R zookeeper: /<volume_dedie_aux_donnees>/zookeeper-data /<volume_dedie_aux_logs_de_transaction>/zookeeper-data-log /var/log/zookeeper
- créer le fichier de configuration “/opt/zookeeper/conf/zoo.cfg” avec le contenu suivant. Il s’agit des paramètres par défaut conseillés avec notamment la distinction des volumes pour les données et les logs de transaction et également l’activation de la purge automatique des données.
tickTime=2000 initLimit=10 syncLimit=5 dataDir=/<volume_dedie_aux_donnees>/zookeeper-data/ dataLogDir=/<volume_dedie_aux_logs_de_transaction>/zookeeper-data-log/ clientPort=2181 autopurge.snapRetainCount=10 autopurge.purgeInterval=24 server.1=zk1:2888:3888 server.2=zk2:2888:3888 server.3=zk3:2888:3888 server.4=zk4:2888:3888 server.5=zk5:2888:3888
- Créer un fichiers myid dans le répertoire data. Ce fichier ne contient uniquement une ligne qui est le numéro de l’instance Zookeeper qui utilise ce répertoire de données (un chiffre de 1 à 255).
cd /opt echo 1 > /<volume_dedie_aux_donnees>/zookeeper-data/myid
L’id 1 est à remplacer par 2, 3, … n sur chacun des serveurs
- mettre en place le fichier d’initialisation “/opt/zookeeper/conf/zookeeper-env.sh” avec le contenu suivant. Contrairement à zoo.cfg, ce fichier est relatif à la configuration de la JVM et des logs. Il permet également de pallier à un problème de conservation des logs de la JVM lors des redémarrages. Les logs des JVM sont en rotation avec une taille de 20 Mo par fichier et un historique de 10 fichiers. Ces valeurs peuvent être adaptées.
Si une version de JVM supérieur a 9 et détectée, le garbadge collectore choisi est le G1GC.
if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then JAVA="$JAVA_HOME/bin/java" elif type -p java; then JAVA=java else echo "Error: JAVA_HOME is not set and java could not be found in PATH." 1>&2 exit 1 fi JAVA_VER=$("$JAVA" -version 2>&1) JAVA_VER_NUM=$(echo $JAVA_VER | head -1 | awk -F '"' '/version/ {print $2}' | sed -e's/^1\.//' | sed -e's/[._-].*$//') echo "Java version $JAVA_VER_NUM" # Configure Log ZOO_LOG_DIR="/opt/zookeeper/log" ZOO_LOG4J_PROP="WARN, ROLLINGFILE" ZOO_GC_LOG_DIR="$ZOO_LOG_DIR" # Configure mémoire JVM selon la mémoire disponible SERVER_JVMFLAGS="-Xmx512m" # Configure JMX (enabled by default for local monitoring by PID) JMXDISABLE=true JMXPORT=10900 # Configure JVM GC and log if [[ "$JAVA_VER_NUM" -lt "9" ]] ; then SERVER_JVMFLAGS="$SERVER_JVMFLAGS -verbose:gc -XX:+PrintHeapAtGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps" SERVER_JVMFLAGS="$SERVER_JVMFLAGS -XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime" SERVER_JVMFLAGS="$SERVER_JVMFLAGS -Xloggc:$ZOO_GC_LOG_DIR/zookeeper-gc.log" SERVER_JVMFLAGS="$SERVER_JVMFLAGS -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=20M" else # Use G1GC SERVER_JVMFLAGS="$SERVER_JVMFLAGS -XX:+UseG1GC -XX:MaxGCPauseMillis=100" #SERVER_JVMFLAGS="-XX:+PerfDisableSharedMem -XX:+ParallelRefProcEnabled -XX:+UseLargePages -XX:+AlwaysPreTouch" SERVER_JVMFLAGS="$SERVER_JVMFLAGS -Xlog:gc*:file=$ZOO_GC_LOG_DIR/zookeeper-gc.log:time,uptime:filecount=10,filesize=20M" fi # Backup des logs GC au démarrage (sinon ils sont perdus) if [ "x$1" = "xstart" ]; then for f in $ZOO_GC_LOG_DIR/zookeeper-gc.log*; do ## Check if the glob gets expanded to existing files. ## If not, f here will be exactly the pattern above ## and the exists test will evaluate to false. if [ -e "$f" ] ; then echo "GC log files found - backing up" d=$PWD && cd $ZOO_GC_LOG_DIR && tar czf zookeeper-gc.$(date +%Y%m%d-%H%M%S).tgz zookeeper-gc.log* && cd $d else echo "No GC log files found" fi ## This is all we needed to know, so we can break after the first iteration break done fi
- Mettre en place le fichier de configuration des logs “/opt/zookeeper/conf/log4j.properties” avec le contenu suivant. Les logs sont en rotation avec une taille de 20 Mo par fichier et un historique de 10 fichiers. Ces valeurs peuvent être adaptées.
# Define some default values that can be overridden by system properties zookeeper.root.logger=INFO, LOGFILE zookeeper.console.threshold=INFO zookeeper.log.dir=. zookeeper.log.file=zookeeper.log zookeeper.log.threshold=DEBUG zookeeper.tracelog.dir=. zookeeper.tracelog.file=zookeeper_trace.log # # ZooKeeper Logging Configuration # # Format is " (, )+ # DEFAULT: console appender only log4j.rootLogger=${zookeeper.root.logger} # # Log to the console # log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.Threshold=${zookeeper.console.threshold} log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n # Add ROLLINGFILE to rootLogger to get log file output log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender log4j.appender.ROLLINGFILE.Threshold=${zookeeper.log.threshold} log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/${zookeeper.log.file} log4j.appender.ROLLINGFILE.MaxFileSize=20MB log4j.appender.ROLLINGFILE.MaxBackupIndex=10 log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n
- repositionner le bon propriétaire des fichiers de configuration
$ sudo chown -R zookeeper: /opt/zookeeper/conf
Script de démarrage
- Mettre en place le script de démarrage “/etc/init.d/zookeeper” avec le contenu suivant
#!/bin/sh # Purpose: This script starts and stops the Zookeeper daemon # chkconfig: - 90 10 # description: Zookeeper daemon APP=/opt/zookeeper/bin/zkServer.sh USER=zookeeper app(){ su - $USER -c "$APP $1" } error(){ echo -e "Error: Parameter non valide !" echo -e "Usage: $0 {start | stop | restart | status}" exit 1 } usage(){ echo -e "Usage: $0 {start | stop | restart | status}" echo "" } start(){ echo -e "Starting Zookeeper" app start echo -e "Done" } stop(){ echo -e "Stopping Zookeeper" app stop echo -e "Done" } restart(){ echo -e "Restarting Zookeeper" app stop sleep 5 app start echo -e "Done" } status(){ echo -e "Zookeeper status" app status } case "$1" in start) start ;; stop) stop ;; status) status ;; restart) restart ;; help) usage ;; *) error ;; esac exit 0
- Démarrer chaque serveur de l’ensemble
$ sudo chmod +x /etc/init.d/zookeeper $ sudo /etc/init.d/zookeeper start
- Mettre en démarrage automatique
Sous Centos :
chkconfig zookeeper on
Sous Debian :
update-rc.d zookeeper defaults
Vous souhaitez bénéficier d’une expertise Solr ou intégrer une ressource ponctuelle à vos projets ? Rendez vous sur la page Contact |