需要盡早知道的Kubernetes最佳實(shí)踐
我希望能早點(diǎn)知道的Kubernetes最佳實(shí)踐。從我在生產(chǎn)環(huán)境中使用Kubernetes的經(jīng)驗(yàn)中學(xué)習(xí),并避免常見(jiàn)的陷阱。
譯自Kubernetes Best Practices I Wish I Had Known Before,作者 None。
Kubernetes 無(wú)可否認(rèn)地改變了我們構(gòu)建、交付和運(yùn)行應(yīng)用程序的方式。但說(shuō)實(shí)話,開(kāi)始使用 Kubernetes 感覺(jué)就像穿著人字拖攀登珠穆朗瑪峰一樣。
作為一名云原生開(kāi)發(fā)者和 Kubernetes 愛(ài)好者,我通過(guò)艱難的經(jīng)驗(yàn)學(xué)習(xí)到了一些“早知道就好了”的最佳實(shí)踐。這些實(shí)踐本來(lái)可以為我節(jié)省時(shí)間、金錢和麻煩。
圖片
“Kubernetes 很容易”的冰山一角 meme 是 Kubernetes 具有欺騙性復(fù)雜性的經(jīng)典示例
在這篇文章中,我將重點(diǎn)介紹一些重要的 Kubernetes 最佳實(shí)踐。這些實(shí)踐來(lái)自我在生產(chǎn)環(huán)境中使用 Kubernetes 多年的經(jīng)驗(yàn)。您可以將此視為您從第一天起就希望擁有的精選“Kubernetes 速查表”。系好安全帶;這將是一次激動(dòng)人心的旅程。
1. 不要吝嗇資源請(qǐng)求和限制
在 Kubernetes 中的第一個(gè)“啊哈!”時(shí)刻之一是意識(shí)到您可以定義容器請(qǐng)求(保證的資源)和限制(允許的最大值)的 CPU 和內(nèi)存數(shù)量。棘手的部分是:跳過(guò)這些設(shè)置可能會(huì)給您帶來(lái)麻煩。
- 資源請(qǐng)求(Requests):這基本上是您容器的基線。如果您的容器請(qǐng)求 200m CPU 和 512Mi 內(nèi)存,Kubernetes 調(diào)度程序?qū)涯?Pod 部署到至少具有這么多可用容量的節(jié)點(diǎn)上。
- 資源限制(Limits):這是上限。如果您的容器試圖超過(guò)限制,它可能會(huì)被限制(CPU)甚至被驅(qū)逐(內(nèi)存)。
專業(yè)提示:
- 從某個(gè)基線開(kāi)始,也許是 100-200m CPU、128-512Mi 內(nèi)存,然后在收集更多數(shù)據(jù)時(shí)進(jìn)行調(diào)整。
- 使用 Prometheus 或 Datadog 等監(jiān)控工具來(lái)分析實(shí)際使用情況并根據(jù)需要進(jìn)行調(diào)整。
2. 像你的生命依賴它一樣使用命名空間
如果您將所有內(nèi)容都部署到默認(rèn)命名空間中,哦,男孩,是時(shí)候進(jìn)行干預(yù)了。命名空間是一種簡(jiǎn)單而強(qiáng)大的機(jī)制,用于組織(和隔離)集群中的資源。
- 基于團(tuán)隊(duì)的命名空間:開(kāi)發(fā)、測(cè)試、生產(chǎn)或每個(gè)微服務(wù)(如果合適)。
- 訪問(wèn)控制:將命名空間與 RBAC(基于角色的訪問(wèn)控制)策略結(jié)合使用,以確保只有合適的人員(和服務(wù))才能訪問(wèn)您的資源。
- 資源配額:您可以為每個(gè)命名空間設(shè)置配額(例如,CPU、內(nèi)存),防止一個(gè)流氓微服務(wù)占用所有資源。
退一步,設(shè)計(jì)您的命名空間策略;未來(lái)的您會(huì)感謝您的。
3. 除非必要,否則避免在一個(gè) Pod 中運(yùn)行多個(gè)容器
是的,一個(gè) Pod 可以包含多個(gè)容器。但是應(yīng)該嗎?通常,只有當(dāng)容器緊密耦合并且必須共享資源(如卷或網(wǎng)絡(luò)命名空間)(例如,用于日志記錄或安全代理的 sidecar 模式)時(shí),您才需要在同一個(gè) Pod 中使用多個(gè)容器。
為什么要避免多容器 Pod?
- 復(fù)雜性:對(duì)單個(gè) Pod 中的多個(gè)容器進(jìn)行故障排除可能很痛苦。
- 耦合:您失去了獨(dú)立擴(kuò)展容器的優(yōu)勢(shì)。如果您需要擴(kuò)展一個(gè)容器,您最終會(huì)擴(kuò)展該 Pod 中的所有內(nèi)容。
遵循“每個(gè) Pod 一個(gè)容器”的經(jīng)驗(yàn)法則,除非您有令人信服的理由(例如 sidecar 模式)。
4. 使用包管理器管理您的 YAML 文件
手動(dòng)處理跨多個(gè)微服務(wù)的數(shù)百個(gè) YAML 文件,就像凌晨 3 點(diǎn)調(diào)試意大利面條代碼一樣有趣。這就是 Helm、Kustomize 或 Timoni 等工具的用武之地。
- Helm: Kubernetes 的“包管理器”。它使用您可以通過(guò)值自定義的 Chart(模板)。
- Kustomize: 一個(gè)原生 Kubernetes 工具,允許您在基本 YAML 清單上疊加更改。
- Timoni: Timoni 是一個(gè) Kubernetes 包管理器,由 CUE 提供支持,并受 Helm 的啟發(fā)。
專業(yè)提示:如果您不熟悉 Helm,請(qǐng)從 Helm Hub 或 Artifact Hub 中的官方 Chart 開(kāi)始。然后根據(jù)您的喜好進(jìn)行自定義。您將避免 YAML 重復(fù)的困擾。
或者,試用Pulumi并使用真正的編程語(yǔ)言來(lái)管理您的 Kubernetes 基礎(chǔ)設(shè)施。
5. Ingress 和網(wǎng)絡(luò)最佳實(shí)踐
在 Kubernetes 中,網(wǎng)絡(luò)可能會(huì)很快變得復(fù)雜。在服務(wù)、Ingress 控制器和負(fù)載均衡器之間,很容易陷入困境。請(qǐng)記住以下幾點(diǎn):
- 使用 Ingress 控制器/Gateway API(NGINX、Traefik、HAProxy、Istio Gateway 等)來(lái)管理外部訪問(wèn)。
- 利用基于路徑和基于子域的路由來(lái)簡(jiǎn)化您的網(wǎng)絡(luò)拓?fù)洹?/li>
- TLS 終止:在您的入口層終止 SSL/TLS。您可以卸載證書管理(例如,通過(guò) cert-manager)并保持集群流量的安全和高效。
- Ingress是Kubernetes中一個(gè)強(qiáng)大的概念,請(qǐng)花時(shí)間正確設(shè)置它。混亂的Ingress配置就像通往漂亮大宅的坑坑洼洼的車道。
圖片
6. 依靠存活性探針、就緒探針和啟動(dòng)探針
Kubernetes有點(diǎn)像個(gè)人助理,但它需要清晰的指令。如果沒(méi)有正確配置存活性探針、就緒探針和啟動(dòng)探針,您的集群將無(wú)法判斷容器的健康狀況。
- 存活性探針: 檢查您的容器是否存活。如果失敗,Kubernetes將重啟容器。
- 就緒探針: 檢查您的容器是否已準(zhǔn)備好接收流量。在準(zhǔn)備好之前,它不會(huì)接收流量。
- 啟動(dòng)探針: 對(duì)于啟動(dòng)需要一段時(shí)間才能完成的應(yīng)用程序非常有用。它可以防止容器在初始加載期間過(guò)早被終止。
專業(yè)提示:在存活性探針之前先使用就緒探針。您不希望您的容器僅僅因?yàn)樯形礈?zhǔn)備好就被終止。微調(diào)閾值、周期和超時(shí)參數(shù)。
7. 注意您的安全:RBAC、Pod安全性和密鑰
在Kubernetes中,安全不僅僅是錦上添花——它是至關(guān)重要的。如果您的集群遭到破壞,游戲就結(jié)束了。
1) RBAC(基于角色的訪問(wèn)控制):
- 從第一天起就實(shí)施它。
- 使用最小權(quán)限原則。只為每個(gè)用戶、服務(wù)帳戶或應(yīng)用程序提供他們所需的訪問(wèn)權(quán)限。
2)Pod安全:
- 使用Pod安全準(zhǔn)入功能來(lái)執(zhí)行標(biāo)準(zhǔn)(例如,不允許特權(quán)容器)。
- 確保您不是在絕對(duì)必要的情況下才以root用戶身份運(yùn)行容器。
3)正確管理密鑰:
- 不要在容器鏡像或環(huán)境變量中以純文本形式存儲(chǔ)憑據(jù)或API密鑰。
- 使用外部密鑰操作符或密鑰存儲(chǔ)CSI驅(qū)動(dòng)程序?qū)⒚荑€存儲(chǔ)在外部密鑰存儲(chǔ)中,例如AWS密鑰管理器、Pulumi ESC或HashiCorp Vault。
8. 監(jiān)控一切(然后更多地監(jiān)控)
在Kubernetes中,監(jiān)控不是可選的——而是強(qiáng)制性的。隨著容器不斷出現(xiàn)和消失,您需要強(qiáng)大的可觀察性來(lái)了解幕后發(fā)生的事情。
Prometheus + Grafana:度量和儀表板的經(jīng)典組合。
- ELK / EFK /Grafana Loki堆棧:Elastic(或OpenSearch)用于日志,加上Kibana和Fluentd/Fluent Bit用于日志收集或Grafana Loki用于日志。
- Jaeger / Zipkin / Tempo:如果您有相互調(diào)用的微服務(wù),則用于分布式跟蹤。
盡早設(shè)置警報(bào)。您不希望您第一次遇到麻煩是午夜時(shí)分從憤怒的用戶那里得到“為什么應(yīng)用程序這么慢?”的消息。
9. 使用CI/CD自動(dòng)化部署
Kubernetes最大的優(yōu)勢(shì)之一是它使自動(dòng)化整個(gè)發(fā)布過(guò)程變得更容易。如果您仍在進(jìn)行手動(dòng)部署,那么現(xiàn)在是時(shí)候轉(zhuǎn)向CI/CD管道了。
- Jenkins、GitLab、GitHub Actions,您可以選擇。
- 擁抱GitOps:將所有清單存儲(chǔ)在Git中,并讓像Flux或Argo CD這樣的工具將它們同步到您的集群。
- 如果部署失敗,則自動(dòng)回滾。
- 自動(dòng)化不僅加快了交付速度,而且還大大減少了人為錯(cuò)誤的空間。
10. 保持Kubernetes集群和組件更新
運(yùn)行過(guò)時(shí)的Kubernetes版本就像在2025年使用運(yùn)行iOS 6的手機(jī)一樣。不可取。
Kubernetes發(fā)布周期: 次要版本大約每三個(gè)月發(fā)布一次,補(bǔ)丁程序發(fā)布頻率更高。
升級(jí)策略:
- 首先在開(kāi)發(fā)環(huán)境中進(jìn)行測(cè)試。
- 備份您的etcd(鍵值存儲(chǔ))。
- 升級(jí)控制平面,然后升級(jí)工作節(jié)點(diǎn),或者使用為您處理部分此工作的托管服務(wù)(例如,EKS、GKE、AKS)。
保持您的依賴項(xiàng)更新(例如,容器運(yùn)行時(shí)、CNI插件等),以從最新的安全性和性能改進(jìn)中受益。
11. 明智地使用標(biāo)簽和注釋
標(biāo)簽(Labels)和注釋(Annotations)乍一看似乎微不足道,但它們對(duì)于組織良好的集群來(lái)說(shuō)是改變游戲規(guī)則的關(guān)鍵。
- 標(biāo)簽: 用于 Kubernetes 對(duì)象分組和選擇的鍵值對(duì)。例如,app=my-app、env=staging、team=payments。
- 注釋: 用于附加非標(biāo)識(shí)元數(shù)據(jù)的鍵值對(duì)(例如,版本信息、聯(lián)系郵箱或上次部署時(shí)間戳)。一致的標(biāo)簽策略有助于快速過(guò)濾資源并維護(hù)集群的清晰思維導(dǎo)圖。
12. 采用多環(huán)境方法
如果您的開(kāi)發(fā)、登臺(tái)和生產(chǎn)環(huán)境共享一個(gè)集群,您就是在玩火。雖然可以這樣做,但最佳實(shí)踐是將生產(chǎn)工作負(fù)載與測(cè)試環(huán)境隔離。
- 獨(dú)立集群: 至少為開(kāi)發(fā)/登臺(tái)環(huán)境和生產(chǎn)環(huán)境各準(zhǔn)備一個(gè)集群。有一些工具,例如vCluster,可以在單個(gè)集群中創(chuàng)建虛擬集群。
- 命名空間隔離: 如果您必須在同一個(gè)集群中運(yùn)行它們,請(qǐng)使用嚴(yán)格的基于命名空間的隔離和 RBAC 規(guī)則。 保持環(huán)境分離可以降低風(fēng)險(xiǎn),并使在沙箱中測(cè)試新功能更容易。
13. 優(yōu)化您的容器鏡像
不要交付包含一半 Ubuntu 系統(tǒng)以及隨機(jī)殘留文件的龐大容器鏡像。這會(huì)導(dǎo)致部署緩慢和資源浪費(fèi)。
- 使用輕量級(jí)基礎(chǔ)鏡像,例如distroless、alpine 或基于最小操作系統(tǒng)的鏡像。
- 清理 Dockerfile 中的臨時(shí)文件和依賴項(xiàng)。
- 使用諸如Trivy或Anchore之類的工具定期掃描您的鏡像是否存在漏洞。
14. 實(shí)施可靠的日志記錄策略
日志是您進(jìn)行故障排除的首選工具,在 Kubernetes 中,您需要一個(gè)能夠處理短暫 Pod 的解決方案。
- 集中式日志記錄: 無(wú)論是 ELK/EFK、Splunk 還是托管服務(wù),請(qǐng)確保日志不會(huì)僅僅存儲(chǔ)在短暫的容器存儲(chǔ)中。
- 結(jié)構(gòu)化日志記錄: JSON 或其他結(jié)構(gòu)化格式有助于您的日志系統(tǒng)更有效地解析和過(guò)濾日志。
- 日志保留和輪換: 定義明確的策略以防止日志存儲(chǔ)膨脹。
相信我,您不希望在生產(chǎn)事故發(fā)生時(shí)四處尋找日志。
15. 將 Kubernetes 當(dāng)作牲畜,而不是寵物
服務(wù)器的古老格言——將它們視為牲畜,而不是寵物——也適用于 Kubernetes。不要依賴手動(dòng)修復(fù)或人工干預(yù)。盡可能爭(zhēng)取不變的基礎(chǔ)設(shè)施:
- 如果 Pod 出現(xiàn)問(wèn)題,請(qǐng)?jiān)?YAML、Code或容器鏡像中修復(fù)它,重新部署,然后讓舊的 Pod 消失。
- 避免對(duì)正在運(yùn)行的容器進(jìn)行偷偷摸摸的“快速修復(fù)”——這些更改會(huì)在 Kubernetes 重新啟動(dòng) Pod 的那一刻消失。
- 擁抱短暫的環(huán)境和動(dòng)態(tài)擴(kuò)展。這就是 Kubernetes 最擅長(zhǎng)的事情!
16. 對(duì)于復(fù)雜的部署,考慮更高級(jí)的方法
雖然原生 YAML 清單可以用于較小的 Kubernetes 部署,但隨著項(xiàng)目和團(tuán)隊(duì)的增長(zhǎng),它們往往會(huì)變得難以管理。Pulumi為部署自動(dòng)化提供了一個(gè)強(qiáng)大的替代方案,它提供:
- 真正的編程語(yǔ)言: 使用 TypeScript、JavaScript、Python、Go、Java 或 C#用于類型安全、可測(cè)試的基礎(chǔ)設(shè)施代碼。
- 跨云靈活性: 使用單個(gè)工具管理多個(gè)云提供商和 Kubernetes 中的資源。
- 可重用模塊: 將常見(jiàn)模式抽象為可重用組件,減少樣板代碼并防止漂移。
- 強(qiáng)大的工具和生態(tài)系統(tǒng): 從包管理器、IDE 集成和豐富的共享 Pulumi 組件庫(kù)中受益。
通過(guò)采用 Pulumi,您可以避免處理無(wú)數(shù) YAML 文件的復(fù)雜性,并為您的 Kubernetes 基礎(chǔ)設(shè)施獲得更精簡(jiǎn)、更易于維護(hù)的工作流程。
Kubernetes 就像一把瑞士軍刀:功能強(qiáng)大、用途廣泛,但如果您不小心,也很容易誤用。通過(guò)采用這些最佳實(shí)踐、聲明式配置、合理的資源分配、強(qiáng)大的安全性、強(qiáng)大的可觀察性和自動(dòng)部署,您可以使您的集群平穩(wěn)運(yùn)行。
如果您已經(jīng)以艱難的方式吸取了一些教訓(xùn),那么您并不孤單。但是 Kubernetes 的好處在于,每一次挫折都會(huì)讓您獲得更多經(jīng)驗(yàn)來(lái)微調(diào)您的方法。