生產(chǎn)中使用Kubernetes兩年后的經(jīng)驗教訓(xùn)
大約兩年前,我們決定放棄基于Ansible的配置管理設(shè)置,以便在EC2上部署應(yīng)用程序,并轉(zhuǎn)向使用Kubernetes進(jìn)行容器化和編排應(yīng)用程序。我們已將大部分基礎(chǔ)架構(gòu)遷移到Kubernetes。這是一項艱巨的任務(wù),也有其自身的挑戰(zhàn)-從運行混合基礎(chǔ)架構(gòu)的技術(shù)挑戰(zhàn)到完成大部分遷移,再到以全新的運營模式培訓(xùn)整個團(tuán)隊,僅舉幾例。
在這篇文章中,我們想反思我們的經(jīng)驗,并與您分享我們在這次旅程中的經(jīng)驗,以幫助您做出更好的決定并增加成功的機會。
明確說明您遷移到Kubernetes的原因
所有那些無服務(wù)器和容器的東西都很好。如果您要開始一項新業(yè)務(wù)并從頭開始構(gòu)建所有內(nèi)容,請務(wù)必使用容器來部署應(yīng)用程序,并在擁有帶寬(或可能不具備)的情況下使用Kubernetes來編排應(yīng)用程序,并且擁有配置和配置技術(shù)的技能。操作Kubernetes以及在Kubernetes上部署應(yīng)用程序。
即使您將Kubernetes的操作卸載到諸如EKS,GKE或AKS之類的Kubernetes托管服務(wù)上,在Kubernetes上正確部署和操作應(yīng)用程序也需要學(xué)習(xí)。您的開發(fā)團(tuán)隊?wèi)?yīng)該應(yīng)對挑戰(zhàn)。只有您的團(tuán)隊遵循DevOps理念,才能實現(xiàn)很多好處。如果您有中央sysadmin團(tuán)隊為其他團(tuán)隊開發(fā)的應(yīng)用程序編寫清單,那么從DevOps的角度來看,我們個人認(rèn)為Kubernetes的好處較小。當(dāng)然,您可以選擇Kubernetes帶來許多其他好處,例如成本,更快的實驗,更快的自動縮放,彈性等。
如果您已經(jīng)在云VM或其他PaaS上進(jìn)行部署,那么為什么真正考慮從現(xiàn)有基礎(chǔ)架構(gòu)遷移到Kubernetes?您是否相信Kubernetes是解決問題的唯一方法?您必須清楚自己的動機,因為將現(xiàn)有基礎(chǔ)架構(gòu)遷移到Kubernetes是一項艱巨的任務(wù)。
我們在這方面犯了一些錯誤。我們遷移到Kubernetes的主要原因是建立一個持續(xù)集成的基礎(chǔ)架構(gòu),該基礎(chǔ)架構(gòu)可以幫助我們快速重新構(gòu)建微服務(wù),而這些年來,這些微服務(wù)一直困擾著許多架構(gòu)。大多數(shù)新功能都需要涉及多個代碼庫,因此,一起開發(fā)和測試所有這些功能會使我們慢下來。我們認(rèn)為有必要為每個開發(fā)人員和每個變更提供一個集成的環(huán)境,以幫助加快開發(fā)和測試周期,而無需協(xié)調(diào)誰來獲得“共享階段環(huán)境”。
> One of our continuous integration pipelines that provisions a new integrated environment with all the microservices and runs automated tests
我們今天做得很好。我們今天在8分鐘內(nèi)在Kubernetes上的集成環(huán)境中提供了21種微服務(wù)。任何開發(fā)人員都可以使用我們自己開發(fā)的工具來執(zhí)行此操作。對于為這21個微服務(wù)中的任何一個創(chuàng)建的每個拉取請求,我們還提供了該環(huán)境的子集。整個測試周期(提供環(huán)境和運行測試)需要不到12分鐘的時間??赡芨杏X很長,但它阻止了我們在當(dāng)前所處的體系結(jié)構(gòu)混亂中進(jìn)行重大更改。
> Continuous Integration pipeline execution report
贊!建立所有這些需要什么?我們花了將近1.5年的時間。那值得嗎?
通過構(gòu)建其他工具,遙測并重新部署每個應(yīng)用程序的方式,我們花了將近1.5年的時間來穩(wěn)定這種復(fù)雜的CI設(shè)置。為了實現(xiàn)開發(fā)/產(chǎn)品平價,我們也必須將所有這些微服務(wù)都部署到生產(chǎn)中,否則,基礎(chǔ)架構(gòu)和部署設(shè)置之間的偏差將使應(yīng)用程序難以為開發(fā)人員辯護(hù),并且本應(yīng)為開發(fā)人員做出選擇一個噩夢。
我們對這個話題有不同的看法?;仡欉^去,我們認(rèn)為解決連續(xù)集成的問題變得更加糟糕,因為將所有微服務(wù)推向生產(chǎn)以實現(xiàn)開發(fā)/產(chǎn)品平價的復(fù)雜性使得實現(xiàn)更快的CI的挑戰(zhàn)變得更加復(fù)雜和困難。在使用Kubernetes之前,我們將Ansible與Hashicorp Consul和Vault一起用于基礎(chǔ)架構(gòu)供應(yīng),配置管理和部署。慢嗎?是的,一點沒錯。但是我們認(rèn)為我們可以通過Consul引入服務(wù)發(fā)現(xiàn)并優(yōu)化Ansible部署,從而在合理的較短時間內(nèi)就足夠接近我們的目標(biāo)。
我們應(yīng)該遷移到Kubernetes嗎?是的,一點沒錯。使用Kubernetes有很多好處-服務(wù)發(fā)現(xiàn),更好的成本管理,彈性,治理,對云基礎(chǔ)架構(gòu)基礎(chǔ)架構(gòu)的抽象等等。今天,我們也收獲了所有這些好處。但這并不是我們開始時的主要目標(biāo),也許沒有必要施加自己的壓力和痛苦來實現(xiàn)自己的方式。
對我們來說,一大收獲是,我們本可以采用另一種且抗性較小的方式來采用Kubernetes。我們只是被Kubernetes收購,這是我們甚至不在乎評估其他選項的唯一解決方案。
我們將在此博客文章中看到,在Kubernetes上進(jìn)行遷移和操作與在云VM或裸機上進(jìn)行部署不同。您的云工程和開發(fā)團(tuán)隊有一條學(xué)習(xí)曲線。對于您的團(tuán)隊來說,值得一試。但是,現(xiàn)在您需要做的是這個問題。您必須嘗試清楚地回答。
開箱即用的Kubernetes幾乎對任何人來說都是遠(yuǎn)遠(yuǎn)不夠的
許多人對Kubernetes作為PaaS解決方案感到困惑,這不是PaaS解決方案。它是構(gòu)建PaaS解決方案的平臺。OpenShift就是這樣一個例子。
開箱即用的Kubernetes對于幾乎任何人來說都是遠(yuǎn)遠(yuǎn)不夠的。這是一個學(xué)習(xí)和探索的絕佳游樂場。但是您很可能需要在頂部放置更多基礎(chǔ)結(jié)構(gòu)組件,并將它們很好地結(jié)合在一起,作為應(yīng)用程序的解決方案,以使其對您的開發(fā)人員更有意義。通常,這種帶有附加基礎(chǔ)設(shè)施組件和策略的Kubernetes捆綁包稱為內(nèi)部Kubernetes平臺。這是一個非常有用的范例,并且有幾種擴展Kubernetes的方法。
度量標(biāo)準(zhǔn),日志,服務(wù)發(fā)現(xiàn),分布式跟蹤,配置和秘密管理,CI / CD,本地開發(fā)經(jīng)驗,對自定義度量標(biāo)準(zhǔn)的自動擴展都是需要照顧和做出決定的事情。這些只是我們要呼吁的一些事情。肯定會有更多的決策和更多的基礎(chǔ)架構(gòu)要建立。一個重要的方面是您的開發(fā)人員將如何使用Kubernetes的資源和清單-在本博客文章的后面將對此進(jìn)行更多介紹。
這是我們的一些決定和理由。
指標(biāo)
我們最后確定了Prometheus。Prometheus幾乎是事實上的度量標(biāo)準(zhǔn)基礎(chǔ)結(jié)構(gòu)。CNCF和Kubernetes非常喜歡它。它在Grafana生態(tài)系統(tǒng)中非常有效。而且我們喜歡Grafana!我們唯一的問題是我們正在使用InfluxDB。我們已決定從InfluxDB遷移并完全致力于Prometheus。
日志
日志一直是我們的大難題。我們一直在努力使用ELK創(chuàng)建一個穩(wěn)定的日志記錄平臺。我們發(fā)現(xiàn)ELK具有我們團(tuán)隊無法實際使用的功能。這些功能需要付出一定的代價。另外,我們認(rèn)為將Elasticsearch用于日志存在固有的挑戰(zhàn),使其成為昂貴的日志解決方案。我們由Grafana最終確定了Loki。這很簡單。它具有滿足我們團(tuán)隊需求的必要功能。極具成本效益。但最重要的是,由于它的查詢語言與PromQL非常相似,因此它具有出色的UX。此外,它與Grafana搭配使用也很好。這樣一來,就可以將整個指標(biāo)監(jiān)視和日志記錄體驗集中到一個用戶界面中。
An example of a Grafana dashboard with visualization over metrics and corresponding logs side-by-sid
配置和密鑰
您會發(fā)現(xiàn)大多數(shù)文章在Kubernetes中使用configmap和密鑰對象。我們的學(xué)習(xí)是,它可以幫助您入門,但是對于我們的用例而言,我們發(fā)現(xiàn)它還遠(yuǎn)遠(yuǎn)不夠。將configmap與現(xiàn)有服務(wù)一起使用需要一定的費用。Configmap可以通過某種方式安裝到pod中-使用環(huán)境變量是最常見的方式。如果您有大量的舊式微服務(wù)從配置管理工具(如Puppet,Chef或Ansible)提供的文件中讀取配置,則您將不得不在所有代碼庫中重做配置處理,以便現(xiàn)在從環(huán)境變量中進(jìn)行讀取。我們沒有找到足夠的理由在合理的情況下執(zhí)行此操作。此外,配置或機密的更改意味著您將必須通過打補丁來重新部署您的部署。這將是kubectl命令的額外命令性編排。
> Design by Asif Jamal
為了避免所有這些情況,我們決定使用Consul,Vault和Consul模板進(jìn)行配置管理。今天,我們將Consul模板作為初始化容器運行,并計劃將其作為Pod中的Sidecar運行,以便它可以監(jiān)視Consul中的配置更改并刷新Vault中即將過期的密鑰并優(yōu)雅地重新加載應(yīng)用程序進(jìn)程。
CI / CD
在遷移到Kubernetes之前,我們一直在使用Jenkins。遷移到Kubernetes之后,我們決定堅持使用詹金斯。到目前為止,我們的經(jīng)驗是,Jenkins并不是使用云原生基礎(chǔ)架構(gòu)的最佳解決方案。我們發(fā)現(xiàn)自己使用Python,Bash,Docker和腳本化/聲明性Jenkins管道做了很多工作,以使其全部正常工作。建立和維護(hù)這些工具和管道開始變得昂貴。我們現(xiàn)在正在探索Tekton和Argo工作流作為我們的新CI / CD平臺。您可以在CI / CD環(huán)境中探索更多選項,例如Jenkins X,Screwdriver,Keptn等。
開發(fā)經(jīng)驗
在開發(fā)工作流程中有多種使用Kubernetes的方法。我們主要將選擇權(quán)歸零到兩個選項-Telepresence.io和Skaffold。Skaffold能夠監(jiān)視您的本地更改并將其不斷部署到您的Kubernetes集群中。另一方面,網(wǎng)真允許您在與Kubernetes集群建立透明網(wǎng)絡(luò)代理的同時在本地運行服務(wù),以便您的本地服務(wù)可以與Kubernetes中的其他服務(wù)進(jìn)行通信,就好像它已部署在集群中一樣。這是個人意見和偏好的問題。很難決定一種工具。目前,我們主要在嘗試網(wǎng)真,但我們并沒有放棄Skaffold對我們來說是更好的工具的可能性。只有時間會告訴我們我們決定使用什么,或者也許我們會同時使用。還有其他解決方案,例如草稿值得一提。
分布式跟蹤
我們暫時還沒有進(jìn)行分布式跟蹤。但是,我們計劃很快就對該領(lǐng)域進(jìn)行投資。像日志記錄一樣,我們希望在Grafana旁邊提供度量標(biāo)準(zhǔn)和日志記錄旁邊的分布式跟蹤,以便為我們的開發(fā)團(tuán)隊提供更加集成的可觀察性體驗。
應(yīng)用程序打包,部署和工具
Kubernetes的一個重要方面是考慮開發(fā)人員如何與集群進(jìn)行交互并部署其工作負(fù)載。我們希望使事情簡單易擴展。我們正在向Kustomize,Skaffold以及一些本地CRD匯聚,以作為開發(fā)人員部署和管理應(yīng)用程序的方式。話雖如此,只要團(tuán)隊是開源的并且建立在開放標(biāo)準(zhǔn)之上,那么任何團(tuán)隊都可以自由地使用他們想與集群進(jìn)行交互的任何工具。
操作Kubernetes集群很困難
我們主要在AWS的新加坡地區(qū)以外運營。在我們開始使用Kubernetes的旅程時,在新加坡地區(qū)還沒有提供EKS服務(wù)。因此,我們必須使用kops在EC2上建立自己的Kubernetes集群。
建立一個基本集群也許并不那么困難。我們能夠在一周內(nèi)建立起第一個集群。當(dāng)您開始部署工作負(fù)載時,大多數(shù)問題都會發(fā)生。從調(diào)整群集自動縮放器到在正確的時間配置資源,再到正確配置網(wǎng)絡(luò)以實現(xiàn)正確的性能,您必須自己研究和配置。在大多數(shù)情況下,默認(rèn)設(shè)置在大多數(shù)情況下都不會起作用(或者至少在那時對我們不起作用)。
我們的學(xué)習(xí)是,操作Kubernetes是復(fù)雜的。有很多活動部件。而且,學(xué)習(xí)如何操作Kubernetes很可能不是您業(yè)務(wù)的核心。盡可能將負(fù)載卸載到云服務(wù)提供商(EKS,GKE,AKS)。自己進(jìn)行此操作沒有任何價值。
您仍然必須考慮升級
Kubernetes非常復(fù)雜,即使您使用的是托管服務(wù),升級也不會一帆風(fēng)順。
即使使用托管的Kubernetes服務(wù),也要盡早投資基礎(chǔ)架構(gòu)即代碼的設(shè)置,以使災(zāi)難恢復(fù)和升級過程在未來的痛苦相對較小,并且能夠在發(fā)生災(zāi)難時快速恢復(fù)。
如果愿意,您可以嘗試推動GitOps。如果您無法做到這一點,那么將手動步驟減少到最低限度是一個很好的開始。我們結(jié)合使用eksctl,terraform和我們的群集配置清單(包括平臺服務(wù)的清單)來建立所謂的“ Grofers Kubernetes平臺”。為了使設(shè)置和部署過程更簡單,可重復(fù),我們建立了一個自動化管道來設(shè)置新集群并將更改部署到現(xiàn)有集群。
資源請求和限制
開始遷移后,由于配置錯誤,我們在群集中觀察到許多性能和功能問題。其結(jié)果之一是在資源請求和限制中添加了許多緩沖區(qū),以消除資源限制,從而降低性能。
最早的觀察之一是由于節(jié)點上的內(nèi)存限制而導(dǎo)致的逐出。原因是與資源請求相比,資源限制過高。隨著流量的激增,內(nèi)存消耗的增加可能導(dǎo)致節(jié)點上的內(nèi)存飽和,從而進(jìn)一步導(dǎo)致Pod逐出。
我們的學(xué)習(xí)是將資源請求保持在足夠高的水平,但又不要過高,以便在低流量時間內(nèi)浪費資源,并使資源限制相對接近資源請求,以便為尖峰流量留出一定的喘息空間,而不會由于節(jié)點上的內(nèi)存壓力而驅(qū)逐Pod。限制與請求之間的接近程度取決于您的流量模式。
這不適用于非生產(chǎn)環(huán)境(例如開發(fā),登臺和CI)。這些環(huán)境不會帶來任何流量高峰。從理論上講,如果將CPU請求設(shè)置為零并為容器設(shè)置足夠高的CPU限制,則可以運行無限個容器。如果您的容器開始占用大量CPU,它們將受到限制。您也可以對內(nèi)存請求和限制執(zhí)行相同的操作。但是,達(dá)到內(nèi)存限制的行為與CPU不同。如果您使用的內(nèi)存超過了設(shè)置的內(nèi)存限制,則容器將被殺死OOM,然后容器將重新啟動。如果您的內(nèi)存限制異常高(例如高于節(jié)點的容量),則可以繼續(xù)使用內(nèi)存,但是最終,當(dāng)節(jié)點可用內(nèi)存不足時,調(diào)度程序?qū)㈤_始逐出Pod。
在非生產(chǎn)環(huán)境中,我們通過保持極低的資源請求和極高的資源限制來盡可能安全地超額分配資源。在這種情況下,限制因素是內(nèi)存,即無論內(nèi)存請求有多低和內(nèi)存限制有多高,pod逐出都是節(jié)點上調(diào)度的所有容器使用的內(nèi)存總和的函數(shù)。
安全與治理
Kubernetes旨在為開發(fā)人員解鎖云平臺,使其更加獨立,并推動DevOps文化。向開發(fā)人員開放平臺,減少云工程團(tuán)隊(或系統(tǒng)管理員)的干預(yù)以及使開發(fā)團(tuán)隊獨立應(yīng)該是重要目標(biāo)之一。
有時,這種獨立性可能會帶來嚴(yán)重的風(fēng)險。例如,默認(rèn)情況下,在EKS中使用LoadBalancer類型服務(wù)會配置面向ELB的公共網(wǎng)絡(luò)。添加某些注釋將確保提供內(nèi)部ELB。我們在早期就犯了一些錯誤。
我們使用開放策略代理來減少各種安全風(fēng)險,以及降低成本,安全和技術(shù)債務(wù)相關(guān)的風(fēng)險。
部署Open Policy Agent以構(gòu)建正確的控件有助于自動化整個變更管理過程,并為我們的開發(fā)人員構(gòu)建正確的安全網(wǎng)。借助Open Policy Agent,我們可以限制如前所述的方案-除非存在正確的注釋,否則可以限制創(chuàng)建服務(wù)對象,以免開發(fā)人員意外創(chuàng)建公共ELB。
成本
遷移后,我們看到了巨大的成本優(yōu)勢。但是,并非所有好處都會立即產(chǎn)生。
注意:我們正在整理有關(guān)我們最近的成本優(yōu)化計劃得更詳細(xì)的文章。提防Lambda。
更好地利用資源容量
這是最明顯的一個。今天,我們的基礎(chǔ)架構(gòu)所配置的計算,內(nèi)存和存儲遠(yuǎn)遠(yuǎn)少于以前。除了由于更好地包裝容器/過程而提高了容量利用率之外,我們還能夠比以前更好地利用我們的共享服務(wù),例如過程的可觀察性(指標(biāo),日志)。
但是,最初,我們在遷移時浪費了大量資源。由于我們無法正確調(diào)整自我管理的Kubernetes集群,從而導(dǎo)致大量性能問題,因此我們最終要求在Pod中使用大量資源作為緩沖區(qū),更像是保險,以減少因出現(xiàn)故障或性能問題而導(dǎo)致的機會缺乏計算或內(nèi)存。
由于存在較大的資源緩沖區(qū),導(dǎo)致高昂的基礎(chǔ)架構(gòu)成本是一個大問題。由于我們應(yīng)該擁有Kubernetes,我們并沒有真正實現(xiàn)容量利用的任何好處。在遷移到EKS之后,觀察到它帶來的穩(wěn)定性使我們變得更加自信,這幫助我們采取了必要的步驟來糾正資源需求并大幅度減少資源浪費。
實例
與Kubernetes一起使用競價型實例比在原始VM上使用競價型實例要容易得多。使用VM,您可以自己管理競價型實例,這可能會有些復(fù)雜性,無法確保您的應(yīng)用程序具有適當(dāng)?shù)恼_\行時間,或者使用SpotInst等服務(wù)。Kubernetes同樣適用,但是Kubernetes帶來的資源效率可以為您留出足夠的空間來保留一些緩沖區(qū),以便即使集群中的幾個實例被中斷,在其上安排的容器也可以在其他地方快速重新安排。有一些選項可以有效地管理現(xiàn)場中斷。
競價型實例幫助我們節(jié)省了大量資金。今天,我們整個階段的Kubernetes集群都在競價型實例上運行,而我們的生產(chǎn)Kubernetes集群的99%都由預(yù)留實例,節(jié)省計劃和競價型實例覆蓋。
優(yōu)化的下一步是如何在競價型實例上運行整個生產(chǎn)集群。在另一篇博客文章中,有關(guān)此主題的更多信息。
ELB合并
我們使用Ingress在舞臺環(huán)境中整合了ELB,并大幅降低了ELB的固定成本。為了避免這種情況導(dǎo)致代碼之間出現(xiàn)開發(fā)/產(chǎn)品差異,我們決定實現(xiàn)一個控制器,該控制器會將LoadBalancer類型服務(wù)與我們階段集群中的入口對象一起更改為NodePort類型服務(wù)。
對于我們來說,向Nginx入口的遷移相對簡單,并且由于采用了控制器方法,因此無需進(jìn)行大量更改。如果我們也將ingress用于生產(chǎn)中,則可以節(jié)省更多的錢。這不是一個簡單的變化。在以正確的方式配置生產(chǎn)的入口時,必須考慮幾個方面,并且還必須從安全性和API管理的角度來考慮。這是我們打算在不久的將來工作的領(lǐng)域。
增加跨可用區(qū)AZ數(shù)據(jù)傳輸
盡管我們節(jié)省了很多基礎(chǔ)架構(gòu)支出,但仍有一部分基礎(chǔ)架構(gòu)成本增加了-跨可用區(qū)數(shù)據(jù)傳輸。
可以在任何節(jié)點上配置Pod。即使您控制Pod在群集中的分布方式,也沒有一種簡單的方法來控制服務(wù)如何以一種服務(wù)的Pod與同一AZ中的另一服務(wù)的Pod交談的方式來發(fā)現(xiàn)彼此,以減少跨可用區(qū)的數(shù)據(jù)轉(zhuǎn)移。
經(jīng)過與其他公司的同行進(jìn)行大量研究和交談之后,我們了解到可以通過引入服務(wù)網(wǎng)格來控制如何將流量從Pod路由到目標(biāo)Pod來實現(xiàn)。我們還沒有準(zhǔn)備好為了節(jié)省跨可用區(qū)數(shù)據(jù)傳輸?shù)某杀径约撼袚?dān)操作服務(wù)網(wǎng)格的復(fù)雜性。
CRD,Operator和控制器–邁向簡化運營的一步和更全面的體驗
每個組織都有自己的工作流程和運營挑戰(zhàn)。我們也有我們的。
在我們使用Kubernetes的兩年旅程中,我們了解到Kubernetes很棒,但是當(dāng)您使用控制器,Operator和CRD等功能來簡化日常操作并為開發(fā)人員提供更集成的體驗時,Kubernetes會更好。
我們已經(jīng)開始投資大量的控制器和CRD。例如,LoadBalancer服務(wù)類型到入口的轉(zhuǎn)換是控制器操作。同樣,只要部署了新服務(wù),我們就會使用控制器在DNS提供程序中自動創(chuàng)建CNAME記錄。這些是幾個例子。我們還有其他5個單獨的用例,它們依靠我們的內(nèi)部控制器來簡化日常操作并減少工作量。
我們還建立了一些CRD。通過聲明指定應(yīng)使用哪些監(jiān)視儀表板,其中之一已在當(dāng)今廣泛用于在Grafana上生成監(jiān)視儀表板。這使開發(fā)人員可以在其應(yīng)用程序代碼庫旁邊嵌入其監(jiān)視儀表板,并使用相同的工作流(kubectl apply -f)部署所有內(nèi)容。。
我們正在大量看到控制者和CRD的好處。當(dāng)我們與云供應(yīng)商AWS緊密合作以簡化集群基礎(chǔ)架構(gòu)操作時,我們就騰出了更多精力專注于構(gòu)建“ Grofers Kubernetes平臺”,該平臺旨在以最佳方式支持我們的開發(fā)團(tuán)隊。
原文鏈接:https://lambda.grofers.com/learnings-from-two-years-of-kubernetes-in-production-b0ec21aa2814