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

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

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

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

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