아파치 주키퍼란?
ZooKeeper는 분산 애플리케이션의 구성 정보를 유지.관리하고, 이름을 지정하고, 분산 동기화를 하고, 그룹 서비스를 제공하는 서비스입니다. 디렉토리 트리 구조의 데이터 모델을 사용합니다.
ZooKeeper는 표준 파일 시스템과 유사하게 구성된 계층적 공유 네임스페이스를 통해 분산 프로세스를 조정할 수 있습니다. 네임스페이스는 znodes라고 하는 데이터 레지스터로 구성되며 파일 및 디렉토리와 유사합니다. 저장용으로 설계된 일반적인 파일 시스템과 달리 ZooKeeper 데이터는 메모리에 보관됩니다.
분산 프로세스와 마찬가지로 ZooKeeper 자체도 앙상블이라는 호스트 집합을 통해 복제되도록 되어 있습니다.
ZooKeeper 서비스를 구성하는 서버는 모두 서로의 상태에 대해 알고 있어야 하므로 영구 저장소의 트랜잭션 로그 및 스냅샷과 함께 메모리 내 상태 이미지를 유지 관리합니다.
클라이언트는 단일 ZooKeeper 서버에 연결합니다. 클라이언트는 요청을 보내고, 응답을 받고, 감시 이벤트를 받고, heart bit을 보내는 TCP 연결을 유지 관리합니다. 서버에 대한 TCP 연결이 끊어지면 클라이언트는 다른 서버에 연결합니다.
ZooKeeper는 트랜잭션의 순서를 반영하는 번호로 순서를 유지합니다.
데이터 모델 및 계층적 네임스페이스
ZooKeeper에서 제공하는 네임스페이스는 표준 파일 시스템과 매우 유사합니다. 이름은 슬래시(/)로 구분된 경로 입니다. ZooKeeper의 네임스페이스에 있는 모든 노드는 경로로 식별됩니다.
계층적 네임스페이스
노드 및 임시 노드
표준 파일 시스템과 달리 ZooKeeper 네임스페이스의 각 노드는 자식뿐만 아니라 연결된 데이터를 가질 수 있습니다. ZooKeeper는 상태 정보, 구성, 위치 정보 등의 조정 데이터를 저장하도록 설계되었으므로 각 노드에 저장된 데이터는 일반적으로 바이트에서 킬로바이트로 작습니다. ZooKeeper 데이터 노드를 znode라고 합니다.
Znode는 데이터 변경, ACL 변경 및 타임스탬프에 대한 버전 번호를 포함하는 통계 구조를 유지하여 캐시 유효성 검사 및 조정된 업데이트를 허용합니다. znode의 데이터가 변경될 때마다 버전 번호가 증가합니다. 예를 들어 클라이언트가 데이터를 검색할 때마다 데이터 버전도 받습니다.
각 노드에는 누가 무엇을 할 수 있는지를 제한하는 ACL(액세스 제어 목록)이 있습니다.
ZooKeeper에는 임시 노드 개념도 있습니다. 이러한 임시 znode는 znode를 생성한 세션이 활성 상태일 떄만 존재합니다. 세션이 종료되면 znode가 삭제됩니다.
조건부 업데이트 및 감시
클라이언트는 znode에서 감시를 설정할 수 있습니다. znode가 변경되면 watch가 트리거되고 제거됩니다. watch가 트리거되면 클라이언트는 znode가 변경되었다는 패킷을 수신합니다. 클라이언트와 ZooKeeper 서버 중 하나 간의 연결이 끊어지면 클라이언트는 로컬 알림을 받습니다.
3.6.0의 새로운 기능: 클라이언트는 트리거될 때 제거되지 않고 등록된 znode 및 모든 자식 znode에 대한 변경을 재귀적으로 트리거하는 znode에 영구적이고 재귀적인 감시를 설정할 수 있습니다.
보증
- 순차 일관성 - 클라이언트의 업데이트는 전송된 순서대로 적용됩니다.
- 원자성 - 업데이트가 성공하거나 실패합니다.
- 단일 시스템 이미지 - 클라이언트는 연결하는 서버에 관계없이 동일한 서비스 보기를 볼 수 있습니다.
- 안정성 - 업데이트가 적용된 후에는 클라이언트가 업데이트를 덮어쓸 때까지 계속 유지됩니다.
- 적시성 - 시스템에 대한 클라이언트 보기는 특정 시간 범위 내에서 최신 상태로 유지되도록 보장됩니다.
Simple API
ZooKeeper는 간결한 프로그래밍 인터페이스를 제공합니다.
- create : 트리의 한 위치에 노드를 생성합니다.
- delete : 노드를 삭제
- exists : 노드가 위치에 존재하는지 테스트
- get data : 노드에서 데이터를 읽습니다.
- set data : 노드에 데이터를 씁니다.
- get children : 노드의 자식 목록을 검색합니다.
- sync : 데이터가 전파될 때까지 기다립니다.
Implementation
ZooKeeper 서비스를 구성하는 각 서버는 요청 프로세서를 제외하고 각 구성 요소를 복제합니다.
복제된 데이터베이스는 전체 데이터 트리를 포함하는 메모리 내 데이터베이스입니다. 업데이트는 복구를 위해 디스크에 기록하고 데이터 쓰기는 메모리 내 데이터베이스에 적용되기 전에 디스크에 씁니다.
모든 ZooKeeper 서버는 클라이언트에 서비스를 제공합니다. 클라이언트는 하나의 서버에 연결하여 요청을 합니다. 읽기 요청은 각 서버 데이터베이스의 로컬 복제본에서 처리됩니다. 서비스 상태를 변경하는 요청인 쓰기 요청은 agreement protoco에 의해 처리됩니다.
클라이언트의 모든 쓰기 요청은 리더로 전달됩니다. 팔로워라고 하는 나머지 ZooKeeper 서버는 리더로부터 메시지 제안을 수신하고 메시지 전달에 동의합니다. 메시징 계층은 실패 시 리더를 교체하고 팔로어를 리더와 동기화하는 작업을 처리합니다.
ZooKeeper는 맞춤형 원자 메시징 프로토콜을 사용합니다. 메시징 계층은 원자성이므로 ZooKeeper는 로컬 복제본이 절대 분기되지 않도록 보장할 수 있습니다. 리더는 쓰기 요청을 받으면 쓰기가 적용될 때 시스템의 상태를 계산하고 이를 이 새로운 상태를 캡처하는 트랜잭션으로 변환합니다.
Uses
ZooKeeper에 대한 프로그래밍 인터페이스는 간단하지만 이를 사용하여 동기화, 그룹 구성원 자격, 소유권 등과 같은 고차원 작업을 구현할 수 있습니다.
주키퍼를 단독으로 구성할 수도 있지만, 주키퍼를 클러스터로 구성하여 고가용성을 확보한 것을 주키퍼 앙상블(Zookeeper Ensemble)이라고 한다.
주키퍼 서버는 홀수로 구성하는 것을 권고하고 있기 때문에 3대로 구성하려고 합니다. 홀수로 구성하는 이유는 예를 들어서 4대로 구성을 했을 때 결함에 대한 장애 대비 기능(failover)가 3대로 구성한 것과 동일합니다.
하나의 OS에서 3개의 주키퍼를 구성합니다.
카프카 브로커에서 브로커와 토픽의 메타데이터를 저장하기 위해 주키퍼를 사용합니다.
주키퍼 설치하기
$ wget http://apache.mirror.cdnetworks.com/zookeeper/stable/apache-zookeeper-3.6.3-bin.tar.gz
$ tar xzvf apache-zookeeper-3.6.3-bin.tar.gz
$ ln -s apache-zookeeper-3.6.3-bin zookeeper
바이너리 버전(apache-zookeeper-3.5.5-bin.tar.gz)과 소스 버전(apache-zookeeper-3.5.5.tar.gz)이 있는데 바이너리 버전으로 다운로드합니다.
주키퍼는 별도의 데이터 디렉토리를 사용합니다.
이 디렉토리에는 지노드의 복사본인 스냅샷과 트랜잭션 로그들이 저장됩니다.
주키퍼의 지노드는 데이터를 저장하기 위한 공간이고 상태정보. 글로벌락, 동기화, 리더채택, 설정관리 등의 정보를 Key-Value 형태로 저장합니다.
- 지노드의 변경사항이 발생하면, 변경사항은 트랜잭션 로그에 추가
- 로그가 어느 정도 커지면, 현재 모든 지노드의 상태 스냅샷이 파일시스템에 저장
1. 주키퍼 환경설정 - single 노드
모든 설정 작업은 주키퍼 설치 디렉토리 "apache-zookeeper-3.6.3-bin" 에서 수행합니다.
1.1 zookeeper 환경설정
data 디렉토리 생성
data 디렉토리로 /zkdata 를 생성하고 log 디렉토리를 위해 /zkdatalog 디렉토리를 생성합니다. 디렉토리명 또는 파일시스템명은 사용자가 원하는 이름으로 생성합니다.
$ mkdir -p /zkdata
$ mkdir -p /zkdatalog
zoo.cfg 파일 설정
주키퍼 환경설정 sample 파일을 zoo.cfg 파일로 복사하고 내용을 수정합니다.
cp conf/zoo_sample.cfg conf/zoo.cfg
vi conf/zoo.cfg
아래와 같이 dataDir를 위에서 생성한 디렉토리명으로 수정합니다.
## zoo.cfg 파일
dataDir=/zkdata
dataLogDir=/zkdatalog
1.2 zookeeper 실행
주키퍼 서버를 standalone 모드로 실행합니다.
conf/zoo.cfg 인자를 입력하지 않아도 default로 zoo.cfg 환경파일로 주키퍼를 실행합니다.
$ bin/zkServer.sh start conf/zoo.cfg
아래와 같은 실행결과가 화면에 표시되면 정상입니다.
ZooKeeper JMX enabled by default
Using config: /apach/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
주키퍼 서버 port가 LISTEN 상태인지 확인합니다.
$ netstat -an | grep 2181
tcp6 0 0 :::2181 :::* LISTEN
1.3 zookeeper 접속
아래 명령어로 로컬 ZooKeeper 서버에 접속합니다.
bin/zkCli.sh -server 127.0.0.1:2181
아래와 같이 CONNECTED 프롬프트가 나오면 정상입니다.
Connecting to 127.0.0.1:2181
...
...
[zk: 127.0.0.1:2181(CONNECTED) 0]
혹시,
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
메시지 상태에 멈추어 있으면 엔터키를 칩니다.
zookeeper 명령 프롬프트에서 help 명령어를 입력하면 사용할 수 있는 명령어들이 표시됩니다.
[zk: 127.0.0.1:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
stat path [watch]
set path data [version]
... ...
close
connect host:port
zookeeper 명령창에서 version 을 입력하고 엔터를 치면 version 정보를 확인할 수 있습니다.
[zk: 127.0.0.1:2181(CONNECTED) 2] version
ZooKeeper CLI version: 3.6.3--6401e4ad2087061bc6b9f80dec2d69f2e3c8660a, built on 04/08/2021 16:35 GMT
ls 명령어로 zookeeper znode를 조회합니다.
[zk: 127.0.0.1:2181(CONNECTED) 2] ls /
[zookeeper]
[zk: 127.0.0.1:2181(CONNECTED) 2] ls /zookeeper
[config, quota]
quit명령어로 zookeeper 명령창을 종료합니다.
[zk: 127.0.0.1:2181(CONNECTED) 2] quit
1.4 zookeeper 서비스 종료
아래 명령어로 ZooKeeper 서비스를 종료합니다.
bin/zkServer.sh stop conf/zoo.cfg
1.5. Zookeeper 시스템 서비스 파일 생성
systemd 서비스를 이용해서 시작/종료를 할 수 있도록 서비스 파일을 생성합니다. 단, WSL 에서는 등록이 안됩니다(There is lack of support in WSL for systemd).
아래 명령어로 시스템 서비스 파일을 편집합니다.
sudo vi /etc/systemd/system/zk.service
아래 내용을 입력합니다.
[Unit]
Description=Zookeeper Daemon
Documentation=http://zookeeper.apache.org
Requires=network.target
After=network.target
[Service]
Type=forking
WorkingDirectory=/opt/zookeeper
User=zk
Group=zk
ExecStart=/opt/zookeeper/bin/zkServer.sh start /opt/zookeeper/conf/zoo.cfg
ExecStop=/opt/zookeeper/bin/zkServer.sh stop /opt/zookeeper/conf/zoo.cfg
ExecReload=/opt/zookeeper/bin/zkServer.sh restart /opt/zookeeper/conf/zoo.cfg
TimeoutSec=30
Restart=on-failure
[Install]
WantedBy=default.target
이제 다음 명령어로 ZooKeeper를 실행해 봅니다.
sudo systemctl start zk
아래 명령으로 정상적으로 실행 중인지 확인 합니다.
sudo systemctl status zk
정상적으로 실행이 되면, 시스템이 부팅 시에도 자동으로 실행되도록 아래와 같이 등록해 줍니다.
sudo systemctl enable zk
다음 명령으로 서비스를 종료합니다.
sudo systemctl stop zk
2. 주키퍼 환경설정 - 멀티노드
2.1 zookeeper 환경설정
data 디렉토리 생성
$ mkdir -p /zkdata1
$ mkdir -p /zkdatalog1
$ mkdir -p /zkdata2
$ mkdir -p /zkdatalog2
$ mkdir -p /zkdata3
$ mkdir -p /zkdatalog3
멀티 노드 설정입니다. ZooKeeper 는 홀수대의 노드로 구성을 해야 하므로, 3대 혹은 5대와 같이 구성을 합니다. 여기서는 3대 구성을 설명합니다.아래 명령어로 설정파일을 편집합니다.
본 문서는 3개의 zookeeper 서버 구성을 위해 각가의 디렉토리를 만듭니다.
모든 설정 작업은 주키퍼 설치 디렉토리 "apache-zookeeper-3.6.3-bin" 에서 수행합니다.
$ cp conf/zoo_sample.cfg conf/zoo1.cfg
$ cp conf/zoo_sample.cfg conf/zoo2.cfg
$ cp conf/zoo_sample.cfg conf/zoo3.cfg
vi conf/zoo1.cfg
아래 내용을 입력합니다. zoo1.cfg 입니다. 다른 2개의 cfg 파일도 동일하게 작성합니다. 단, dataDir, dataLogDir 및 clientPort는 각 서버에 맞게 작성합니다. 본 문서에서는 한 대의 서버에 3개의 zookeeper 서버를 구성하는 예이므로 port 및 directory 경로를 상이하게 설정했습니다. 물리적으로 분리된 서버를 별도로 구성할 경우 동일한 경로와 port로 설정할 수 있습니다.
## zoo1.cfg 파일
## datdaDir 은 각각의 서버에 맞게 설정하는데
dataDir=/zkdata1
dataLogDir=/zkdatalog1
clientPort=2181
server.1=localhost:2888:3888
server.2=localhost:2889:3889
server.3=localhost:2890:3890
- dataDir : 주키퍼의 스냅샷이 저장되는 경로
- dataLogDir : 주키퍼의 트랜잭션가 저장되는경로
- clientPort : Client 접속 포트
- server.myid : 주키퍼 앙상블 구성을 위한 서버 설정, server.myid 형식으로 사용. 2888 : 서버 노드끼리 통신을 위해 사용, 3888 리더 선출을 위해 사용
zoo2.cfg 파일 예제입니다.
## zoo2.cfg 파일
## datdaDir 은 각각의 서버에 맞게 설정하는데
dataDir=/zkdata2
dataLogDir=/zkdatalog2
clientPort=2182
server.1=localhost:2888:3888
server.2=localhost:2889:3889
server.3=localhost:2890:3890
zoo3.cfg 파일 예제입니다.
## zoo3.cfg 파일
## datdaDir 은 각각의 서버에 맞게 설정하는데
dataDir=/zkdata3
dataLogDir=/zkdatalog3
clientPort=2183
server.1=localhost:2888:3888
server.2=localhost:2889:3889
server.3=localhost:2890:3890
설정이 완료되면 각각의 노드의 dataDir 디렉토리에 myid 라는 파일을 생성하고 각각의 파일에 1, 2, 3 과 같이 입력해 줍니다.
아래와 같이 각각의 노드에 따라 숫자를 입력하고 저장합니다.
1번째 노드
sudo vi /zkdata1/myid
1
2번째 노드
sudo vi /zkdata2/myid
2
3번째 노드
sudo vi /zkdata3/myid
3
2.2 zookeeper 실행
주키퍼 서버를 앙상블(멀티노드) 모드로 실행합니다.
$ bin/zkServer.sh start conf/zoo1.cfg
$ bin/zkServer.sh start conf/zoo2.cfg
$ bin/zkServer.sh start conf/zoo3.cfg
아래와 같은 실행결과가 화면에 표시되면 정상입니다.
$ bin/zkServer.sh start conf/zoo1.cfg
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: conf/zoo1.cfg
Starting zookeeper ... STARTED
$ bin/zkServer.sh start conf/zoo2.cfg
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: conf/zoo2.cfg
Starting zookeeper ... STARTED
r$ bin/zkServer.sh start conf/zoo3.cfg
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: conf/zoo3.cfg
Starting zookeeper ... STARTED
주키퍼 서버 port가 LISTEN 상태인지 확인합니다.
$ netstat -an | egrep "2181|2182|2183"
tcp6 0 0 :::2181 :::* LISTEN
tcp6 0 0 :::2182 :::* LISTEN
tcp6 0 0 :::2183 :::* LISTEN
2.3 zookeeper 접속
아래 명령어로 로컬 ZooKeeper 서버에 접속합니다.
bin/zkCli.sh -server 127.0.0.1:2181
아래와 같이 CONNECTED 프롬프트가 나오면 정상입니다.
Connecting to 127.0.0.1:2181
...
...
[zk: 127.0.0.1:2181(CONNECTED) 0]
혹시,
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
메시지 상태에 멈추어 있으면 엔터키를 칩니다.
zookeeper 명령 프롬프트에서 help 명령어를 입력하면 사용할 수 있는 명령어들이 표시됩니다.
[zk: 127.0.0.1:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
stat path [watch]
set path data [version]
... ...
close
connect host:port
노드 1에서 아래 명령을 입력합니다.
[zkshell:] create /zk_znode_1 sample_data
노드 1에서 다음 명령으로 생성된 내용을 확인해 봅니다.
[zkshell: ] get /zk_znode_1
다른 터미널 창에서 노드 2에서 접속하여 노드 1에서 생성한 데이터를 조회합니다.
$ bin/zkCli.sh -server 127.0.0.1:2182
[zkshell: ] get /zk_znode_1
sample_data
노드 1, 노드 2 양쪽 모두 동일한 결과가 나와서 동기화가 되는 것을 확인하면 정상입니다.
아래 명령으로 znode를 삭제해 줍니다.
[zkshell: ] delete /zk_znode_1
quit명령어로 zookeeper 명령창을 종료합니다.
[zk: 127.0.0.1:2181(CONNECTED) 2] quit
* 참고로, 아파치 broker 서버가 기동되면 zookeeper에서 생성한 zookeeper znode를 제외한 많은 수의 znode들이 생성된다. [admin, brokers, cluster, config, consumers, controller, controller_epoch, feature, isr_change_notification, latest_producer_id_block, log_dir_event_notification, zookeeper]
2.4 zookeeper 서비스 종료
아래 명령어로 ZooKeeper 서비스를 종료합니다.
bin/zkServer.sh stop conf/zoo1.cfg
bin/zkServer.sh stop conf/zoo2.cfg
bin/zkServer.sh stop conf/zoo3.cfg
'Apache Kafka' 카테고리의 다른 글
아파치 주키퍼 설치 및 실행 (0) | 2022.01.09 |
---|---|
주키퍼 Cluster 구성 (0) | 2022.01.08 |
Confluent란 (0) | 2022.01.07 |
UI for Apache Kafka – 카프카 모니터링 툴 (0) | 2022.01.07 |
카프카 클러스터 모니터링 및 관리 툴 비교 (0) | 2022.01.07 |