使用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 API
  • JVMFLAGS: "-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

參考文檔

Docker ZooKeeper

docker-compose

Zookeeper之 兩種選舉制度|為什么需要過半投票機制?

理解Zookeeper(九):Zookeeper擴容和縮容


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM