분산 코디네이션 서비스를 제공하는 오픈소스다. Leader-Follower 로 구성되는 앙상블(Ensemble) 위에서 설정 관리 · 클러스터 멤버십 · 리더 선출 · 분산 락을 구현한다. 앙상블 과반(quorum)이 살아 있으면 서비스가 유지된다[1].
주키퍼를 쓰는 대표적인 용도는 다음과 같다.
Kafka 4.0 부터는 ZooKeeper 를 쓰지 않는다. 브로커 메타데이터는 KRaft 가 관리한다. Kafka 때문에 ZooKeeper 를 올릴 필요는 이제 없다 — Apache Kafka 를 볼 것. HDFS NameNode HA(ZKFC) · HBase · Solr 등은 여전히 ZooKeeper 를 쓴다.
| 계열 | 상태 | 비고 |
|---|---|---|
| 3.9 | 현행(current). 최신 3.9.6[2] | |
| 3.8 | 안정(stable). 최신 3.8.7 | 새 minor 가 나오면 약 6개월 안에 보안 · 치명 수정만 받다가 종료된다 |
| 3.7 이하 | EOL (3.7.2 는 2024-02-02 종료) |
Java 8 이상에서 동작한다(JDK 8 · 11 · 17 LTS 권장, Java 9 · 10 은 지원하지 않는다)[1:1].
클라이언트는 앙상블의 아무 서버에 붙어 znode 를 읽거나 쓴다. 앙상블 안의 서버들은 조율된 상태이며 항상 같은 데이터를 가진다 — 어느 서버에서 읽어도 같다.
쓰기 동작은 다음 순서로 전파된다.
클라이언트 관점에서 서버에 접속할 때 보게 되는 것은 znode 다. 리눅스 파일 시스템과 비슷한 트리 구조이며 노드마다 데이터(최대 1MB)를 가진다.
/
/app1 , /app2
/app1/p_1 , /app1/p_2 , /app1/p_3
znode 의 stat 구조는 다음을 담는다.
znode 는 세 가지 타입이 있다.
/app0000000001, /app0000000002 ...). 락 · 글로벌 큐에 쓴다.| 항목 | 요구 |
|---|---|
| Java | 8 이상. JDK 11 또는 17 LTS 권장[1:2] |
| 노드 수 | 홀수. 최소 3대, 서로 다른 장비에 둔다[1:3] |
| 디스크 | 트랜잭션 로그(dataLogDir)는 전용 디스크에 두는 것이 지연 안정에 가장 효과가 크다[1:4] |
| 포트 | 2181(클라이언트) · 2888(팔로워→리더 동기화) · 3888(리더 선출) · 8080(AdminServer) · 7000(Prometheus, 켰을 때) |
RHEL 9 계열 3노드(dist01 · dist02 · dist03)에 3.9.6[2:1] 을 올린다. 세 노드 모두 같은 작업을 하고, myid 만 다르게 준다. sudo 권한이 필요하다.
sudo dnf install -y java-17-openjdk
java -version
sudo groupadd -r zookeeper
sudo useradd -r -g zookeeper -m -d /home/zookeeper -s /bin/bash zookeeper
sudo mkdir -p /opt/apps /data/zookeeper/data /data/zookeeper/datalog /var/log/zookeeper
sudo chown -R zookeeper:zookeeper /data/zookeeper /var/log/zookeeper
cd /usr/local/src
sudo curl -LO https://dlcdn.apache.org/zookeeper/zookeeper-3.9.6/apache-zookeeper-3.9.6-bin.tar.gz
sudo tar -xzf apache-zookeeper-3.9.6-bin.tar.gz -C /opt/apps/
sudo ln -s /opt/apps/apache-zookeeper-3.9.6-bin /opt/zookeeper
sudo chown -R zookeeper:zookeeper /opt/apps/apache-zookeeper-3.9.6-bin /opt/zookeeper
dlcdn.apache.org에는 현행 버전만 있다. 지난 버전은archive.apache.org/dist/zookeeper/에서 받는다. 반드시-bin이 붙은 아카이브를 받는다 — 붙지 않은 것은 소스다.
conf/zoo_sample.cfg 를 복사해 conf/zoo.cfg 로 만들고 고친다. 세 노드에 같은 내용을 둔다.
sudo -u zookeeper cp /opt/zookeeper/conf/zoo_sample.cfg /opt/zookeeper/conf/zoo.cfg
sudo -u zookeeper vi /opt/zookeeper/conf/zoo.cfg
# 기본 시간 단위 (ms)
tickTime=2000
# follower 가 leader 에 처음 연결·동기화할 때 허용하는 tick 수. 넘으면 timeout.
initLimit=10
# leader-follower 사이 동기화 지연 허용 tick 수. 넘으면 follower 가 떨어져 나간다.
syncLimit=5
# 스냅샷 저장 디렉터리. /tmp 는 쓰지 않는다.
dataDir=/data/zookeeper/data
# 트랜잭션 로그 디렉터리. 전용 디스크에 두면 지연이 안정된다.
dataLogDir=/data/zookeeper/datalog
# 클라이언트 접속 포트
clientPort=2181
# 클라이언트 최대 연결 수 (기본 60)
maxClientCnxns=60
# 스냅샷·로그 자동 정리 — 유지 개수(최소 3) 와 주기(시간, 0 이면 끔)
autopurge.snapRetainCount=3
autopurge.purgeInterval=24
# 4글자 명령 허용 목록 (기본은 srvr 만 열려 있다)
4lw.commands.whitelist=srvr,stat,ruok,mntr,conf
# AdminServer (내장 Jetty). 기본 8080 — 다른 서비스와 겹치면 바꾼다.
admin.enableServer=true
admin.serverPort=8080
admin.commandURL=/commands
# Prometheus 메트릭 노출 (선택)
metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
metricsProvider.httpPort=7000
metricsProvider.exportJvmInfo=true
# 앙상블 구성원. server.<myid>=<host>:<동기화 포트>:<리더 선출 포트>
server.1=dist01.haedongg.net:2888:3888
server.2=dist02.haedongg.net:2888:3888
server.3=dist03.haedongg.net:2888:3888
admin.serverPort 기본값은 8080 이다[1:5]. AdminServer 를 외부에 열 이유가 없으면 admin.serverAddress=127.0.0.1 로 묶거나 admin.enableServer=false 로 끈다.
dataDir 안에 myid 파일을 만들고 server.N 의 N 을 적는다. 노드마다 값이 다르다.
# dist01
echo 1 | sudo -u zookeeper tee /data/zookeeper/data/myid
# dist02
echo 2 | sudo -u zookeeper tee /data/zookeeper/data/myid
# dist03
echo 3 | sudo -u zookeeper tee /data/zookeeper/data/myid
bin/zkEnv.sh 는 건드리지 않는다. 힙과 로그 위치는 conf/java.env 로 준다(있으면 zkEnv.sh 가 읽는다).
sudo -u zookeeper tee /opt/zookeeper/conf/java.env > /dev/null <<'ENV'
export JVMFLAGS="-Xms1g -Xmx1g"
export ZOO_LOG_DIR=/var/log/zookeeper
ENV
힙은 물리 메모리를 넘기지 않는다. 스왑이 일어나면 지연이 튀어 앙상블에서 떨어진다.
sudo tee /etc/systemd/system/zookeeper.service > /dev/null <<'UNIT'
[Unit]
Description=Apache ZooKeeper
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
User=zookeeper
Group=zookeeper
Environment=ZOOCFGDIR=/opt/zookeeper/conf
ExecStart=/opt/zookeeper/bin/zkServer.sh start
ExecStop=/opt/zookeeper/bin/zkServer.sh stop
ExecReload=/opt/zookeeper/bin/zkServer.sh restart
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
UNIT
sudo systemctl daemon-reload
sudo systemctl enable --now zookeeper
sudo firewall-cmd --permanent --add-port=2181/tcp
sudo firewall-cmd --permanent --add-port=2888/tcp
sudo firewall-cmd --permanent --add-port=3888/tcp
# 필요할 때만
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --permanent --add-port=7000/tcp
sudo firewall-cmd --reload
# 노드 역할 (leader / follower)
/opt/zookeeper/bin/zkServer.sh status
# 4글자 명령
echo ruok | nc dist01.haedongg.net 2181 # imok
echo mntr | nc dist01.haedongg.net 2181 | grep -E 'zk_server_state|zk_synced_followers'
# AdminServer
curl -s http://dist01.haedongg.net:8080/commands/stat
# 클라이언트 접속
/opt/zookeeper/bin/zkCli.sh -server dist01.haedongg.net:2181
# [zk: dist01.haedongg.net:2181(CONNECTED) 0] ls /
# [zk: dist01.haedongg.net:2181(CONNECTED) 1] create /test "hello"
# [zk: dist01.haedongg.net:2181(CONNECTED) 2] get /test
세 노드 중 하나가 leader, 둘이 follower 로 나오면 앙상블이 선 것이다. zk_synced_followers 는 leader 에서 2 여야 한다.
ZooKeeper Administrator's Guide — 2026-09-20 확인. https://zookeeper.apache.org/doc/current/zookeeperAdmin.html ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
최신 버전 3.9.6 (current) · 3.8.7 (stable) — 2026-09-20 확인. https://zookeeper.apache.org/releases.html ↩︎ ↩︎
그림 출처 — Apache ZooKeeper 공식 문서 (Apache License 2.0). https://zookeeper.apache.org/doc/current/zookeeperOver.html ↩︎