ZooKeeper 란

ZooKeeper는 분산 어플리케이션들에 대한 분산 조정 서비스를 제공하는 프로그램으로 표준 파일 시스템과 유사하게 구성되어 공유된 계층적 공간을 통해서 분산된 프로세스들이 서로 조정할 수 있는 기능을 관리한다. 공유되는 공간은 ZooKeepr의 용어로 zNodes라고 불리는 데이터 등록의 집합으로 구성 되어 있으며 이 구조는 폴더들과 파일들의 구성과 유사하다. 파일 시스템과는 달리 ZooKeeper는 자바로 실행되며 자바와 C에 대한 바인딩을 가지고 있다.

ZooKeeper Cluster 기본 구성

ZooKeeper Service 는 “Ensemble” 이라고 불리는 Host 들의 집합들을 통해서 복제되며, 동일한 어플리케이션을 구성하는 서버들의 복제된 그룹을 “Quorum” 이라고 부른다. Quorum 내의 모든 서버는 동일한 설정 파일들의 복제본을 가지고 있다. 

ZooKepper의 서버 구성의 수는 절반이 실패해도 기능을 수행할 수 있도록 항상 홀수로 구성하는 것을 권장한다. 예를 들어 2대의 서버가 장애 상태가 되어도 나머지 서버들이 동작할 수 있도록 5대의 서버로 구성하는 것이다. 이 중에 한 대는 Leader가 된다. 최소한의 구성은 3 대가 된다.

ZooKeeper Cluster의 구성은 아래의 그림과 같이 기본적으로 Leader를 포함하는 홀 수의 서버 구성이 되어야 한다.


본 문서에서는 한 대의 서버에 3개의 주키퍼 서버 구성을 설명한다.

  • ZooKeeper 서버 구성의 수는  - 위에서 언급한 것과 같이 홀수를 기준으로 구성하며, 테스트 환경이므로 3대의 서버로 구성한다.
  • 물리적인 서버의 수는 - 물리적인 장애가 발생하는 경우를 대비해서 가능하면 물리적으로 존재하는 서버로 구성하는 것이 좋다. 그러나 본 문서에서는 단일 서버를 사용하도록 한다.
  • 운영을 위한 포트의 구성은 - 별도의 서버로 존재하면 Port를 크게 신경쓰지 않아도 되지만 테스트를 위해서 단일 서버에 구성하는 것이기 때문에 아래와 같이 구성한다.
    • Client Port  - 클러스터에서 운영할 어플리케이션에 ZooKeeper로 접속하기 위한 포트를 의미한다.
    • Qourum Port  - 클러스터내의 ZooKeeper 서버간에 통신을 위한 포트를 의미한다.
    • Leader election Port  - 클러스터내의 ZooKeeper 서버간에 Leader를 선출하기 위한 통신 포트를 의미한다.

단일 서버에 3개의 ZooKeeper 서버를 구성하기 위해 아래와 같이 포트 구성과 경로를 설정해 준다.

Server ID Client Port Quorum Port Election Port dataDir dataLogDir
1 2181 2888 3888 /zkdata/zkdata1 /zktlogs/zktlog1
2 2182 2889 3889 /zkdata/zkdata2 /zktlogs/zktlog2
3 2183 2890 3890 /zkdata/zkdata3 /zktlogs/zktlog3
  • dataDir 은 in-memory database snapshots을 저장하기 위한 경로이다.
  • dataLogDir 은  트랜잭션 Log 저장을 위한 경로이다.

ZooKeeper에 대한 메모리 설정은 - 테스트 시에는 기본 Heap size를 사용해도 되지만 운영 서버 구성 시에는 ZooKeeper 설치 경로의 “/conf/java.env” 파일을 생성해서 메모리 설정을 조정해 준다.

ZooKeeper Multiple Server 구성하기

각각의 주키퍼 서버를 구성하기 위해 환경파일(cfg) 을 구성한다.

주키퍼가 설치된 경로 밑에 conf 디렉토리에 있는 zoo_sample.cfg 을 복사해서 3개의 zoo1.cfg, zoo2.cfg, zoo3.cfg 파일을 생성하고 아래와 같이 각각의 파일을 수정한다.

dataDir과 clientPort 파라미터는 각 주키퍼 서버에 맞도록 설정한다.

 

zoo1.cfg 파일 내용

dataDir=/zkdata/zkdata1
dataLogDir=/zktlogs/zktlog1
# the port at which the clients will connect
clientPort=2181

server.1=localhost:2888:3888
server.2=localhost:2889:3889
server.3=localhost:2890:3890

zoo2.cfg 파일 내용

dataDir=/zkdata/zkdata2
dataLogDir=/zktlogs/zktlog2
# the port at which the clients will connect
clientPort=2182

server.1=localhost:2888:3888
server.2=localhost:2889:3889
server.3=localhost:2890:3890

zoo3.cfg 파일 내용

dataDir=/zkdata/zkdata3
dataLogDir=/zktlogs/zktlog3
# the port at which the clients will connect
clientPort=2183

server.1=localhost:2888:3888
server.2=localhost:2889:3889
server.3=localhost:2890:3890

 

myid 파일 생성

각 주키퍼 서버의 dataDir 디렉토리 밑에 myid 파일을 만들고 각 서버를 구별할 수 있도록 1번 서버에는 1, 2번 서버에는 2, 3번 서버에는 3이 기록된 myid 파일을 생성한다.

$ echo 1 > /zkdata/zkdata1/myid
$ echo 2 > /zkdata/zkdata2/myid
$ echo 3 > /zkdata/zkdata3/myid

 

 

ZooKeeper Multiple Server 실행하기

각각의 환경파일로 주키퍼 서버를 기동한다.

$ bin/zkServer.sh start conf/zoo1.cfg
$ bin/zkServer.sh start conf/zoo2.cfg
$ bin/zkServer.sh start conf/zoo3.cfg

프로세스가 정상적으로 구동했는지 확인한다.

netstat -an | grep 218
tcp6       0      0 :::2181                 :::*                    LISTEN
tcp6       0      0 :::2182                 :::*                    LISTEN
tcp6       0      0 :::2183                 :::*                    LISTEN

zkServer.sh 명령어로 주키퍼 서버의 상태를 조회한다. 예제에서는 2번 주키퍼 서버가 leader이고 1번, 3번 서버가 follower 인 것을 볼 수 있다.

$ bin/zkServer.sh status conf/zoo3.cfg
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: conf/zoo3.cfg
Client port found: 2183. Client address: 172.24.121.239. Client SSL: false.
Mode: follower

$ bin/zkServer.sh status conf/zoo2.cfg
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: conf/zoo2.cfg
Client port found: 2182. Client address: 172.24.121.239. Client SSL: false.
Mode: leader

$ bin/zkServer.sh status conf/zoo1.cfg
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: conf/zoo1.cfg
Client port found: 2181. Client address: 172.24.121.239. Client SSL: false.
Mode: follower

 

 

start the server in the foreground for debugging

주키퍼 서버를 foreground 모드로 실행한다.

bin/zkServer.sh start-foreground conf/zoo1.cfg
bin/zkServer.sh start-foreground conf/zoo2.cfg
bin/zkServer.sh start-foreground conf/zoo3.cfg

 

stop the server

주키퍼 서버를 중지한다.

bin/zkServer.sh stop conf/zoo1.cfg
bin/zkServer.sh stop conf/zoo2.cfg
bin/zkServer.sh stop conf/zoo3.cfg

restart the server

주키퍼 서버를 재시작한다.

bin/zkServer.sh restart conf/zoo1.cfg
bin/zkServer.sh restart conf/zoo2.cfg
bin/zkServer.sh restart conf/zoo3.cfg

 

Notes
zk-server1 을 실행하면 Log 상에 2번과 3번 서버로의 통신이 실패했다는 Log를 볼 수 있다. zk-server2 를 실행하면 3 번 서버로의 통신이 실패했다는 Log를 볼 수 있다. 1번과 2번이 실행되었으므로 1번과 2번 모두 3번과 연결할 수 없다는 Log를 확인할 수 있다. 마지막으로 zk-server3 을 실행하면 연결이 모두 되어 동작하는 것을 확인할 수 있다.
zkServer.sh 스크립트는 다양한 명령을 제공한다.

  • start
  • start-foreground
  • stop
  • restart
  • status
  • upgrade
  • print-cmd

 

ZooKeeper CLI Client 사용법

ZooKeeper CLI 는 Command Line 으로 ZooKeeper를 관리할 수 있는 도구로 주키퍼 CLI 문서를 참고한다. 

[ 추가 참고문서 ]

 How to connect ZooKeeper through CLI? 와 “Famous Four letter commands” 를 참조하면 된다.

 

ZooKeeper Commands: The Four Letter Words 수행

nc 나 telnet 로 서비스 port에 4자리 주키퍼 명령어를 보낸다.

아래 ruok 명령어를 주키퍼 서버에 보내는 예제이다.

 

nc(Netcat)은 TCP/UDP 프로토콜로 연결된 네크워크 상에서 데이터를 읽고 쓸 수 있는 간단한 리눅스 유틸리티이다. 네크워크에 연결된 서버 간의 포트 오픈을 확인할 수 있고, listen 모드로 자신이 서버가 되는 기능을 제공하기도 한다.

$  echo ruok | nc 127.0.0.1 2181
ruok is not executed because it is not in the whitelist.

$ nc 127.0.0.1 2181
ruok
ruok is not executed because it is not in the whitelist.

$ telnet localhost 2181
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
ruok
ruok is not executed because it is not in the whitelist.
Connection closed by foreign host.

위 예제에서는 "ruok is not executed because it is not in the whitelist." 메시지가 출력되었는데

환경설정 파일에(zoo1.cfg, zoo2.cfg, zoo3.cfg 또는 zookeeper.properties 파일) 아래 내용을 추가하고 주키퍼 서버를 재기동 하면 정상적인 메시지를 받을 수 있다.

  • 4lw.commands.whitelist=*
$  echo ruok | nc 127.0.0.1 2181
imok

$ nc 127.0.0.1 2181
ruok
imok

$ telnet localhost 2181
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
ruok
imok

 

ZooKeeper Cluster를 어플리케이션에서 사용하는 방법

ZooKeeper Cluster 를 이용할 어플리케이션은 ZooKeeper Cluster 구성 후에는 바로 연결할 수 있다.

이 때 필요한 정보는 다음과 같다.

  • ZooKeeper Server 의 Host Address / Host IP
  • ZooKeeper Server 의 Client Access Port No

 

기본적인 유지 관리 부분

별다른 작업이 필요한 것은 아니고 다음과 같은 정보를 정리하면 된다.

  • 데이터 디렉토리 정리
  • 디버그 Log 정리

ZooKeeper는 “autopurge.snapRetainCount” 와 “autopurge.purgeInterval” 과 같은 설정을 통해서 자동으로 정리하는 기능 (Autopurge) 을 제공하고 있다.  “ZooKeeper maintenance” 를 참고하여 적절한 방침과 방법을 수립한다.

성능과 가용성에 대한 검토 사항들

  • Ensemble 을 구성하는 서버들의 대부분이 가동되면 ZooKeeper 서비스를 이용할 수 있다. 위에서도 계속 언급을 했지만 절반이 실패하더라도 구성이 가능할 수 있도록 홀 수를 유지하는 것이 중요하다. 예를 들어 짝수로 구성된 4개의 서버 중에서 2개의 서버가 실패하면 나머지 2개의 서버 중에서 1개의 서버는 리더가 되고 1개의 서버가 복제 상태가 되는데 이런 경우는 복제가 실패했을 때 대응을 할 수 없는 상태가 된다. 여기서 리더는 복제 단위가 아니기 때문에 1개 서버 만으로 복제를 운영할 수 없는 상태가 된다.
  • ZooKeeper는 오류가 발생하면 프로세스가 종료되는 Fail-Fast 정책으로 운영된다. 따라서 자동으로 복원을 하는 것이 아니기 때문에 관리자의 감독하에서 실행하는 것이 상당히 중요하다. 
  • ZooKeeper의 데이터 디렉토리는 Emsemble 에서 처리되는 zNodes 들의 정보 복사본들이 저장된다. 이 파일들은 Snapshot 파일들로 zNodes 들에서 처리된 변경들을 트랜잭션 로드로 추가하며, 때때로 Log들이 커지게 되면 모든 zNode 들의 현재 상태의 Snapshot 들을 파일 시스템에 기록하고 기존의 Log들을 대체한다.
  • ZooKeeper의 Transaction Log는 전용 장치에 존재해야 하며, 파티션으로 처리된 전용 공간으로는 충분하지 않다고 명시되어 있다. 즉 ZooKeeper는 Log를 순차적으로 기록하며, 다른 프로세스들과 탐색이 경합이 발생할 수 있는 Log 장치의 공유를 허용하지 않는 것을 원칙으로 해야 한다.
  • ZooKeeper 을 Swap이 발생할 수 있는 상황으로 관리하면 안 된다. ZooKeeper가 기능을 제대로 발휘할 수 있도록 하기 위해서는 Swap 발생을 미리 차단해 놓아야 한다. 예를 들어 ZooKeeper가 사용할 수 있는 Heap Size를 물리적인 사용 가능 메모리보다 크게 지정하면 나중에 메모리 Swap이 발생하므로 이런 설정은 피해야 한다. 이와 같은 피해야 할 부분들은 여기를 참고하면 된다.

'Apache Kafka' 카테고리의 다른 글

주키퍼 CLI  (0) 2022.01.09
아파치 주키퍼 설치 및 실행  (0) 2022.01.09
아파치 주키퍼란  (0) 2022.01.08
Confluent란  (0) 2022.01.07
UI for Apache Kafka – 카프카 모니터링 툴  (0) 2022.01.07

+ Recent posts