使用Helm創(chuàng)建了一個 Kubernetes Operator
K8ssandra 是 Apache Cassandra?在 Kubernetes 上的一個發(fā)行版,由多個開源組件構(gòu)建而成。從一開始直到最近的 K8ssandra 1.3 版本,K8ssandra 一直使用 Helm 圖表進行安裝和管理。雖然該項目的某些組件使用了 Kubernetes Operators——包括 Cassandra(cass-operator)和 Medusa(medusa-operator),但還沒有一個 Operator 對所有組件進行整體管理。
K8ssandra 團隊最近完成了一個我們討論了幾個月的決定:為 K8ssandra 項目創(chuàng)建一個 Operator。在本文中,我們介紹了我們使用 Helm 的經(jīng)驗,我們?yōu)?K8ssandra 創(chuàng)建 Operator 的決定,以及我們希望這將為項目帶來的好處。

1 背景
K8ssandra 的核心是 cass-operator,我們使用它來部署 Cassandra 節(jié)點。我們圍繞它添加了一系列組件,組成一個生態(tài)系統(tǒng),用于在 Kubernetes 中有效地運行 Cassandra。這些組件包括用于管理反熵修復(fù)(Reaper)和備份(Medusa)的操作工具。我們引入了用于指標(biāo)收集和報告的 Prometheus/Grafana 技術(shù)棧。Stargate 則是一個數(shù)據(jù)網(wǎng)關(guān),通過 REST、GraphQL 和 Document API 提供了對 Cassandra 更靈活的訪問。
一開始,我們使用 Helm 來幫助管理這些組件的安裝和配置。這使我們能夠快速啟動項目并開始組建社區(qū)。最初對該項目感興趣的人主要是 Cassandra 社區(qū)的開發(fā)人員,他們不一定有很多 Kubernetes 的專業(yè)知識和經(jīng)驗。他們中的許多人發(fā)現(xiàn)掌握像 Helm 這樣的包管理工具和安裝程序比掌握 Operator 和 CRD(定制資源定義)更容易。這并不是說 Helm 是為“不太了解 Kubernetes 的人”準(zhǔn)備的,因為 Kubernetes 生態(tài)的很大一部分都在使用 Helm。

2 進展:Helm 的優(yōu)缺點
隨著項目的發(fā)展,我們開始在 Helm 上遇到一些限制。雖然正確安裝 K8ssandra 集群非常簡單,但我們在升級和管理集群時遇到了比較多的問題。
Helm 通過循環(huán)和 if 語句很好地支持控制流。然而,當(dāng)嵌套層次比較多時,整個代碼就很難理解和閱讀,而且縮進也成為一個問題。特別是,我們發(fā)現(xiàn)對修改后的 Helm 圖表進行同行評審變得相當(dāng)困難。
Helm 變量的作用范圍被限制在聲明它們的模板內(nèi)。例如,我們在 Cassandra 數(shù)據(jù)中心模板中定義了一個變量,在 Stargate 模板中不可能重用它,我們必須在 Stargate 模板中重新創(chuàng)建相同的變量。這使得我們的代碼很難保持 DRY 原則,我們發(fā)現(xiàn)這是缺陷的來源。
類似地,Helm 有一個很好很大的幫助模板函數(shù)庫,但是這個庫并沒有涵蓋所有用例,并且沒有接口來定義您自己的函數(shù)。您可以定義自己的模板,模板可以被大量重用,但它們不能代替函數(shù)。
傘形圖設(shè)計模式是 Helm 的最佳實踐,但我們在嘗試實現(xiàn)該模式時也遇到了困難。我們能夠創(chuàng)建一個頂級 K8ssandra Helm 圖表,其中包含 Cassandra 和 Prometheus 的子圖表,但當(dāng)我們試圖為 Reaper 和 Stargate 創(chuàng)建額外的子圖表時,卻遇到了變量作用范圍的問題。我們的目的是僅僅在頂級圖表定義身份驗證設(shè)置,這樣它們不僅可以應(yīng)用于 Cassandra,還可以應(yīng)用于 Stargate 和 Reaper。Helm 的繼承模型不支持這種將變量向下推到子圖表的概念。
Helm 可以創(chuàng)建 Kubernetes 的定制資源定義(CRD),但不能管理它們。我們知道這是 Helm 開發(fā)者為 Helm 3 做出的深思熟慮的設(shè)計選擇。由于定制資源的定義是集群范圍的,如果多個 Helm 安裝過程試圖在不同版本的 CRD 上工作可能會帶來一些混亂。然而,這給我們帶來了一些困難。為了管理資源的更新——比如 Helm 內(nèi)部的 Cassandra 數(shù)據(jù)中心,我們必須實現(xiàn)一個變通方案。我們實現(xiàn)了定制的 Kubernetes job,并將它們標(biāo)記為升級前的鉤子(Hook),這樣 Helm 就可以在升級時執(zhí)行它們。每個 job 都用 Go 語言編寫,并打包成一個鏡像。這本質(zhì)上就像編寫迷你控制器,并且在某種程度上開始感覺像編寫 Operator。
雖然我們已經(jīng)能夠通過 1.3 版本解決這些 Helm 的問題,但我們路線圖上的下一個主要特性是實現(xiàn)多集群 K8ssandra 部署(跨越多個 Kubernetes 集群的 K8ssandra/Cassandra 集群)。我們意識到,即使沒有復(fù)雜的網(wǎng)絡(luò)配置,我們也無法使用 Helm 有效實現(xiàn)這一步。
3 設(shè)定新方向
最后,我們意識到我們讓 Helm 做得太多了。很容易陷入這樣的情況:您學(xué)會了如何使用錘子,所有東西看起來都像釘子,但您真正需要的是螺絲刀。
結(jié)果,我們發(fā)現(xiàn)我們與 Operator 框架 的創(chuàng)建者有一些共同點,他們已經(jīng)為 Operator 定義了一個 功能模型,我們將其展示在這里:

如圖所示,Helm 最適合 Operator 前兩個級別的功能,側(cè)重于簡單的安裝和升級。執(zhí)行更復(fù)雜的操作如故障處理和恢復(fù)、自動伸縮,以及更復(fù)雜的安裝和升級應(yīng)該用諸如 Ansible 或 Go 之類的編程語言來實現(xiàn),而不是使用像 Helm 這樣的模板語言。
基于這一分析,團隊決定開始構(gòu)建一個 Operator,我們將其稱之為 K8ssandra 2.x 系列版本。2.0 版本的首要任務(wù)是移植我們在 Helm 圖表中已有的功能,確保 Operator 具有相同的特性,并在其中增加多集群支持。我們?nèi)匀淮蛩憬鉀Q 1.x 版本中的 bug 或漏洞,但我們正試圖將所有主要的新功能都集中在 Operator 上。
在工具方面,我們不認(rèn)為 Helm 和 Operator 是相互排斥的。這兩種方法是互補的,我們需要根據(jù)其優(yōu)勢來使用每一種方法。我們將繼續(xù)使用 Helm 執(zhí)行基本的安裝操作,包括安裝 Operator 以及設(shè)置 Cassandra 和其他組件使用的管理員服務(wù)帳號(Administrator Service Account)。這些都是 Helm 這樣的包管理器最擅長的功能。
4 Operator 設(shè)計和實現(xiàn)的選擇
在 K8ssandra Operator 的設(shè)計和實現(xiàn)中,我們做出了幾個關(guān)鍵的選擇。
雖然 Reaper Operator、Medusa Operator 和 Stargate Operator 有單獨的倉庫,但我們計劃將它們合并到 K8ssandra Operator 中。K8ssandra Operator 將在單個 pod 中運行,但將包含與每個 CRD 對應(yīng)的多個控制器。我們將會有多個 CRD 和多個控制器。因為 cass operator 已經(jīng)被獨立使用,所以它仍將是獨立的,并將成為 K8ssandra Operator 的一個依賴項。

雖然目前這不是微服務(wù)架構(gòu),但它是松耦合和模塊化的,所以未來如果需要,我們可以將控制器重新打包為獨立的微服務(wù)。
我們決定基于 Operator SDK 使用 Go 語言編寫 K8ssandra Operator。對于我們來說,這是一個簡單的選擇,因為我們已經(jīng)從開發(fā) cass-operator 中熟悉了它。我們相信使用像 Go 語言這樣的全功能編程語言會比使用 YAML 模板更有吸引力,并有助于吸引新的貢獻(xiàn)者加入項目。這還將使我們能夠使用該語言的全部功能。例如,Go 可以很容易地創(chuàng)建易于重用的輔助函數(shù)。
新的 K8ssandra 集群 CRD 有一個狀態(tài)字段,可以讓您大致了解集群的狀態(tài),包括是否已經(jīng)就緒(ready)、尚未就緒(not ready)、正在初始化(initializing)等等。該狀態(tài)將匯總組成集群的所有對象的健康狀況,包括 Cassandra 集群、Stargate、Reaper 和其他任何部署在其中的對象,而這不是 Helm 可以做到的。
我們?yōu)槊總€定制資源開發(fā)控制器的設(shè)計方法與 Kubernetes 中管理資源的標(biāo)準(zhǔn)方法更加一致。例如,我們有一個特定的啟動順序,我們想定義如下規(guī)則:在 Cassandra 初始化之前不啟動 Stargate。開箱即用的 Helm 無法實現(xiàn)這一功能。我們必須在 Stargate pod 中添加一個初始化容器,以執(zhí)行集群啟動和運行的基本檢查。有了新的 Operator,Stargate 可以檢查 Cassandra 數(shù)據(jù)中心 CRD 的狀態(tài)變化。當(dāng)它被調(diào)協(xié)器(reconciliation)觸發(fā)運行,它查詢獲得 Cassandra 數(shù)據(jù)中心的狀態(tài),一旦其狀態(tài)變?yōu)榫途w(ready),Operator 就將部署 Stargate。
這種方式也將改進測試。有很多可用的測試覆蓋工具,例如我們正在使用的 SonarCloud。然而,我們不能將 SonarCloud 與 Helm 模板一起使用。所以我們現(xiàn)在沒有一個好的方法來衡量測試中的覆蓋水平,而且 IDE 的支持也不像對靜態(tài)語言那么好。
5 我們?nèi)栽谘芯康氖虑?/strong>
在開發(fā) Operator 的過程中,我們還在繼續(xù)探索和學(xué)習(xí)一些領(lǐng)域。
Helm 模板非常適合快速迭代,但 Operator 的開發(fā)步驟更復(fù)雜。在修改 Operator 代碼之后,我們必須重新構(gòu)建 Operator 鏡像并部署它,然后部署 Operator 管理的定制資源,以便它隨后生成 Deployment 對象,然后我們就可以驗證部署了。這個過程涉及更多步驟,所以我們正在尋求改進方法,使其更加自動化。
測試多集群 K8ssandra 部署存在一些挑戰(zhàn)。到目前為止,我們已經(jīng)能夠使用 GitHub Actions 進行大多數(shù)持續(xù)集成測試(使用免費的 tier runner),但我們發(fā)現(xiàn)這在涉及多集群資源的時候是不夠的。
我們正在調(diào)研的集成測試工具之一是 Kuttl。使用 Kuttl,測試用例和預(yù)期結(jié)果都在 YAML 文件中描述,這意味著您不必是 Go 語言或 Kubernetes API 的專家也可以貢獻(xiàn)測試。我們相信這會讓開發(fā)人員更容易參與測試并立即做出貢獻(xiàn),然后如果他們愿意,可以按照自己的節(jié)奏開始使用 Go。
6 您應(yīng)該使用 Operator 嗎?您應(yīng)該開發(fā)一個 Operator 嗎?
如果您已經(jīng)讀到這里,您可能想知道這對您自己的項目的影響。如果您在 Kubernetes 中使用數(shù)據(jù)庫或其他基礎(chǔ)設(shè)施,那么使用 Operator 盡可能自動化的操作工作負(fù)載肯定是有意義的。
如果您為數(shù)據(jù)基礎(chǔ)設(shè)施供應(yīng)商工作,或者為開源數(shù)據(jù)基礎(chǔ)設(shè)施項目做出貢獻(xiàn),您可能會好奇何時應(yīng)該開始構(gòu)建 Operator。我們在自己的過渡過程中進行了很多思考,特別是在時間安排和對用戶的影響方面。最終我們的建議是:您在很多情況下發(fā)現(xiàn)您所使用的工具對您不利,而不是對您有利,此時可能是時候考慮不同的解決方案了。
7 建立社區(qū)
我們現(xiàn)在看到對 K8ssandra 的貢獻(xiàn)有所增加,尤其是在問題創(chuàng)建方面。現(xiàn)在我們已經(jīng)開始在 Operator 的發(fā)展中獲得動力,不斷增長的用戶社區(qū)幫助我們認(rèn)識到為了加快產(chǎn)品成熟而需要做的事情,這是擁有這樣一個社區(qū)的巨大好處。
我們還想繼續(xù)加強代碼貢獻(xiàn)團隊。如果您有興趣在 Kubernetes 上運行 Cassandra 或構(gòu)建 Operator,我們很樂意讓您成為 K8ssandra 項目的一員。您可以查看我們的網(wǎng)站,也可以在 論壇 或我們的 Discord 服務(wù)上提出任何問題。
原文鏈接:https://thenewstack.io/
文章轉(zhuǎn)載:InfoQ
(版權(quán)歸原作者所有,侵刪)