使用Kubernetes兩年來的經(jīng)驗(yàn)教訓(xùn)
在Ridecell公司管理基礎(chǔ)設(shè)施團(tuán)隊(duì)幾年后,我想在停下來休息時記錄下我的一些想法和經(jīng)驗(yàn)教訓(xùn)。
Kubernetes不僅僅是炒作
我在Kubernetes領(lǐng)域里活躍了很久,所以這并不出乎我的意料,但當(dāng)某件事情被大肆宣傳的時候,仔細(xì)檢查一下總是好的。在兩年多的時間里,我的團(tuán)隊(duì)完成了從Ansible+Terraform到純Kubernetes的全面遷移,在這個過程中,我們的部署率增加了三倍多,同時將部署錯誤減少到“我都不記得上次是什么時候發(fā)生的”的水平。我們還提高了操作可見性,大量無趣卻很重要的自動化任務(wù),以及基礎(chǔ)設(shè)施中斷時的平均恢復(fù)時間。
Kubernetes并不是魔法,但如果被一個懂它的團(tuán)隊(duì)使用,那它就是一個非常強(qiáng)大的工具。
Traefik + Cert-Manager + Ext-DNS組合很棒
Traefik作為Ingress控制器,Cert-Manager通過LetsEncrypt生成證書,External-DNS管理邊緣DNS記錄,這三個組合使得HTTP路由和管理像黃油一樣順暢。我一直對Traefik 2.0中刪除了很多1.x注釋功能的選擇頗有微詞,但它們終于在2.2中回歸了,盡管以不同的形式。作為一個邊緣代理,Traefik是一個可靠的選擇,它具有出色的指標(biāo)集成,是所有Ingress控制器中管理部件最少的,以及有一個反應(yīng)迅速的開發(fā)團(tuán)隊(duì)。Cert-Manager配合任意Ingress方案都是一個神奇的工具,如果你在Kubernetes集群中做了TLS,但還沒開始使用,那現(xiàn)在就去了解下吧。External-DNS沒有其他兩個那么受歡迎,但是對于自動化DNS記錄和實(shí)際匹配的步驟來說,它的重要性不亞于其他兩個。
如果有什么不同的話,這些工具實(shí)際上可能使得設(shè)置新的HTTPS端點(diǎn)變得太容易。多年來,我們最終使用了幾十個獨(dú)特的證書,這在Cert Transparency搜索和LetsEncrypt自己的證書到期警告等方面產(chǎn)生了很多噪音。以后我將會仔細(xì)考慮哪些主機(jī)名可以作為全局配置的通配符證書的一部分,以減少正在使用的證書總數(shù)。
Prometheus很震撼,Thanos并非大材小用
這是我第一次使用Prometheus作為主要的度量系統(tǒng),它不愧為該領(lǐng)域的首要工具。我們選擇Prometheus-Operator來管理它,這不失為一個好的選擇,讓我們更容易將抓取和規(guī)則配置分發(fā)到需要它們的應(yīng)用中。(如果重來的話,)我會在一開始就使用Thanos。我原本以為使用它會過于大材小用,沒想到它是那么容易配置,而且在跨區(qū)域查詢和減少Prometheus資源使用方面起了很大幫助,即使我們沒有直接使用主-主互備高可用的設(shè)置。
在使用該技術(shù)棧時我遇到的最大困擾是Grafana的數(shù)據(jù)管理,如何存儲和組合儀表板。管理儀表板的工具有了巨大的增長,例如YAML文件、JSON文件、Kubernetes自定義對象,以及你能想到的其他任何東西。但根源問題還是任何一個工具都很難從頭開始編寫一個儀表盤,因?yàn)镚rafana有一百萬種不同的配置選項(xiàng)和面板模式等等。我們最終將它作為一個有狀態(tài)的系統(tǒng)來處理,將所有的儀表板進(jìn)行分組管理,但我并不喜歡這種解決方案。這里是否有一個更好的工作流程呢?
GitOps才是正道
如果你使用Kubernetes,那么你應(yīng)該使用GitOps。關(guān)于工具選擇有很多,最簡單的就是在你現(xiàn)有的CI系統(tǒng)中添加運(yùn)行kubectl apply的作業(yè),一直到使用專用的系統(tǒng)例如ArgoCD和Flux。不過我堅定地站在ArgoCD陣營,它是一個可作為開始的可靠的選擇,而且在過去的這些年里它越來越好。就在這周,GitOps-engine的第一個版本已經(jīng)上線,其將ArgoCD和Flux放在一個共享的底層系統(tǒng)上,所以現(xiàn)在更快更好了。如果你不喜歡這些工具的工作流,你現(xiàn)在甚至可以更容易構(gòu)建新的。在幾個月前我們遇到了一次意外的災(zāi)難恢復(fù)游戲日,因?yàn)橛腥瞬恍⌒膭h除了測試集群中的大部分命名空間,多虧了GitOps,我們的恢復(fù)方式是在bootstrap庫中執(zhí)行make apply,然后等待系統(tǒng)自行重建。話說回來,對于一些不能在git中生存的有狀態(tài)數(shù)據(jù)的Velero備份也是很重要的(比如cert-manager的證書,它雖然可以重新簽發(fā),但你可能會遇到LetsEncrypt的速率限制)。
我們遇到最大的問題就是選擇將所有核心基礎(chǔ)設(shè)施保存在一個存儲庫中。我依然認(rèn)為使用一個單一的庫是正確的設(shè)計,但我將會將不同的事物劃分到不同的ArgoCD實(shí)例中,而不是像現(xiàn)在將所有都放在一個“infra”的實(shí)例中。使用單個實(shí)例導(dǎo)致更長的收斂時間和嘈雜的UI,而且如果我們習(xí)慣了正確地分割我們的Kustomize定義的話,它就沒有多大益處了。
我們應(yīng)用創(chuàng)建更多的Operator
我從一開始就積極發(fā)展自定義Operator,且我們在這方面取得了巨大的成功。我們從一個自定義資源和控制器開始,用于部署我們的主要網(wǎng)絡(luò)應(yīng)用,并慢慢擴(kuò)展到該應(yīng)用和其他應(yīng)用所需的所有其他自動化。使用普通的Kustomize和ArgoCD進(jìn)行簡單的基礎(chǔ)架構(gòu)服務(wù)效果很好,但是當(dāng)我們想要控制外部事物時(例如從Kubernetes創(chuàng)建AWS IAM角色,通過kiam來使用),或者當(dāng)我們需要某種級別的狀態(tài)機(jī)來控制這些事物時(例如帶有SQL遷移的Django應(yīng)用部署),我們都會需要用到Operator。 作為其中的一部分,我們還為我們所有的自定義對象和控制器建立了一個非常徹底的測試套件,這極大地提高了操作的穩(wěn)定性和我們自己對系統(tǒng)正確工作的確定性。
當(dāng)前有越來越多的方式來構(gòu)建Opeator,但我仍然對kubebuilder相當(dāng)滿意(盡管公平地說,我們確實(shí)隨著時間的推移大幅修改了項(xiàng)目結(jié)構(gòu),所以說它使用的是controller-runtime和controller-tools比kubebuilder本身更公平)。無論你最喜歡使用哪種語言和框架,都可能有可用的Operator工具包,你絕對應(yīng)該使用它。
Secret管理仍是難題
Kubernetes有自己的Secret對象,用于在運(yùn)行時管理秘密數(shù)據(jù),與容器或與其他對象一起使用,而且這個系統(tǒng)工作得很好。但是Secret的長期工作流程還是有點(diǎn)亂。把一個原始的Secret提交到Git是很糟糕的,原因有很多,希望我不需要列舉,那么我們?nèi)绾喂芾磉@些對象呢?我的解決方案是開發(fā)一個自定義的EncryptedSecret類型,它使用AWS KMS對每個值進(jìn)行加密,同時在Kubernetes中運(yùn)行的控制器像往常一樣將其解密回正常的Secret,還有一個用于解密-編輯-再加密循環(huán)的命令行工具。使用 KMS意味著我們可以通過IAM規(guī)則限制KMS密鑰的使用來做訪問控制,并且只加密值,讓文件有合理的差異性?,F(xiàn)在有一些基于Mozilla Sops的社區(qū)Operator提供了大致相同的工作流,盡管Sops在本地編輯工作流程上有點(diǎn)令人沮喪。總的來說,這個領(lǐng)域還需要很多努力,人們應(yīng)該期待一個可審計、可版本化、可代碼審查的工作流,就像在GitOps世界里的所有事情一樣。
作為一個相關(guān)的問題,Kubernetes的RBAC模型的弱點(diǎn)在Secrets上表現(xiàn)得最為明顯。幾乎在所有情況下,被用于一個事物的Secret必須和使用它的事物在同一個命名空間中,這往往意味著很多不同事物的Secret最終會在同一個命名空間中(數(shù)據(jù)庫密碼、廠商API令牌、TLS證書),如果你想給某人(或某事,同樣的問題適用于Operator)訪問其中一個,他們就會獲得所有的訪問權(quán)限。讓你的命名空間盡可能的小,任何可以放在它自己的命名空間的東西,都去做吧。你的RBAC策略會感謝你現(xiàn)在的做法。
原生CI和日志分析仍是開放性問題
我遇到的兩大生態(tài)系統(tǒng)坑就是CI和日志分析。有很多部署在Kubernetes的CI系統(tǒng),例如Jenkins、Concourse、Buildkite等。但感覺完全類原生的解決方案很少。JenkinsX可能是最接近原生體驗(yàn)的,但它是建立在非常大的復(fù)雜性上,我覺得非??上?。Prow本身也是非常原生的,但定制化很多,所以也不是一個容易上手的工具。Tekton Pipelines和Argo Workflows都有原生CI系統(tǒng)的低級管道,但是找到一種方法將其暴露給我的開發(fā)團(tuán)隊(duì)從來沒有超出理論操作人員的范圍。Argo-CI似乎已經(jīng)被放棄了,但Tekton團(tuán)隊(duì)似乎正在積極地追蹤這個用例,所以我對它的一些改進(jìn)充滿希望。
日志收集基本上是一個已解決的問題,社區(qū)集中在Fluent Bit上,將其作為一個DaemonSet發(fā)送給一些Fluentd pods,然后再發(fā)到你用來存儲和分析的任何系統(tǒng)上。在存儲方面,我們有ElasticSearch和Loki作為主要的開放競爭者,每個都有自己的分析前端(Kibana和Grafana)。似乎主要還是最后一部分是我的挫敗感的來源。Kibana出現(xiàn)的時間更久,分析功能也很豐富,但你必須使用商業(yè)版來獲得基本的操作,比如用戶身份驗(yàn)證和用戶權(quán)限仍然非常模糊。Loki要新得多,分析工具就更少了(子字符串搜索和每行標(biāo)簽搜索),至今沒有任何針對權(quán)限的設(shè)計。如果你小心翼翼地確保所有的日志輸出是安全的,可以讓所有的工程師看到,這沒問題,但你要準(zhǔn)備好在SOC/PCI等審計中遇到一些尖銳的問題。
結(jié)語
Kubernetes并不是很多人所說的那種可全套交付的解決方案,但是通過一些精心的工程設(shè)計和非凡的社區(qū)生態(tài)系統(tǒng),它可以成為一個無與倫比的平臺?;c(diǎn)時間學(xué)習(xí)每個底層組件,你將會在通往容器幸福的道路上走得很好,希望你在此過程中能避免我的一些錯誤。