我在本地和托管 Kubernetes 集群方面工作了七年多。我能說(shuō)的是,容器已經(jīng)徹底改變了托管格局!它帶來(lái)了許多需要復(fù)雜設(shè)置的設(shè)施。擁有多個(gè)實(shí)例,具有滾動(dòng)重啟、零停機(jī)、健康檢查等功能。以前真是費(fèi)時(shí)費(fèi)力(實(shí)現(xiàn) VRRP 解決方案、使用 monit 之類的應(yīng)用程序監(jiān)控重啟、負(fù)載均衡 haproxy 之類的)!
因此,現(xiàn)在使用 Kubernetes 可以更輕松地訪問一切,但如果您想為應(yīng)用程序的生命周期構(gòu)建完美的設(shè)置,您仍然必須了解它的工作原理以及根據(jù)您的情況應(yīng)遵循哪種策略。
在本文中,我將解釋為什么以及如何使用 Kubernetes 實(shí)現(xiàn)零停機(jī)應(yīng)用程序。
容器鏡像位置
如果您已經(jīng)使用Docker一段時(shí)間,那么這看起來(lái)很簡(jiǎn)單。拉取和使用容器鏡像非常簡(jiǎn)單。但是,在生產(chǎn)環(huán)境中,如果您不是映像所有者,您通常不想依賴遠(yuǎn)程且不受控制的映像注冊(cè)表。為什么?
注冊(cè)表可能會(huì)消失,并且您無(wú)法再拉取鏡像( Kubernetes 上出現(xiàn)ImagePullBackOff錯(cuò)誤)
您正在使用的圖像標(biāo)簽已被刪除(相同的ImagePullBackOff錯(cuò)誤)
圖像標(biāo)簽沒有改變,但圖像內(nèi)容不再相同(非不可變圖像,因此圖像哈希值不同)。集群的不同節(jié)點(diǎn)上的圖像之間的行為不相同(取決于標(biāo)簽何時(shí)更改并在集群節(jié)點(diǎn)上拉取)
它不符合您要求控制這些圖像的安全要求(SOC2、HIPPA…)。
存在多種解決方案。一種是將容器映像從源注冊(cè)表同步到您自己的注冊(cè)表。
Pod 數(shù)量(應(yīng)用程序?qū)嵗?/p>
這聽起來(lái)很明顯,但如果您正在尋求高可用性,則您的應(yīng)用程序至少需要2 個(gè) Kubernetes 副本(2 個(gè) Pod)。例子:
apiVersion:apps/v1 kind:Deployment metadata: name:nginx spec: replicas:2#tellsdeploymenttorun2podsmatchingthetemplate template: ..
我多次聽到的關(guān)于 Kubernetes 的一個(gè)常見錯(cuò)誤是:“我不需要兩個(gè)實(shí)例,因?yàn)?Kubernetes 執(zhí)行滾動(dòng)更新,因此它將在關(guān)閉當(dāng)前實(shí)例之前啟動(dòng)一個(gè)新實(shí)例”。確實(shí)如此,但它僅適用于部署更新!
以下是不適用此規(guī)則的其他場(chǎng)景:
當(dāng)您丟失運(yùn)行應(yīng)用程序的節(jié)點(diǎn)時(shí)(節(jié)點(diǎn)崩潰、硬件故障......)。您的應(yīng)用程序pod 必須從頭開始:
1/鏡像拉取(如果節(jié)點(diǎn)上尚未存在):拉取時(shí)間取決于鏡像大小
2/磁盤附件(如果有):需要幾秒鐘(通常觀察到最多 1 分鐘)
3/應(yīng)用程序啟動(dòng):可能會(huì)有所不同,具體取決于受影響的資源和應(yīng)用程序類型(Java 應(yīng)用程序通常需要更長(zhǎng)的時(shí)間才能啟動(dòng))
4 / probes:它們正在等待您的應(yīng)用程序準(zhǔn)備好提供服務(wù),并增加了幾秒鐘的時(shí)間
當(dāng)集群請(qǐng)求節(jié)點(diǎn)耗盡時(shí)(例如在 EKS 升級(jí)或節(jié)點(diǎn)類型更改期間):
要替換的節(jié)點(diǎn)上的 Pod 會(huì)收到SIGTERM信號(hào)以正常停止。Pod 正在從RUNNING狀態(tài)切換到TERMINATING狀態(tài)。此處,Kubernetes 服務(wù)已更新,以停止向TERMINATING pod 發(fā)送流量。因此,您不會(huì)再收到流量并且會(huì)出現(xiàn)停機(jī)時(shí)間。然后創(chuàng)建一個(gè)新的 Pod(請(qǐng)參閱上面的場(chǎng)景),在此期間,您不會(huì)收到任何流量。不幸的是,Kubernetes 在殺死一個(gè) pod 之前不會(huì)啟動(dòng)一個(gè)新的 pod。
這就是為什么設(shè)置兩個(gè)實(shí)例是避免停機(jī)的最低要求(另請(qǐng)參閱 Pod 反關(guān)聯(lián)性部分)。
Pod 中斷預(yù)算
PodDisruptionBudget (PDB) 是一個(gè) Kubernetes 對(duì)象,它指定在部署、維護(hù)或任何給定時(shí)間不可用的 Pod 數(shù)量。這有助于確保您的應(yīng)用程序保持可用,即使某些 pod 被終止或驅(qū)逐也是如此。
讓我們舉一個(gè)例子,我的應(yīng)用程序有三個(gè) pod(實(shí)例);我總是希望始終擁有至少兩個(gè)running;我可以應(yīng)用一個(gè) PDB 對(duì)象,這將保證我始終有至少兩個(gè)正在運(yùn)行的 pod!
apiVersion:policy/v1 kind:PodDisruptionBudget metadata: name:my-pdb spec: maxUnavailable:1 selector: matchLabels: app:my-app
部署策略
Kubernetes 部署有兩種策略:
RollingUpdate:默認(rèn)更新,部署順利。重新創(chuàng)建:在啟動(dòng)較新版本的應(yīng)用程序之前強(qiáng)制應(yīng)用程序完全關(guān)閉。
默認(rèn)情況下,應(yīng)用 RollingUpdate 策略。但是您可以使用其他選項(xiàng)(例如最大不可用百分比和最大激增)來(lái)調(diào)整部署的方式。當(dāng)您面臨繁重的流量負(fù)載并且想要控制部署速度以最大程度地減少性能影響時(shí),這些選項(xiàng)非常有用。
自動(dòng)回滾部署
不幸的是,自動(dòng)回滾并不是 Kubernetes 默認(rèn)提供的功能。一般來(lái)說(shuō),您必須使用 Helm、ArgoCD、Spinnaker 等第三方工具才能實(shí)現(xiàn)自動(dòng)回滾。
大多數(shù)人想要的很簡(jiǎn)單:如果我的應(yīng)用程序無(wú)法正常啟動(dòng),不要向其發(fā)送流量并回滾。
例如,對(duì)于 Helm,使用 Helm 實(shí)現(xiàn)它的一些選項(xiàng)很有趣:
— wait
— wait-for-jobs
— atomic
為了獲得運(yùn)行良好的解決方案,必須設(shè)置并正確配置探針(請(qǐng)參閱下一節(jié))。如果 pod 沒有通過(guò)其活性探針正常啟動(dòng),則會(huì)自動(dòng)回滾。
Probe 探針
不幸的是,探針經(jīng)常被低估,但它們對(duì)于實(shí)現(xiàn)零停機(jī)非常重要!
驗(yàn)證應(yīng)用程序健康狀況的兩個(gè)最重要的探測(cè)器是“Liveness”和“Readiness”探測(cè)器。比長(zhǎng)篇大論更好的是,這里有一個(gè)解釋目標(biāo)的模式:
Kubernetes 探針工作流程
Liveness探針可確保您的應(yīng)用程序處于活動(dòng)狀態(tài),并將決定 pod 是存活還是死亡!
如果活性探測(cè)未成功:
Pod 停止接收流量
Pod 重新啟動(dòng),嘗試恢復(fù)健康狀態(tài)。任何進(jìn)一步的重新啟動(dòng)都會(huì)應(yīng)用指數(shù)退避(指數(shù)延遲)
Readiness 探針決定是否將流量發(fā)送到您的 Pod。
如果您的流量出現(xiàn)突發(fā)(并且活性探針正在響應(yīng)),但您的應(yīng)用程序開始變慢,則就緒狀態(tài)可以決定停止向您的應(yīng)用程序發(fā)送流量。讓它恢復(fù)到更加健康的狀態(tài)。
如果就緒探針沒有響應(yīng),則不會(huì)重新啟動(dòng)您的 Pod。它僅請(qǐng)求負(fù)載均衡器停止向該 Pod 發(fā)送流量。
在什么情況下配置自定義活躍度和就緒度探測(cè)器有用?
答案是“永遠(yuǎn)”!當(dāng)然,您可以使用簡(jiǎn)單的 TCP 檢查,但它永遠(yuǎn)不會(huì)像您自己在應(yīng)用程序中構(gòu)建的自定義探針(例如,REST API 上的專用端點(diǎn))那樣可靠。
初始啟動(dòng)時(shí)間延遲
初始啟動(dòng)時(shí)間可能需要延遲。它可能發(fā)生在不同的情況下:
您的應(yīng)用程序使用大量 CPU 來(lái)啟動(dòng)(例如 SpringBoot 應(yīng)用程序)。
您的應(yīng)用程序需要在啟動(dòng)時(shí)執(zhí)行比以前更多的操作(由于新功能),并且您沒有升級(jí)分配的 CPU 資源。
您的應(yīng)用程序必須加載數(shù)據(jù)庫(kù)中的架構(gòu)和其中的數(shù)據(jù),并且在數(shù)據(jù)庫(kù)準(zhǔn)備就緒之前它才可用。
還存在其他幾個(gè)例子……
但這是可能發(fā)生片狀啟動(dòng)的示例。如果您遇到這種情況或想要預(yù)見它,您應(yīng)該像這樣更新initialDelaySeconds :
livenessProbe: initialDelaySeconds:60 httpGet: ...
注意:存在專用啟動(dòng)探測(cè)器,但在大多數(shù)情況下可能沒有用。一般來(lái)說(shuō),initialDelaySeconds選項(xiàng)就足夠了。
優(yōu)雅終止期 GrancePeriodSeconds
這個(gè) Kubernetes 選項(xiàng)并不直接與零停機(jī)功能相關(guān),而是更多地涉及忽略應(yīng)用程序正常關(guān)閉的重要性的缺點(diǎn)效應(yīng)。
僅當(dāng)應(yīng)用程序能夠攔截 SIGTERM時(shí),優(yōu)雅終止期才能起作用!如果應(yīng)用程序未編碼為攔截 SIGTERM,則它只會(huì)硬終止應(yīng)用程序,無(wú)論是否存在大于 30 秒的優(yōu)雅終止期,這都可能導(dǎo)致數(shù)據(jù)丟失。
不管理 SIGTERM 可能會(huì)帶來(lái)幾個(gè)問題:
糟糕的用戶體驗(yàn):用戶遇到錯(cuò)誤、空白頁(yè)面或更糟的情況
丟失數(shù)據(jù):數(shù)據(jù)尚未提交,用戶事務(wù)丟失
不可恢復(fù)的數(shù)據(jù):刷新磁盤上的數(shù)據(jù)突然停止,您的應(yīng)用程序無(wú)法處理它
還存在其他原因,但您會(huì)看到讓應(yīng)用程序足夠快地關(guān)閉是多么重要。
硬件故障總是有可能的,因此您的應(yīng)用程序應(yīng)該始終能夠在此類故障后恢復(fù)。然而,類似的常規(guī)故障不應(yīng)頻繁發(fā)生。
多給你一點(diǎn)時(shí)間讓你的應(yīng)用程序正常停止通常是很好的做法(<5 分鐘)。Kubernetes 默認(rèn)值為 30 秒,但您可以使用終止GracePeriodSeconds 選項(xiàng)進(jìn)行調(diào)整。
Pod 反親和力
Pod 反關(guān)聯(lián)性可讓您避免同一節(jié)點(diǎn)上存在同一應(yīng)用程序 (Pod) 的多個(gè)實(shí)例。當(dāng)所有實(shí)例都位于同一節(jié)點(diǎn)上時(shí)發(fā)生節(jié)點(diǎn)崩潰時(shí),您可以想象會(huì)發(fā)生停機(jī)。
為了避免這種情況,您可以要求 Kubernetes 避免所有 pod 都位于同一節(jié)點(diǎn)上。存在兩個(gè)版本:
軟反親和性Soft Anti-Affinity
PreferredDuringSchedulingIgnoredDuringExecution:它將盡最大努力避免它,但如果它不能(缺乏資源),它將在同一節(jié)點(diǎn)上添加兩個(gè)實(shí)例。這個(gè)版本具有成本效益,并且在 95% 的情況下都能發(fā)揮作用。
Hard Anti-Affinity
requiredDuringSchedulingIgnoredDuringExecution:這將是一個(gè)硬性要求,不能在同一節(jié)點(diǎn)上有兩個(gè) pod。但如果您要求同一應(yīng)用程序有 50 個(gè) pod,則需要 50 個(gè)節(jié)點(diǎn)。這很快就會(huì)變得非常昂貴。
這是它在 Kubernetes 上的樣子:
affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: -labelSelector: matchExpressions: -key:security operator:In values: -S1 topologyKey:topology.kubernetes.io/zone podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: -weight:100 podAffinityTerm: labelSelector: matchExpressions: -key:security operator:In values: -S2 topologyKey:topology.kubernetes.io/zone
資源
資源是最常見的問題之一。當(dāng)設(shè)置的資源不足時(shí),您的應(yīng)用程序可以:
內(nèi)存不足 (OOM) 并被內(nèi)核驅(qū)逐。所以你會(huì)遇到停機(jī)、連接嚴(yán)重關(guān)閉等情況……
你設(shè)置的CPU夠用了嗎?您的應(yīng)用程序可能需要很長(zhǎng)時(shí)間才能響應(yīng),甚至有時(shí)在活動(dòng)檢查成功之前無(wú)法啟動(dòng)。運(yùn)行 100% 的 CPU 可能會(huì)強(qiáng)制自動(dòng)縮放程序添加過(guò)多的實(shí)例。而您只需要利用當(dāng)前的 CPU 數(shù)量即可。除非您知道自己在做什么,否則低于 100m 通常不好。
自動(dòng)縮放Autoscaling
自動(dòng)縮放是避免流量負(fù)載下停機(jī)的好方法。默認(rèn)基于CPU(可以使用其他自定義指標(biāo))。這是自動(dòng)部署更多實(shí)例(Pod)的簡(jiǎn)單方法。
自動(dòng)縮放并不是魔法!您必須在 Kubernetes 上正確配置您的應(yīng)用程序。
因此,例如,當(dāng)您的 pod 短時(shí)間內(nèi)運(yùn)行超過(guò) 60% 的 CPU 時(shí),Kubernetes 會(huì)觸發(fā)一個(gè)新的 pod 來(lái)處理負(fù)載并減少當(dāng)前正在運(yùn)行的應(yīng)用程序的使用率。
以下是 Kubernetes 上的示例:
apiVersion:autoscaling/v2 kind:HorizontalPodAutoscaler spec: ... minReplicas:1 maxReplicas:10 metrics: -type:Resource resource: name:cpu target: type:Utilization averageUtilization:50
結(jié)論
Kubernetes 確實(shí)有神奇的作用,但只有當(dāng)應(yīng)用程序盡可能是云原生且配置正確時(shí),它才能發(fā)揮神奇作用。
總之,當(dāng)您想將應(yīng)用程序引入 Kubernetes 時(shí),您至少應(yīng)該注意:
最少兩個(gè)實(shí)例
添加健康檢查(探針)
您的應(yīng)用程序必須處理 Sigterm
配置自動(dòng)縮放器
給予足夠的資源
使用 pod 反親和力
添加 PDB
如果一切設(shè)置正確,Kubernetes 體驗(yàn)將令人難以置信,您將不會(huì)再遭受任何停機(jī)。
審核編輯:湯梓紅
-
容器
+關(guān)注
關(guān)注
0文章
521瀏覽量
22723 -
應(yīng)用程序
+關(guān)注
關(guān)注
38文章
3339瀏覽量
59707 -
負(fù)載均衡
+關(guān)注
關(guān)注
0文章
128瀏覽量
12783 -
Docker
+關(guān)注
關(guān)注
0文章
525瀏覽量
13718 -
kubernetes
+關(guān)注
關(guān)注
0文章
254瀏覽量
9332
原文標(biāo)題:結(jié)論
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
Kubernetes Helm入門指南

Kubernetes 網(wǎng)絡(luò)模型如何實(shí)現(xiàn)常見網(wǎng)絡(luò)任務(wù)
利用FTP實(shí)現(xiàn)應(yīng)用程序的遠(yuǎn)程更新
在Windows 10上創(chuàng)建單節(jié)點(diǎn)的Kubernetes實(shí)施示例

首次部署 Kubernetes 應(yīng)用程序需注意的“陷阱”

新版本Portworx PX-Backup助力Kubernetes有狀態(tài)應(yīng)用程序實(shí)現(xiàn)跨云數(shù)據(jù)保護(hù)與遷移

Kubernetes網(wǎng)絡(luò)模型介紹以及如何實(shí)現(xiàn)常見網(wǎng)絡(luò)任務(wù)
KUBERNETES開源平臺(tái)的定義、工作原理及重要意義
Kubernetes網(wǎng)絡(luò)模型的基礎(chǔ)知識(shí)
跟蹤Kubernetes的網(wǎng)絡(luò)流量路徑
Commvault宣布擴(kuò)展面向Kubernetes工作負(fù)載的保護(hù)
如何從零開發(fā)Kubernetes Operator?
探討使用YAML文件定義Kubernetes應(yīng)用程序
Jenkins pipeline是如何連接Kubernetes的呢?

評(píng)論