跨區域、Kubernetes叢集執行資料庫實踐指南

語言: CN / TW / HK

譯者 | 康少京

策劃 | 雲昭

在眾多NoSQL儲存中,Cassandra 是廣受企業和開發者歡迎的選擇之一。它使用AmazonDynamo引入的架構方面的特性來支援Big Table 資料模型,優勢非常明顯:高度可擴充套件性和高度可用性、沒有單點故障 NoSQL 列族實現、非常高的寫入吞吐量和良好的讀取吞吐量、二級索引支援搜尋可調節的一致性和對複製的支援靈活的模式等。除此之外,它還實現了一個非常棘手的 Kubernetes 叢集中執行資料庫(或其他應用程式)的難題,這裡供大家參考。  全球應用程式需要一個與它們服務的使用者一樣分散式的資料層,Apache Cassandra已經很好的做到了這一點,目前為蘋果、Netflix和索尼等公司處理資料需求。傳統上,分散式應用程式的資料層管理,由專門的團隊來管理數千個節點的部署和操作(包括本地節點和雲中的節點)。

為了減輕DevOps團隊的大部分負擔,我們利用Kubernetes(K8s)提供的公共控制區域,在K8ssandra中開發了許多這樣的實踐和模式。不過,有一個問題是,如果沒有適當的注意和預先規劃,跨多個區域或K8s叢集執行資料庫(或任何應用程式)是很棘手的。

在這裡向您展示下是如何做到這一點的,我們先看看在一個單獨的K8s叢集上執行的單個區域K8ssandra部署。它是由六個Cassandra節點組成,分佈在該區域內的三個可用性區域中,每個可用性區域中有兩個Cassandra節點。在本例中,我們將使用谷歌雲平臺(GCP)區域名稱。然而,這裡的例子同樣適用於其他雲,甚至是線上雲。

這就是我們現在的處境:

雲資料庫的現有部署

目標是建立兩個區域,每個區域都有一個 Cassandra 資料中心。 在我們這裡的雲管理 K8s 部署中,這就轉化為兩個K8s叢集——每個叢集都有一個單獨的控制平面,但使用一個公共的虛擬私有云 (VPC) 網路。 通過 Cassandra 叢集擴充套件到多個數據中心,我們可以在區域中斷的情況下獲得冗餘,並且在本地訪問資料的情況下改善客戶端應用程式的響應時間和延遲。

這就是我們的目標:擁有兩個區域,每個區域都有自己的 Cassandra 資料中心。

表面上看,我們似乎可以通過簡單地啟動另一個部署相同 K8s YAML 的 K8s 叢集來實現這一點。然後對可用區名稱新增一些調整,我們就可以完成了,對吧?最終,這些資源的形狀非常相似,都是 K8s 物件。那麼,這不應該有效嗎?也許。根據您的環境,這種方法可能會起作用。

如果沒有使用完全分散式資料庫部署,會避免很多問題。但不幸的是,事情很少那麼簡單。即使其中一些障礙很容易清除,還有許多其他無害的事情可能會出錯並導致降級狀態。您選擇的雲提供商、K8s 發行版、命令列標誌,是的,甚至是 DNS——這些都可能導致您進入一條黑暗深淵。所以,我們來探討一些可能遇到的最常見問題來避免這種情況。

常見障礙

即使您的某些部署一開始起來執行得很好,但當您發展到多雲環境、升級到另一個 K8s 版本或開始使用不同的發行版和免費工具時,您可能會遇到一兩個障礙。當涉及到分散式資料庫時,它有更多的底層功能。瞭解 K8s是如何在一系列硬體中執行容器的,將有助於開發高階解決方案--最終它將滿足您的確切需求。

Cassandra 節點需要唯一 IP 地址

您可能遇到的第一個障礙涉及基本網路。回到我們的第一個叢集,讓我們看一下所涉及的網路層。

在下面顯示的 VPC 中,我們有一個無分類域間路由 (CIDR) 範圍,代表 K8s工作例項的地址。在 K8s 叢集範圍內,有一個單獨的地址空間,用於操作 pods 和容器執行。Pod 是共享了某些資源的容器集合,例如儲存、網路和程序空間。  在某些雲環境中,這些子網被繫結到特定的可用區域。因此,K8s工作器所啟動的每個子網可能都有一個CIDR範圍。 VPC 中可能還有其他虛擬機器,但在本例中,我們將堅持使用 K8s 作為唯一租戶。

具有K8s層的VPC使用的CIDR範圍

在我們的例子中,有 10.100.x.x 用於節點,10.200.x.x 用於 K8s 級別。 每個K8s工作者都會獲得10.200.x.x 的一部分,在該單個例項上執行Pod 的CIDR範圍。

回想一下我們的目標結構,如果兩個叢集使用相同或重疊的CIDR地址範圍會發生什麼? 當你第一次接觸網路時,您可能還記得這些錯誤資訊:

嘗試連線兩個網路時的常見錯誤訊息

K8s 的錯誤看起來不像這樣。不會彈出叢集無法有效溝通的警告。

如果您有一個具有 IP 空間的叢集,而另一個叢集有相同的IP空間或重疊的位置,那麼每個叢集如何知道特定資料包何時需要離開自己的地址空間,並且通過 VPC 網路路由到另一個叢集,然後進入該叢集的網路?

正常情況下,這裡沒有任何提示。有一些方法可以解決這個問題;但從更高的層面來看,如果你有重疊,那就是自找麻煩。這裡的重點是,您需要了解每個叢集的地址空間,然後仔細規劃這些 IP 的分配和使用。這允許 Linux 核心(K8s 路由發生的地方)和 VPC 網路層根據需要轉發和路由資料包。

但是,如果您沒有足夠的 IP怎麼辦?在某些情況下,您不能給每 pod提供自己的 IP 地址。因此,在這種情況下,您需要退後一步,確定哪些服務絕對必須具有唯一地址,以及哪些服務可以在同一地址空間中一起執行。例如,如果您的資料庫需要能夠與每個其他pod通訊,那麼它可能需要自己的唯一地址。但是,如果在東海岸和西海岸的應用程式層只是與他們的本地資料層通訊,它們可以擁有自己的專用 K8s 叢集,地址範圍相同,避免衝突。

扁平化網路

在我們的參考部署中,我們將 K8s 叢集中的非重疊範圍專用於基礎設施層,這些基礎設施必須是唯一的,並且服務不會通訊的重疊 CIDR 範圍。最終,我們在這裡所做的是扁平化網路。

有了不重疊的 IP 範圍,現在可以繼續將資料包路由到每個叢集中的 pod。在上圖中,您可以看到西海岸為 10.100,東海岸為 10.150,K8s pod 接收來自這些範圍的 IP。K8s 叢集有自己的 IP 空間,200 對 250,並且 pod 像以前一樣被分割。

如何處理 Cassandra 資料中心之間的路由

我們有一堆 IP 地址,並且我們對這些地址具有唯一性。現在,我們如何處理這些資料的路由以及所有這些的通訊和發現?發往叢集 A 的資料包無法知道它們需要如何路由到叢集 B。當我們嘗試跨叢集邊界傳送資料包時,本地Linux網路堆疊會發現這不是該主機或本地K8s群集內的任何主機的本地資料包,然後將資料包轉發到 VPC 網路。從這裡開始,我們的雲提供商必須有一個路由表條目來了解這個資料包需要去哪裡。

在某些情況下,這是開箱即用。 VPC 路由表使用 pod 和服務 CIDR 範圍進行更新,告知應路由哪些主機資料包。在其他環境中,包括混合環境和本地環境,這可能採取通過 BGP向網路層通告路由的形式。雅虎!日本有一篇很棒的文章介紹了這種確切的部署方法。

但是,這些選項可能並不總是最好的答案,這取決於您的多叢集架構在單個雲提供商中的樣子。它是混合雲還是多雲,結合了本地和兩個不同的雲提供商?雖然您當然可以在所有這些不同的環境中檢測這些,但您可以指望它需要大量的時間和維護。

要考慮的一些解決方案

覆蓋網路

一個更簡單的答案是使用覆蓋網路,在其中為您的應用程式構建一個單獨的 IP 地址空間——在這種情況下,它是一個 Cassandra 資料庫。然後,您可以利用代理、 sidecars和閘道器在現有的Kube網路上執行它。在這篇文章中,我們不會深入探討這一點,但我們有一些關於如何跨 K8s 叢集連線有狀態工作負載的很棒的內容,這些內容將向您展示如何從高層次上做到這一點。

所以,接下來是什麼?資料包在流動,但現在有一些新的 K8s詭計要處理。假設您已經準備好了網路並擁有了所有適當的路由,那麼這些叢集之間至少在 IP層存在一些連線。您擁有 IP 連線 Pod,並且Cluster 1 可以與 Pods 和Cluster 2 通訊,但您現在還需要考慮一些新的事情。  

服務發現

在K8s 網路中,身份是暫時的。由於叢集事件,Pod可能被重新安排並接收新的網路地址。在某些應用中,這不是問題。在其他情況下,比如資料庫,網路地址就是身份——這可能導致意外行為。儘管 IP 地址可能會發生變化,但隨著時間的推移,我們的儲存以及每個 pod 所代表的資料都會保持不變。我們必須有一種方法來維護地址到應用程式的對映。這就是服務發現的切入點。

在大多數情況下,服務發現是在 K8s內通過DNS 實現的。即使 pod 的 IP 地址可能發生變化,它也可以具有基於 DNS 的持久身份,該身份會在叢集時間發生時被更新。這聽起來很不錯,但是當我們進入多叢集的世界時,我們必須確保我們的服務可以跨叢集邊界被發現。作為Cluster  1 中的 pod,我應該能夠獲取Cluster  2 中的 pod 的地址。

DNS 存根

解決這個難題的一種方法是 DNS 存根。在這個配置中,我們配置 K8s DNS 服務,將特定域字尾的請求路由到遠端叢集。有了完全限定的域名,我們就可以將 DNS 查詢請求轉發到適當的叢集進行解析並最終路由。

這裡的問題是,每個叢集都需要通過 kubelet 標誌設定單獨的 DNS 字尾,這在所有 K8s 中都不是一個選項。一些使用者通過使用名稱空間名稱作為 FQDN 的一部分來配置存根解決此問題。這是可行的,但有點像黑客,不是正確設定集群后綴。

託管 DNS

另一種類似於 DNS 存根的解決方案是使用託管 DNS 產品。 在 GCP 的情況下,有  Cloud DNS 產品,可以將本地 DNS 表項複製到 VPC 級別,供外部叢集甚至同一 VPC 內的虛擬機器進行解析。 此選項提供了很多好處,包括:

消除管理叢集託管 DNS 伺服器的開銷——雲 DNS 不需要擴充套件、監控或管理 DNS 例項,因為它是託管的 Google 服務。

每個Google K8s引擎(GKE)節點上DNS查詢的本地解析——與NodeLocal DNSCache類似,雲DNS將DNS響應存到本地,提供低延遲和高可擴充套件性DNS解析。

與 Google Cloud 的操作套件整合——提供了 DNS 監控和日誌記錄。

VPC 範圍DNS——提供多叢集、多環境和 VPC 範圍的 K8s 業務解析。

用於多叢集服務發現的複製託管 DNS

Cloud DNS 抽象了許多傳統的開銷。 雲提供商將管理伸縮性、監控和安全補丁,以及您期望從託管產品中獲得的所有其他方面。 對於一些提供商來說,GKE還提供了一個節點本地 DNS 快取,它通過在較低級別執行 DNS 快取來減少延遲,這樣您就不用等待 DNS 響應。

從長遠來看,如果您只在單個雲中,專門用於DNS的託管服務將可以正常工作。 但是,如果您跨越多個雲提供商和本地環境的叢集,託管產品可能只是解決方案的一部分。

雲本地計算基金會https://www.cncf.io/(CNCF) 提供了多種選擇,並且有大量開源專案缺思在幫助緩解這些痛點方面取得了很大的發展,尤其是在跨雲、多雲、 或混合雲型別的場景。

譯者介紹

康少京,51CTO社群編輯,目前從事通訊類行業,底層驅動開發崗位,研究過資料結構,Python,現對作業系統和資料庫等相關領域感興趣。

原文標題:Taking Your Database Beyond a Single Kubernetes Cluster,作者:Christopher Bradford

連結:https://dzone.com/articles/taking-your-database-beyond-a-single-kubernetes-cl