ZooKeeper 앙상블 앞에 HAProxy 를 두어 클라이언트가 고정 엔드포인트 하나로 접속하게 하는 구성이다. ZooKeeper 는 세션 기반 프로토콜이라 HTTP 처럼 단순 분산하면 문제가 생기므로 TCP 모드, 상태 확인 헬스체크, 소스 고정이 필수다. 클라이언트 라이브러리가 접속 문자열의 앙상블 목록으로 이미 페일오버와 분산을 하므로, HAProxy 는 방화벽·NAT 경계, Kubernetes 외부 노출, 클라이언트 설정 변경 불가 같은 "고정 엔드포인트가 필요한 경우" 에만 의미가 있다.
defaults
mode tcp
timeout connect 5s
timeout client 1h
timeout server 1h
option tcpka
frontend zk_in
bind :2181
default_backend zk_nodes
backend zk_nodes
balance source
hash-type consistent
option tcp-check
tcp-check connect
tcp-check send mntr\n
tcp-check expect rstring zk_server_state\s+(leader|follower)
server zk1 zk1.internal.example:2181 check inter 3s fall 2 rise 3
server zk2 zk2.internal.example:2181 check inter 3s fall 2 rise 3
server zk3 zk3.internal.example:2181 check inter 3s fall 2 rise 3
클라이언트 접속 문자열은 앙상블 목록 대신 HAProxy 주소 하나가 되고 chroot 접미사는 그대로 붙인다.
zk1:2181,zk2:2181,zk3:2181/myapp → zk-lb.internal.example:2181/myapp
balance source 는 같은 클라이언트가 계속 같은 노드로 가게 해 세션 재수립을 줄인다. 세션은 앙상블에 복제되므로 노드가 바뀌어도 세션 타임아웃 안이면 재개되지만, 클라이언트가 자기보다 zxid 가 뒤처진 노드에 붙으면 연결이 거부되므로 불필요한 이동을 줄이는 편이 좋다. 뒤쪽 노드가 죽으면 클라이언트 연결이 끊기고 같은 주소로 재접속하며, 헬스체크에서 빠진 노드는 제외돼 살아 있는 노드로 붙는다.
헬스체크는 ruok 만으로 부족하다. 쿼럼에서 이탈한 LOOKING 상태에서도 imok 이 나올 수 있어 mntr 로 leader/follower 상태를 확인한다. ZooKeeper 3.5 이상은 4lw.commands.whitelist=ruok,mntr,srvr 설정이 필요하다.
maxClientCnxns(기본 60) 에 쉽게 걸린다. 값을 크게 잡거나 0 으로 둔다. ZooKeeper 는 PROXY 프로토콜을 지원하지 않아 원본 IP 기반 ACL·감사도 무력화된다.zk-lb1:2181,zk-lb2:2181/myapp) 클라이언트 재시도 로직을 살린다.