Site icon Eolya Consulting

Zookeeper – Installation et bonnes pratiques

Zookeeper logo

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.

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 :

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.

$ sudo useradd zookeeper
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 

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
$ 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
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
cd /opt
echo 1 > /<volume_dedie_aux_donnees>/zookeeper-data/myid

L’id 1 est à remplacer par 2, 3, … n sur chacun des serveurs

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
# 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
$ sudo chown -R zookeeper: /opt/zookeeper/conf

Script de démarrage

#!/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
$ sudo chmod +x /etc/init.d/zookeeper
$ sudo /etc/init.d/zookeeper start

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

Quitter la version mobile