使用Docker快速搭建ZooKeeper叢集
前言
之前,已經使用 Docker 安裝 zookeeper,但是這只是安裝單機的。現在,我們要用 docker-compose 來編排叢集容器。
因為一個一個地啟動 ZK 太麻煩了, 所以為了方便起見, 我直接使用 docker-compose 來啟動 ZK 叢集。
1. yml 檔案
首先建立一個名為 docker-compose.yml 的檔案, 其內容如下:
version: '3' services: zoo1: image: zookeeper restart: always container_name: zoo1 ports: - "2181:2181" environment: ZOO_MY_ID: 1 ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2182 server.3=zoo3:2888:3888;2183 server.4=zoo4:2888:3888;2184 zoo2: image: zookeeper restart: always container_name: zoo2 ports: - "2182:2181" environment: ZOO_MY_ID: 2 ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2182 server.3=zoo3:2888:3888;2183 server.4=zoo4:2888:3888;2184 zoo3: image: zookeeper restart: always container_name: zoo3 ports: - "2183:2181" environment: ZOO_MY_ID: 3 ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2182 server.3=zoo3:2888:3888;2183 server.4=zoo4:2888:3888;2184 zoo4: image: zookeeper restart: always container_name: zoo4 ports: - "2184:2181" environment: ZOO_MY_ID: 4 ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2182 server.3=zoo3:2888:3888;2183 server.4=zoo4:2888:3888;2184
1、version: 版本號
- 一般來說,和你的 Docker Engine 的版本相匹配;
- 因為我的 Docker Engine 的版本是 20.10.5,因此我選擇 3;
2、image: 映象版本
- 預設使用的是latest版本,可預設;
3、ZOO_MY_ID(環境變數):
- 該id在叢集中必須是唯一的,並且其值應介於1和255之間;
- 請注意,如果使用已包含 myid 檔案的 /data 目錄啟動容器,則此變數將不會產生任何影響。相當於你在zoo.cfg中指定的dataDir目錄中建立檔案myid,並且檔案的內容就是範圍為1到255的整數;
4、ZOO_SERVERS(環境變數):
- 此變數允許您指定Zookeeper叢集的計算機列表;
- 每個條目都應該這樣指定:
server.id=<address1>:<port1>:<port2>[:role];[<client port address>:]<client port>
id
是一個數字,表示叢集中的伺服器ID;address1
表示這個伺服器的ip地址;- 叢集通訊端⼝:
port1
表示這個伺服器與叢集中的 Leader 伺服器交換資訊的埠; - 叢集選舉端⼝:
port2
表示萬一叢集中的 Leader 伺服器掛了,需要一個埠來重新進行選舉,選出一個新的 Leader,而這個埠就是用來執行選舉時伺服器相互通訊的埠; role
: 預設是 participant,即參與過半機制的⻆⾊,選舉,事務請求過半提交,還有⼀個是observer, 觀察者,不參與選舉以及過半機制。client port address
是可選的,如果未指定,則預設為 “0.0.0.0” ;client port
位於分號的右側。從3.5.0開始,zoo.cfg中不再使用clientPort和clientPortAddress配置引數。作為替代,client port
用來表示客戶端連線 Zookeeper 伺服器的埠,Zookeeper 會監聽這個
埠,接受客戶端的訪問請求。
- 請注意,如果使用已包含zoo.cfg檔案的/conf目錄啟動容器,則此變數不會產生任何影響。換句話說,zoo.cfg檔案中包含叢集的計算機列表,此時該環境變數不生效。
2. 啟動叢集
開啟命令列提示符,進入 docker-compose.yml 所在的目錄,接著執行
docker-compose -f docker-compose.yml up
最後檢查一下執行情況:
如圖所示,容器 zoo1,zoo2,zoo3,zoo4 都在執行中。
3. 檢測叢集狀態
檢測叢集狀態的命令是 zkServer.sh status /conf/zoo.cfg
。使用該命令的前提是要先登入容器中,可以使用 docker exec -it zoo1 bash
登入 zoo1 中。
zoo1 在本次實驗中角色是 follower:
類似地,zoo2 的角色也是 follower:
zoo3 的角色也是 follower:
zoo4 的角色是 leader:
4. ZooKeeper 叢集角色介紹
Zookeeper 叢集模式⼀共有三種類型的⻆⾊:
角色 | 職責 |
---|---|
Leader | 處理所有的事務請求(寫請求),可以處理讀請求,叢集中只能有⼀個Leader |
Follower | 只能處理讀請求,同時作為 Leader的候選節點,即如果Leader宕機,Follower節點要參與到新的Leader選舉中,有可能成為新的Leader節點。 |
Observer | 只能處理讀請求。不能參與選舉 |
5. 不宕機動態擴容和縮容
ZooKeeper 支援通過修改 zoo.cfg 並重啟來改變ZooKeeper叢集中的伺服器 閱讀,但是這種方式,不是很方便,上線一臺伺服器或者下線一臺伺服器需要對所有的伺服器進行重啟。
ZooKeeper 3.5.0 提供了⽀持動態擴容/縮容的 新特性。但是通過客戶端 API可以變更服務端叢集狀態是件很危險的事情,所以在ZooKeeper 3.5.3 版本要⽤動態配置,需要開啟超級管理員身份驗證模式 ACLs。
關於ZooKeeper的ACL許可權控制,可以 點選此處閱讀
Step1: 我為 super:qwer1234
生成了 digest 為 super:YjJhp1/a1jnzeGTDN7nAUxFcep8=
;
Step2: docker-compose -f docker-compose.yml down
停掉並刪除原來的容器;
Step3: 修改 docker-compose.yml 的內容:
version: '3'
services:
zoo1:
image: zookeeper
restart: always
container_name: zoo1
ports:
- "2181:2181"
environment:
ZOO_MY_ID: 1
ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181 server.4=zoo4:2888:3888;2181
ZOO_CFG_EXTRA: "reconfigEnabled=true"
JVMFLAGS: "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:YjJhp1/a1jnzeGTDN7nAUxFcep8="
zoo2:
image: zookeeper
restart: always
container_name: zoo2
ports:
- "2182:2181"
environment:
ZOO_MY_ID: 2
ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181 server.4=zoo4:2888:3888;2181
ZOO_CFG_EXTRA: "reconfigEnabled=true"
JVMFLAGS: "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:YjJhp1/a1jnzeGTDN7nAUxFcep8="
zoo3:
image: zookeeper
restart: always
container_name: zoo3
ports:
- "2183:2181"
environment:
ZOO_MY_ID: 3
ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181 server.4=zoo4:2888:3888;2181
ZOO_CFG_EXTRA: "reconfigEnabled=true"
JVMFLAGS: "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:YjJhp1/a1jnzeGTDN7nAUxFcep8="
zoo4:
image: zookeeper
restart: always
container_name: zoo4
ports:
- "2184:2181"
environment:
ZOO_MY_ID: 4
ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181 server.4=zoo4:2888:3888;2181
ZOO_CFG_EXTRA: "reconfigEnabled=true"
JVMFLAGS: "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:YjJhp1/a1jnzeGTDN7nAUxFcep8="
ZOO_CFG_EXTRA: "reconfigEnabled=true"
開啟了預設關閉的客戶端 reconfig APIJVMFLAGS: "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:YjJhp1/a1jnzeGTDN7nAUxFcep8="
設定了超級管理員賬號為super
,明文密碼為qwer1234
Step4: 重啟叢集
在 docker-compose.yml
所在目錄執行以下命令:
docker-compose -f docker-compose.yml up
Step5: 登入客戶端
接下來就是使用ZooKeeper客戶端的reconfig命令了。
5.1 檢視當前叢集資訊
get /zookeeper/config
執行結果如下:
[zk: localhost:2181(CONNECTED) 0] get /zookeeper/config
server.1=zoo1:2888:3888:participant;0.0.0.0:2181
server.2=zoo2:2888:3888:participant;0.0.0.0:2181
server.3=zoo3:2888:3888:participant;0.0.0.0:2181
server.4=zoo4:2888:3888:participant;0.0.0.0:2181
version=0
5.2 擴縮容前的認證超級管理員身份
addauth digest super:qwer1234
5.3 移除叢集中的一臺伺服器
reconfig -remove <id>
比如說,從叢集中移除ID為3的ZooKeeper服務:
[zk: localhost:2181(CONNECTED) 2] reconfig -remove 3
Committed new configuration:
server.1=zoo1:2888:3888:participant;0.0.0.0:2181
server.2=zoo2:2888:3888:participant;0.0.0.0:2181
server.4=zoo4:2888:3888:participant;0.0.0.0:2181
version=100000003
5.4 為叢集新增一臺伺服器
reconfig -add server.id=<address1>:<port1>:<port2>[:role];[<client port address>:]<client port>
比如說,把剛才移除的伺服器再添加回來:
[zk: localhost:2181(CONNECTED) 3] reconfig -add server.3=zoo3:2888:3888;2181
Committed new configuration:
server.1=zoo1:2888:3888:participant;0.0.0.0:2181
server.2=zoo2:2888:3888:participant;0.0.0.0:2181
server.3=zoo3:2888:3888:participant;0.0.0.0:2181
server.4=zoo4:2888:3888:participant;0.0.0.0:2181
version=100000004
6. 過半機制
participant ⻆⾊能夠形成叢集(過半機制),如果叢集內的 participant 有一半及以上都宕機了,此時客戶端將不再可用。
6.1 半數伺服器宕機
比如說,我停掉了 zoo3 和 zoo4:
此時,沒有停掉的服務,也啟動不了客戶端:
6.2 半數以上伺服器可用
然後,我再重啟了 zoo3:
稍等一會之後,叢集再次變得可用了。
問題記錄
Client port not found in server configs
參考官網 ZOO_SERVERS 的配置,以zoo1為例: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888 server.4=zoo4:2888:3888
沒有加上埠號,我實踐後遇上了問題。
☆ 問題具體資訊如下:
出現如圖所示的錯誤,找不到客戶端埠號。
★ 解決方案:我立即停止和刪除容器、網路、卷:
docker-compose -f docker-compose.yml down
然後,改成我上面給出的 docker-compose.yml 檔案內容,然後用 docker-compose -f docker-compose.yml up
重啟叢集伺服器。
KeeperErrorCode = Reconfig is disabled
從3.5.0開始到3.5.3之前,沒有辦法禁用動態重新配置功能。我們希望提供禁用重新配置功能的選項,因為啟用重新配置後,我們存在一個安全問題,即惡意參與者可以對ZooKeeper集合的配置進行任意更改,包括向集合中新增受損伺服器。我們傾向於讓使用者自行決定是否啟用它,並確保適當的安全措施到位。因此,在3.5.3中引入了reconfigEnabled configuration選項,以便可以完全禁用重新配置功能,並且通過reconfig API重新配置叢集的任何嘗試(無論是否具有身份驗證)在預設情況下都將失敗,除非reconfigEnabled設定為true。
要將選項設定為true,配置檔案(zoo.cfg)應包含:
reconfigEnabled=true
Insufficient permission
☆ 問題具體報錯資訊如下:
★ 解決方案:addauth digest super:qwer1234
賦予超級管理員許可權
[zk: localhost:2181(CONNECTED) 0] reconfig -remove 3
Insufficient permission :
[zk: localhost:2181(CONNECTED) 1] addauth digest super:qwer1234
[zk: localhost:2181(CONNECTED) 2] reconfig -remove 3
Committed new configuration:
server.1=zoo1:2888:3888:participant;0.0.0.0:2181
server.2=zoo2:2888:3888:participant;0.0.0.0:2181
server.4=zoo4:2888:3888:participant;0.0.0.0:2181
version=100000003