超簡便!不停機搞定數百個Zookeeper例項到K8S的遷移

最近,我們在不停機的情況下將數百個 ZooKeeper 例項遷移到了 Kubernetes。我們利用了強大的 Kubernetes 特性(例如端點)簡化了遷移過程,那些想要跟我們一樣進行 Zookeeper 遷移的人可以在這篇文章裡找到答案。文章的末尾列出了進行遷移所需的網路條件。

一、傳統的ZooKeeper遷移方法

ZooKeeper 是很多分散式系統的基礎,它為這些系統提供了一個強大的平臺,讓它們可以聚在一起形成叢集。它提供了一種比較基礎的方法來形成叢集:每個伺服器例項都有一個配置檔案,檔案裡列出了叢集成員的主機名和數字 ID,所有的伺服器都有相同的叢集成員列表,如下所示:

server.1=host1:2888:3888

server.2=host2:2888:3888

server.3=host3:2888:3888

每臺伺服器都有一個叫作 myid 的檔案,用來指明它在列表中對應的是哪個數字 ID。

叢集可以隨意新增和移除伺服器,只要沒有違反這個關鍵規則:每臺伺服器必須能夠與配置檔案中列出的仲裁伺服器通訊。傳統的 ZooKeeper 伺服器遷移步驟主要包括:

啟動一臺新主機,在伺服器列表配置中加入“server.4=host:4…”;

更新已有主機上的配置檔案,新增新的伺服器條目,或刪除已退役的主機;

滾動重啟舊主機(3.4x 版本分支不提供動態伺服器配置功能);

更新客戶端的連線串。

這種方法的缺點是需要修改大量的配置檔案並進行滾動重啟,這種方式可能無法進行可靠的自動化。在將 ZooKeeper 遷移到 Kubernetes 之前,我們也考慮過這種方法,但後來找到了一種更簡單的方法。這種方法更為安全,因為根據我們的經驗,每一次新的首領選舉都存在一個小風險,就是有可能會讓依賴它們的系統崩潰。

二、新的遷移方法

我們將已有的 ZooKeeper 伺服器包裝成 Kubernetes 服務,然後使用相同的 ZooKeeper ID 進行從伺服器到 Pod 的一對一替換。這隻需要一次滾動重啟就可以重新配置現有的 ZooKeeper 例項,然後逐一關閉伺服器。不過,我們不打算深入討論如何為 ZooKeeper 配置 Kubernetes 拓撲,也不打算深入討論底層的狀態就緒檢查機制,因為有很多方法可以實現這些操作。

我們將分五個步驟進行遷移:

確保為 ZooKeeper 叢集的遷移做好準備;

在 Kubernetes 中建立 ClusterIP 服務,將 Zookeeper 包裝成服務;

修改 ZooKeeper 客戶端,讓它們連線到 ClusterIP 服務;

配置 ZooKeeper 伺服器例項,讓它們可以基於 ClusterIP 服務地址執行點對點事務;

透過 Kubernetes Pod 執行 ZooKeeper 例項。

對於下面的每一個步驟,我們都將提供一個基礎設施拓撲關係圖。為了便於理解,這些圖只包含兩個 ZooKeeper 例項(在現實當中一般不會建立少於三個節點的叢集)。

1、準備好先決條件

我們從一個可執行的 ZooKeeper 叢集開始,確保主機上的服務能夠與 Kubernetes 叢集通訊。文末介紹了幾種方法。

圖 1:初始狀態,一個包含兩個例項的 ZooKeeper 叢集和一些客戶端

2、建立ClusterIP服務

為每個 ZooKeeper 伺服器建立一個具有匹配端點的 ClusterIP 服務,可以讓客戶端埠(2181)和叢集內部埠(2888、3888)透過。完成之後,就可以透過這些服務主機名連線到 ZooKeeper 叢集。

Kubernetes ClusterIP 服務在這個時候很有用,因為它們提供了可以作為後端 Pod 負載均衡器的靜態 IP 地址。我們用它們進行從服務到 Pod 的一對一對映,相當於為每個 Pod 提供了一個靜態的 IP 地址。

圖 2:可以透過 ClusterIP 服務訪問我們的叢集(ZooKeeper 仍然執行在物理硬體上)

3、重新配置客戶端

在可以透過 Kubernetes ClusterIP 服務連線到 ZooKeeper 叢集之後,接下來就可以重新配置客戶端了。如果你在 ZooKeeper 連線串中使用了 CNAME 記錄,那麼請修改 DNS 記錄。

如果客戶端在連線失敗時不會重新解析 DNS 條目,那麼就重新啟動客戶端。如果沒有使用 CNAME 記錄,那麼就需要使用新的連線串,並重新啟動客戶端。在這個時候,新舊連線串都可以使用。

圖 3:客戶端現在透過 ClusterIP 服務例項與 ZooKeeper 叢集通訊

4、重新配置ZooKeeper例項

接下來,我們將讓 ZooKeeper 伺服器透過 ClusterIP 服務進行點對點通訊。為此,我們將結合 ClusterIP 服務的地址來修改配置檔案。這裡還需要配置 zk_quorum_listen_all_ips 標誌,如果沒有這個,ZooKeeper 例項將無法成功繫結到主機介面上不存在的 IP 地址,因為它是一個 Kube 服務 IP。

server.1=zk1-kube-svc-0:2888:3888

server.2=zk2-kube-svc-1:2888:3888

server.3=zk3-kube-svc-2:2888:3888

zk_quorum_listen_all_ips: true

滾動重新啟動這些主機,後面就可以開始準備用 Pod 替換主機了。

圖 4:ZooKeeper 例項現在透過 ClusterIP 服務與其他例項通訊

5、使用Pod替代ZooKeeper主機

我們將進行以下這些步驟,每次操作一臺伺服器:

選擇一臺 ZooKeeper 伺服器及其相應的 ClusterIP 服務;

關閉伺服器上的 ZooKeeper 程序;

使用與被關閉的 ZooKeeper 具有相同伺服器列表配置和 myid 檔案的 Pod;

等待,直到 Pod 中的 ZooKeeper 啟動,並與其他 ZooKeeper 節點的資料同步。

就這樣,ZooKeeper 叢集現在執行在 Kubernetes 中,並帶有之前所有的資料。

圖 5:經過替換後的叢集。ZK1 執行在一個 Pod 中,而 ZK2 不需要知道發生了什麼

6、網路先決條件

要順利完成這些步驟,需要確保一些網路設定符合條件。你需要確保:

可以從所有需要連線到 ZooKeeper 的伺服器重新路由 Kubernetes Pod 的 IP 地址;

所有連線到 ZooKeeper 的伺服器必須能夠解析 Kubernetes 服務主機名;

所有需要連線到 ZooKeeper 的伺服器必須執行 kube-proxy,讓它們能夠訪問 ClusterIP 服務。

這些可以通過幾種方式來實現,我們使用了一個內部網路外掛。

類似於 Lyft 的外掛:
https://github.com/aws/amazon-vpc-cni-k8s

或者 AWS 外掛:
https://github.com/lyft/cni-ipvlan-vpc-k8s

可以直接將 AWS VPC IP 地址分配給 Pod,而不是使用虛擬疊加網路,所以可以從任意例項重新路由 Pod 的 IP。疊加網路(如 flannel)也是可以的,只要所有的伺服器都可以連線到疊加網路。

>>>>

版權宣告:本文源自 網路, 於,由 楠木軒 整理釋出,共 3018 字。

轉載請註明: 超簡便!不停機搞定數百個Zookeeper例項到K8S的遷移 - 楠木軒