Install and configure a basic ZooKeeper cluster to play with it.

Update package index.

$ sudo apt update

Install GnuPG.

$ sudo apt -y install gpg

Install Java.

$ sudo apt -y install openjdk-11-jre-headless

Create a dedicated zookeeper user.

$ sudo adduser --system --home /opt/zookeeper --shell /bin/bash --uid 810  --group --disabled-login zookeeper

Create a directory for the software archive.

$ sudo -u zookeeper mkdir /opt/zookeeper/software

Download the ZooKeeper archive and its ASCII-armored signature.

$ sudo -u zookeeper wget  --quiet --directory-prefix /opt/zookeeper/software https://downloads.apache.org/zookeeper/zookeeper-3.7.0/apache-zookeeper-3.7.0-bin.tar.gz
$ sudo -u zookeeper wget  --quiet --directory-prefix /opt/zookeeper/software https://downloads.apache.org/zookeeper/zookeeper-3.7.0/apache-zookeeper-3.7.0-bin.tar.gz.asc

Download the public key used to sign this archive.

$ sudo -u zookeeper gpg --keyserver keyserver.ubuntu.com --recv-key AF3D175EC05DB249738D01AC8D8C3C3ED0B02E66
gpg: directory '/opt/zookeeper/.gnupg' created
gpg: keybox '/opt/zookeeper/.gnupg/pubring.kbx' created
gpg: /opt/zookeeper/.gnupg/trustdb.gpg: trustdb created
gpg: key 8D8C3C3ED0B02E66: public key "Damien Diederen (CODE SIGNING KEY) <ddiederen@apache.org>" imported
gpg: Total number processed: 1
gpg:               imported: 1

Verify signature.

$ sudo -u zookeeper gpg --verify /opt/zookeeper/software/{apache-zookeeper-3.7.0-bin.tar.gz.asc,apache-zookeeper-3.7.0-bin.tar.gz}
gpg: Signature made Wed Mar 17 09:47:05 2021 UTC
gpg:                using RSA key AF3D175EC05DB249738D01AC8D8C3C3ED0B02E66
gpg: Good signature from "Damien Diederen (CODE SIGNING KEY) <ddiederen@apache.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: AF3D 175E C05D B249 738D  01AC 8D8C 3C3E D0B0 2E66

Create an application directory.

$ sudo -u zookeeper mkdir /opt/zookeeper/zookeeper

Extract downloaded archive.

$ sudo -u zookeeper tar --directory /opt/zookeeper/zookeeper --strip-components 1 --extract --file /opt/zookeeper/software/apache-zookeeper-3.7.0-bin.tar.gz

Create a data directory.

$ sudo -u zookeeper mkdir /opt/zookeeper/zookeeper/data

Create a sample configuration.

$ sudo -u zookeeper cat <<EOF | tee /opt/zookeeper/zookeeper/conf/zoo.cfg
tickTime=2000
initLimit=10           
syncLimit=5
dataDir=/opt/zookeeper/zookeeper/data
clientPort=2181
server.1=zookeeper1.example.org:2888:3888
server.2=zookeeper2.example.org:2888:3888
server.3=zookeeper3.example.org:2888:3888
EOF

Update myid file that contains the machine id.

$ hostname -s | sed "s/.*\([^0-9]\)//g" | sudo -u zookeeper tee /opt/zookeeper/zookeeper/data/myid

Inspect myid file on zookeeper1.example.org.

$ cat /opt/zookeeper/zookeeper/data/myid
1

Create systemd service file.

$ cat <<EOF | sudo tee /etc/systemd/system/zookeeper.service
[Unit]
Description=ZooKeeper Service
After=network-online.target 
Requires=network-online.target

[Service]
Type=forking

User=zookeeper
Group=zookeeper

ExecStart=/opt/zookeeper/zookeeper/bin/zkServer.sh --config /opt/zookeeper/zookeeper/conf start
ExecStop=/opt/zookeeper/zookeeper/bin/zkServer.sh --config /opt/zookeeper/zookeeper/conf stop
ExecReload=/opt/zookeeper/zookeeper/bin/zkServer.sh --config /opt/zookeeper/zookeeper/conf restart
WorkingDirectory=/opt/zookeeper

[Install]
WantedBy=multi-user.target
EOF

Reload systemd daemon.

$ sudo systemctl daemon-reload

Start service and enable it at boot.

$ sudo systemctl enable --now zookeeper.service 

Check mode on each server.

zookeeper1:~$ sudo -u zookeeper /opt/zookeeper/zookeeper/bin/zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
zookeeper2:~$ sudo -u zookeeper /opt/zookeeper/zookeeper/bin/zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: leader
zookeeper3:~$ sudo -u zookeeper /opt/zookeeper/zookeeper/bin/zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower

Execute cli.

$ sudo -u zookeeper /opt/zookeeper/zookeeper/bin/zkCli.sh
/usr/bin/java                                                                                                            [10/47]
Connecting to localhost:2181                                                                                                    
2021-06-11 14:27:27,565 [myid:] - INFO  [main:Environment@98] - Client environment:zookeeper.version=3.7.0-e3704b390a6697bfdf4b0bef79e3da7a4f6bac4b, built on 2021-03-17 09:46 UTC                                                                              2021-06-11 14:27:27,569 [myid:] - INFO  [main:Environment@98] - Client environment:host.name=zookeeper2
2021-06-11 14:27:27,570 [myid:] - INFO  [main:Environment@98] - Client environment:java.version=11.0.11                         2021-06-11 14:27:27,572 [myid:] - INFO  [main:Environment@98] - Client environment:java.vendor=Debian
2021-06-11 14:27:27,573 [myid:] - INFO  [main:Environment@98] - Client environment:java.home=/usr/lib/jvm/java-11-openjdk-amd64
2021-06-11 14:27:27,574 [myid:] - INFO  [main:Environment@98] - Client environment:java.class.path=/opt/zookeeper/zookeeper/bin/../zookeeper-server/target/classes:/opt/zookeeper/zookeeper/bin/../build/classes:/opt/zookeeper/zookeeper/bin/../zookeeper-server/target/lib/*.jar:/opt/zookeeper/zookeeper/bin/../build/lib/*.jar:/opt/zookeeper/zookeeper/bin/../lib/zookeeper-prometheus-metrics-3.7.0.jar:/opt/zookeeper/zookeeper/bin/../lib/zookeeper-jute-3.7.0.jar:/opt/zookeeper/zookeeper/bin/../lib/zookeeper-3.7.0.jar:/opt/zookeeper/zookeeper/bin/../lib/snappy-java-1.1.7.7.jar:/opt/zookeeper/zookeeper/bin/../lib/slf4j-log4j12-1.7.30.jar:/opt/zookeeper/zookeeper/bin/../lib/slf4j-api-1.7.30.jar:/opt/zookeeper/zookeeper/bin/../lib/simpleclient_servlet-0.9.0.jar:/opt/zookeeper/zookeeper/bin/../lib/simpleclient_hotspot-0.9.0.jar:/opt/zookeeper/zookeeper/bin/../lib/simpleclient_common-0.9.0.jar:/opt/zookeeper/zookeeper/bin/../lib/simpleclient-0.9.0.jar:/opt/zookeeper/zookeeper/bin/../lib/netty-transport-native-unix-common-4.1.59.Final.jar:/opt/zookeeper/zookeeper/bin/../lib/netty-transport-native-epoll-4.1.59.Final.jar:/opt/zookeeper/zookeeper/bin/../lib/netty-transport-4.1.59.Final.jar:/opt/zookeeper/zookeeper/bin/../lib/netty-resolver-4.1.59.Final.jar:/opt/zookeeper/zookeeper/bin/../lib/netty-handler-4.1.59.Final.jar:/opt/zookeeper/zookeeper/bin/../lib/netty-common-4.1.59.Final.jar:/opt/zookeeper/zookeeper/bin/../lib/netty-codec-4.1.59.Final.jar:/opt/zookeeper/zookeeper/bin/../lib/netty-buffer-4.1.59.Final.jar:/opt/zookeeper/zookeeper/bin/../lib/metrics-core-4.1.12.1.jar:/opt/zookeeper/zookeeper/bin/../lib/log4j-1.2.17.jar:/opt/zookeeper/zookeeper/bin/../lib/jline-2.14.6.jar:/opt/zookeeper/zookeeper/bin/../lib/jetty-util-ajax-9.4.38.v20210224.jar:/opt/zookeeper/zookeeper/bin/../lib/jetty-util-9.4.38.v20210224.jar:/opt/zookeeper/zookeeper/bin/../lib/jetty-servlet-9.4.38.v20210224.jar:/opt/zookeeper/zookeeper/bin/../lib/jetty-server-9.4.38.v20210224.jar:/opt/zookeeper/zookeeper/bin/../lib/jetty-security-9.4.38.v20210224.jar:/opt/zookeeper/zookeeper/bin/../lib/jetty-io-9.4.38.v20210224.jar:/opt/zookeeper/zookeeper/bin/../lib/jetty-http-9.4.38.v20210224.jar:/opt/zookeeper/zookeeper/bin/../lib/javax.servlet-api-3.1.0.jar:/opt/zookeeper/zookeeper/bin/../lib/jackson-databind-2.10.5.1.jar:/opt/zookeeper/zookeeper/bin/../lib/jackson-core-2.10.5.jar:/opt/zookeeper/zookeeper/bin/../lib/jackson-annotations-2.10.5.jar:/opt/zookeeper/zookeeper/bin/../lib/commons-cli-1.4.jar:/opt/zookeeper/zookeeper/bin/../lib/audience-annotations-0.12.0.jar:/opt/zookeeper/zookeeper/bin/../zookeeper-*.jar:/opt/zookeeper/zookeeper/bin/../zookeeper-server/src/main/resources/lib/*.jar:/opt/zookeeper/zookeeper/bin/../conf:
2021-06-11 14:27:27,574 [myid:] - INFO  [main:Environment@98] - Client environment:java.library.path=/usr/java/packages/lib:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib
2021-06-11 14:27:27,574 [myid:] - INFO  [main:Environment@98] - Client environment:java.io.tmpdir=/tmp
2021-06-11 14:27:27,575 [myid:] - INFO  [main:Environment@98] - Client environment:java.compiler=<NA>
2021-06-11 14:27:27,575 [myid:] - INFO  [main:Environment@98] - Client environment:os.name=Linux
2021-06-11 14:27:27,576 [myid:] - INFO  [main:Environment@98] - Client environment:os.arch=amd64
2021-06-11 14:27:27,576 [myid:] - INFO  [main:Environment@98] - Client environment:os.version=5.10.0-3-amd64
2021-06-11 14:27:27,576 [myid:] - INFO  [main:Environment@98] - Client environment:user.name=zookeeper
2021-06-11 14:27:27,577 [myid:] - INFO  [main:Environment@98] - Client environment:user.home=/opt/zookeeper
2021-06-11 14:27:27,577 [myid:] - INFO  [main:Environment@98] - Client environment:user.dir=/home/vagrant
2021-06-11 14:27:27,577 [myid:] - INFO  [main:Environment@98] - Client environment:os.memory.free=4MB
2021-06-11 14:27:27,580 [myid:] - INFO  [main:Environment@98] - Client environment:os.memory.max=247MB
2021-06-11 14:27:27,580 [myid:] - INFO  [main:Environment@98] - Client environment:os.memory.total=7MB
2021-06-11 14:27:27,584 [myid:] - INFO  [main:ZooKeeper@637] - Initiating client connection, connectString=localhost:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@68c4039c
2021-06-11 14:27:27,588 [myid:] - INFO  [main:X509Util@77] - Setting -D jdk.tls.rejectClientInitiatedRenegotiation=true to disable client-initiated TLS renegotiation
2021-06-11 14:27:27,596 [myid:] - INFO  [main:ClientCnxnSocket@239] - jute.maxbuffer value is 1048575 Bytes
2021-06-11 14:27:27,612 [myid:] - INFO  [main:ClientCnxn@1726] - zookeeper.request.timeout value is 0. feature enabled=false
Welcome to ZooKeeper!
2021-06-11 14:27:27,657 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1171] - Opening socket connection to server localhost/0:0:0:0:0:0:0:1:2181.
2021-06-11 14:27:27,657 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1173] - SASL config status: Will not attempt to authenticate using SASL (unknown error)
JLine support is enabled
2021-06-11 14:27:27,693 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1005] - Socket connection established, initiating session, client: /0:0:0:0:0:0:0:1:45036, server: localhost/0:0:0:0:0:0:0:1:2181
2021-06-11 14:27:27,732 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1438] - Session establishment complete on server localhost/0:0:0:0:0:0:0:1:2181, session id = 0x2000000eb000000, negotiated timeout = 30000

WATCHER::

WatchedEvent state:SyncConnected type:None path:null

Test some commands.

[zk: localhost:2181(CONNECTED) 0] version
ZooKeeper CLI version: 3.7.0-e3704b390a6697bfdf4b0bef79e3da7a4f6bac4b, built on 2021-03-17 09:46 UTC
[zk: localhost:2181(CONNECTED) 1] get /zookeeper/config
server.1=zookeeper1.example.org:2888:3888:participant
server.2=zookeeper2.example.org:2888:3888:participant
server.3=zookeeper3.example.org:2888:3888:participant
version=0
ko-fi