Kubernetes 的自动伸缩你用对了吗?
作者 | AddoZhang
來(lái)源 | 云原生指北
本文翻譯自 learnk8s 的?Architecting Kubernetes clusters — choosing the best autoscaling strategy[1],有增刪部分內(nèi)容。
TL;DR: 在默認(rèn)設(shè)置下,擴(kuò)展 Kubernetes 集群中的 pod 和節(jié)點(diǎn)可能需要幾分鐘時(shí)間。了解如何調(diào)整集群節(jié)點(diǎn)的大小、配置水平和集群自動(dòng)縮放器以及過(guò)度配置集群以加快擴(kuò)展速度。
自動(dòng)擴(kuò)展器
在 Kubernetes 中,常說(shuō)的“自動(dòng)擴(kuò)展”有:
?HPA:Pod 水平縮放器[2]
?VPA:Pod 垂直縮放器[3]
?CA:集群自動(dòng)縮放器[4]
不同類(lèi)型的自動(dòng)縮放器,使用的場(chǎng)景不一樣。
HPA
HPA 定期檢查內(nèi)存和 CPU 等指標(biāo),自動(dòng)調(diào)整 Deployment 中的副本數(shù),比如流量變化:
調(diào)整前
調(diào)整后
VPA
有些時(shí)候無(wú)法通過(guò)增加 Pod 數(shù)來(lái)擴(kuò)容,比如數(shù)據(jù)庫(kù)。這時(shí)候可以通過(guò) VPA 增加 Pod 的大小,比如調(diào)整 Pod 的 CPU 和內(nèi)存:
調(diào)整前
調(diào)整后
CA
當(dāng)集群資源不足時(shí),CA 會(huì)自動(dòng)配置新的計(jì)算資源并添加到集群中:
調(diào)整前
調(diào)整后
自動(dòng)縮放 Pod 出錯(cuò)時(shí)
比如一個(gè)應(yīng)用需要 1.5 GB 內(nèi)存和 0.25 個(gè) vCPU。一個(gè) 8GB 和 2 個(gè) vCPU 的節(jié)點(diǎn),可以容納 4 個(gè)這樣的 Pod,完美!
做如下配置:
1.HPA:每增加 10 個(gè)并發(fā),增加一個(gè)副本。即 40 個(gè)并發(fā)的時(shí)候,自動(dòng)擴(kuò)展到 4 個(gè)副本。(這里使用自定義指標(biāo),比如來(lái)自 Ingress Controller 的 QPS)
2.CA:在資源不足的時(shí)候,增加計(jì)算節(jié)點(diǎn)。
當(dāng)并發(fā)達(dá)到 30 的時(shí)候,系統(tǒng)是下面這樣。完美!HPA 工作正常,CA 沒(méi)工作。
當(dāng)增加到 40 個(gè)并發(fā)的時(shí)候,系統(tǒng)是下面的情況:
1.HPA 增加了一個(gè) Pod
2.Pod 掛起
3.CA 增加了一個(gè)節(jié)點(diǎn)
HPA 工作
CA 工作
為什么 Pod 沒(méi)有部署成功?
節(jié)點(diǎn)上的操作系統(tǒng)進(jìn)程和 kubelet 也會(huì)消耗一部分資源,8G 和 2 vCPU 并不是全都可以提供給 Pod 用的。并且還有一個(gè)驅(qū)逐閾值[5]:在節(jié)點(diǎn)系統(tǒng)剩余資源達(dá)到閾值時(shí),會(huì)驅(qū)逐 Pod,避免 OOM 的發(fā)生。
當(dāng)然上面的這些都是可配置[6]的。
那為什么在創(chuàng)建該 Pod 之前,CA 沒(méi)有增加新的節(jié)點(diǎn)呢?
CA 如何工作?
CA 在觸發(fā)自動(dòng)縮放時(shí),不會(huì)查看可用的內(nèi)存或 CPU。
CA 是面向事件工作的,并每 10 秒檢查一次是否存在不可調(diào)度(Pending)的 Pod。
當(dāng)調(diào)度器無(wú)法找到可以容納 Pod 的節(jié)點(diǎn)時(shí),這個(gè) Pod 是不可調(diào)度的。
此時(shí),CA 開(kāi)始創(chuàng)建新節(jié)點(diǎn):CA 掃描集群并檢查是否有不可調(diào)度的 Pod。
當(dāng)集群有多種節(jié)點(diǎn)池,CA 會(huì)通過(guò)選擇下面的一種策略:
?random:默認(rèn)的擴(kuò)展器,隨機(jī)選擇一種節(jié)點(diǎn)池
?most-pods:能夠調(diào)度最多 Pod 的節(jié)點(diǎn)池
?least-waste:選擇擴(kuò)展后,資源空閑最少的節(jié)點(diǎn)池
?price:選擇成本最低的節(jié)點(diǎn)池
?priority:選擇用戶分配的具有最高優(yōu)先級(jí)的節(jié)點(diǎn)池
確定類(lèi)型后,CA 會(huì)調(diào)用相關(guān) API 來(lái)創(chuàng)建資源。(云廠商會(huì)實(shí)現(xiàn) API,比如 AWS 添加 EC2;Azure 添加 Virtual Machine;阿里云增加 ECS;GCP 增加 Compute Engine)
計(jì)算資源就緒后,就會(huì)進(jìn)行節(jié)點(diǎn)的初始化[7]。
注意,這里需要一定的耗時(shí),通常比較慢。
探索 Pod 自動(dòng)縮放的前置時(shí)間
四個(gè)因素:
1.HPA 的響應(yīng)耗時(shí)
2.CA 的響應(yīng)耗時(shí)
3.節(jié)點(diǎn)的初始化耗時(shí)
4.Pod 的創(chuàng)建時(shí)間
默認(rèn)情況下,kubelet 每 10 秒抓取一次 Pod 的 CPU 和內(nèi)存占用情況[8]。
每分鐘,Metrics Server 會(huì)將聚合的指標(biāo)開(kāi)放[9]給 Kubernetes API 的其他組件使用。
CA 每 10 秒排查不可調(diào)度的 Pod。[10]
?少于 100 個(gè)節(jié)點(diǎn),且每個(gè)節(jié)點(diǎn)最多 30 個(gè) Pod,時(shí)間不超過(guò) 30s。平均延遲大約 5s。
?100 到 1000個(gè)節(jié)點(diǎn),不超過(guò) 60s。平均延遲大約 15s。
節(jié)點(diǎn)的配置時(shí)間,取決于云服務(wù)商。通常在 3~5 分鐘。
容器運(yùn)行時(shí)創(chuàng)建 Pod:啟動(dòng)容器的幾毫秒和下載鏡像的幾秒鐘。如果不做鏡像緩存,幾秒到 1 分鐘不等,取決于層的大小和梳理。
對(duì)于小規(guī)模的集群,最壞的情況是 6 分 30 秒。對(duì)于 100 個(gè)以上節(jié)點(diǎn)規(guī)模的集群,可能高達(dá) 7 分鐘。
HPA delay:1m30s+CA delay:0m30s+Cloud provider:4m+Container runtime:0m30s+=========================Total6m30s突發(fā)情況,比如流量激增,你是否愿意等這 7 分鐘?
這 7 分鐘,如何優(yōu)化壓縮?
?HPA 的刷新時(shí)間,默認(rèn) 15 秒,通過(guò)?--horizontal-pod-autoscaler-sync-period?標(biāo)志控制。
?Metrics Server 的指標(biāo)抓取時(shí)間,默認(rèn) 60 秒,通過(guò)?metric-resolution?控制。
?CA 的掃描間隔,默認(rèn) 10 秒,通過(guò)?scan-interval?控制。
?節(jié)點(diǎn)上緩存鏡像,比如?kube-fledged[11]?等工具。
即使調(diào)小了上述設(shè)置,依然會(huì)受云服務(wù)商的時(shí)間限制。
那么,如何解決?
兩種嘗試:
1.盡量避免被動(dòng)創(chuàng)建新節(jié)點(diǎn)
2.主動(dòng)創(chuàng)建新節(jié)點(diǎn)
為 Kubernetes 選擇最佳規(guī)格的節(jié)點(diǎn)
這會(huì)對(duì)擴(kuò)展策略產(chǎn)生巨大影響。
這樣的場(chǎng)景
應(yīng)用程序需要 1GB 內(nèi)存和 0.1 vCPU;有一個(gè) 4GB 內(nèi)存和 1 個(gè) vCPU 的節(jié)點(diǎn)。
排除操作系統(tǒng)、kubelet 和閾值保留空間后,有 2.5GB 內(nèi)存和 0.7 個(gè) vCPU 可用。
最多只能容納 2 個(gè) Pod,擴(kuò)展副本時(shí)最長(zhǎng)耗時(shí) 7 分鐘(HPA、CA、云服務(wù)商的資源配置耗時(shí))
假如節(jié)點(diǎn)的規(guī)格是 64GB 內(nèi)存和 16 個(gè) vCPU,可用的資源為 58.32GB 和 15.8 個(gè) vCPU。
這個(gè)節(jié)點(diǎn)可以托管 58 個(gè) Pod。只有擴(kuò)容第 59 個(gè)副本時(shí),才需要?jiǎng)?chuàng)建新的節(jié)點(diǎn)。
CleanShot 2021-06-08 at 23.16.56@2x
這樣觸發(fā) CA 的機(jī)會(huì)更少。
選擇大規(guī)格的節(jié)點(diǎn),還有另外一個(gè)好處:資源的利用率會(huì)更高。
節(jié)點(diǎn)上可以容納的 Pod 數(shù)量,決定了效率的峰值。
物極必反!更大的實(shí)例,并不是一個(gè)好的選擇:
1.爆炸半徑(Blast radius):節(jié)點(diǎn)故障時(shí),少節(jié)點(diǎn)的集群和多節(jié)點(diǎn)的集群,前者影響更大。
2.自動(dòng)縮放的成本效益低:增加一個(gè)大容量的節(jié)點(diǎn),其利用率會(huì)比較低(調(diào)度過(guò)去的 Pod 數(shù)少)
即使選擇了正確規(guī)格的節(jié)點(diǎn),配置新的計(jì)算單元時(shí),延遲仍然存在。怎么解決?
能否提前創(chuàng)建節(jié)點(diǎn)?
為集群過(guò)度配置節(jié)點(diǎn)
即為集群增加備用節(jié)點(diǎn),可以:
1.創(chuàng)建一個(gè)節(jié)點(diǎn),并留空 (比如 SchedulingDisabled)
2.一旦空節(jié)點(diǎn)中有了一個(gè) Pod,馬上創(chuàng)建新的空節(jié)點(diǎn)
CleanShot 2021-06-08 at 23.26.26@2x
這種會(huì)產(chǎn)生額外的成本,但是效率會(huì)提升。
CA 并不支持此功能 -- 總是保留一個(gè)空節(jié)點(diǎn)。
但是,可以偽造。創(chuàng)建一個(gè)只占用資源,不使用資源的 Pod 占用整個(gè) Node 節(jié)點(diǎn)。
一旦有了真正的 Pod,驅(qū)逐占位的 Pod。
待后臺(tái)完成新的節(jié)點(diǎn)配置后,將“占位” Pod 再次占用整個(gè)節(jié)點(diǎn)。
這個(gè)“占位”的 Pod 可以通過(guò)永久休眠來(lái)實(shí)現(xiàn)空間的保留。
apiVersion: apps/v1kind:Deploymentmetadata: name: overprovisioningspec: replicas:1 selector: matchLabels: run: overprovisioningtemplate: metadata: labels: run: overprovisioning spec: containers:- name: pause image: k8s.gcr.io/pause resources: requests: cpu:'1739m' memory:'5.9G'使用優(yōu)先級(jí)和搶占[12],來(lái)實(shí)現(xiàn)創(chuàng)建真正的 Pod 后驅(qū)逐“占位”的 Pod。
使用?PodPriorityClass?在配置 Pod 優(yōu)先級(jí):
apiVersion: scheduling.k8s.io/v1beta1kind:PriorityClassmetadata: name: overprovisioningvalue:-1#默認(rèn)的是 0,這個(gè)表示比默認(rèn)的低globalDefault:falsedescription:'Priority class used by overprovisioning.'為“占位” Pod 配置優(yōu)先級(jí):
apiVersion: apps/v1kind:Deploymentmetadata: name: overprovisioningspec: replicas:1 selector: matchLabels: run: overprovisioningtemplate: metadata: labels: run: overprovisioning spec: priorityClassName: overprovisioning #HERE containers:- name: reserve-resources image: k8s.gcr.io/pause resources: requests: cpu:'1739m' memory:'5.9G'已經(jīng)做完過(guò)度配置,應(yīng)用程序是否需要優(yōu)化?
為 Pod 選擇正確的內(nèi)存和 CPU 請(qǐng)求
Kubernetes 是根據(jù) Pod 的內(nèi)存和 CPU 請(qǐng)求,為其分配節(jié)點(diǎn)。
如果 Pod 的資源請(qǐng)求配置不正確,可能會(huì)過(guò)晚(或過(guò)早)觸發(fā)自動(dòng)縮放器。
這樣一個(gè)場(chǎng)景:
?應(yīng)用程序平均負(fù)載下消耗 512MB 內(nèi)存和 0.25 個(gè) vCPU。
?高峰時(shí),消耗 4GB 內(nèi)存 和 1 個(gè) vCPU。(即資源限制,Limit)
有三種請(qǐng)求的配置選擇:
1.遠(yuǎn)低于平均使用量
2.匹配平均使用量
3.盡量接近限制
第一種的問(wèn)題在于超賣(mài)嚴(yán)重,過(guò)度使用節(jié)點(diǎn)。kubelet 負(fù)載高,穩(wěn)定性差。
第三種,會(huì)造成資源的利用率低,浪費(fèi)資源。這種通常被稱(chēng)為?QoS:Quality of Service class[13]?中的?Guaranteed?級(jí)別,Pod 不會(huì)被終止和驅(qū)逐。
如何在穩(wěn)定性和資源使用率間做權(quán)衡?
這就是?QoS:Quality of Service class[14]?中的?Burstable?級(jí)別,即 Pod 偶爾會(huì)使用更多的內(nèi)存和 CPU。
1.如果節(jié)點(diǎn)中有可用資源,應(yīng)用程序會(huì)在返回基線(baseline)前使用這些資源。
2.如果資源不足,Pod 將競(jìng)爭(zhēng)資源(CPU),kubelet 也有可能?chē)L試驅(qū)逐 Pod(內(nèi)存)。
在?Guaranteed?和?Burstable?之前如何做選擇?取決于:
1.想盡量減少 Pod 的重新調(diào)度和驅(qū)逐,應(yīng)該是用?Guaranteed。
2.如果想充分利用資源時(shí),使用?Burstable。比如彈性較大的服務(wù),Web 或者 REST 服務(wù)。
如何做出正確的配置?
應(yīng)該分析應(yīng)用程序,并測(cè)算空閑、負(fù)載和峰值時(shí)的內(nèi)存和 CPU 消耗。
甚至可以通過(guò)部署 VPA 來(lái)自動(dòng)調(diào)整。
如何進(jìn)行集群縮容?
每 10 秒,當(dāng)請(qǐng)求(request)利用率低于 50%時(shí),CA 才會(huì)決定刪除節(jié)點(diǎn)。
CA 會(huì)匯總同一個(gè)節(jié)點(diǎn)上的所有 Pod 的 CPU 和內(nèi)存請(qǐng)求。小于節(jié)點(diǎn)容量的一半,就會(huì)考慮對(duì)當(dāng)前節(jié)點(diǎn)進(jìn)行縮減。
需要注意的是,CA 不考慮實(shí)際的 CPU 和內(nèi)存使用或者限制(limit),只看請(qǐng)求(request)。
移除節(jié)點(diǎn)之前,CA 會(huì):
1.檢查 Pod[15]?確??梢哉{(diào)度到其他節(jié)點(diǎn)上。
2.檢查節(jié)點(diǎn)[16],避免節(jié)點(diǎn)被過(guò)早的銷(xiāo)毀,比如兩個(gè)節(jié)點(diǎn)的請(qǐng)求都低于 50%。
檢查都通過(guò)之后,才會(huì)刪除節(jié)點(diǎn)。
為什么不根據(jù)內(nèi)存或 CPU 進(jìn)行自動(dòng)縮放?
基于內(nèi)存和 CPU 的自動(dòng)縮放器,不關(guān)進(jìn) pod。
比如配置縮放器在節(jié)點(diǎn)的 CPU 達(dá)到總量的 80%,就自動(dòng)增加節(jié)點(diǎn)。
當(dāng)你創(chuàng)建 3 個(gè)副本的 Deployment,3 個(gè)節(jié)點(diǎn)的 CPU 達(dá)到了 85%。這時(shí)會(huì)創(chuàng)建一個(gè)節(jié)點(diǎn),但你并不需要第 4 個(gè)副本,新的節(jié)點(diǎn)就空閑了。
不建議使用這種類(lèi)型的自動(dòng)縮放器。
總結(jié)
定義和實(shí)施成功的擴(kuò)展策略,需要掌握以下幾點(diǎn):
?節(jié)點(diǎn)的可分配資源。
?微調(diào) Metrics Server、HPA 和 CA 的刷新間隔。
?設(shè)計(jì)集群和節(jié)點(diǎn)的規(guī)格。
?緩存容器鏡像到節(jié)點(diǎn)。
?應(yīng)用程序的基準(zhǔn)測(cè)試和分析。
配合適當(dāng)?shù)谋O(jiān)控工具,可以反復(fù)測(cè)試擴(kuò)展策略并調(diào)整集群的縮放速度和成本。
引用鏈接
[1]?Architecting Kubernetes clusters — choosing the best autoscaling strategy:?https://learnk8s.io/kubernetes-autoscaling-strategies#when-autoscaling-pods-goes-wrong
[2]?HPA:Pod 水平縮放器:?https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
[3]?VPA:Pod 垂直縮放器:?https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler
[4]?CA:集群自動(dòng)縮放器:?https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler
[5]?驅(qū)逐閾值:?https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/#eviction-thresholds
[6]?可配置:?https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/#node-allocatable
[7]?節(jié)點(diǎn)的初始化:?https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/
[8]?kubelet 每 10 秒抓取一次 Pod 的 CPU 和內(nèi)存占用情況:?https://github.com/kubernetes/kubernetes/blob/2da8d1c18fb9406bd8bb9a51da58d5f8108cb8f7/pkg/kubelet/kubelet.go#L1855
[9]?每分鐘,Metrics Server 會(huì)將聚合的指標(biāo)開(kāi)放:?https://github.com/kubernetes-sigs/metrics-server/blob/master/FAQ.md#how-often-metrics-are-scraped
[10]?CA 每 10 秒排查不可調(diào)度的 Pod。:?https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#how-does-scale-up-work
[11]?kube-fledged:?https://github.com/senthilrch/kube-fledged
[12]?優(yōu)先級(jí)和搶占:?https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/
[13]?QoS:Quality of Service class:?https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#qos-classes
[14]?QoS:Quality of Service class:?https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#qos-classes
[15]?檢查 Pod:?https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-types-of-pods-can-prevent-ca-from-removing-a-node
[16]?檢查節(jié)點(diǎn):?https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#i-have-a-couple-of-nodes-with-low-utilization-but-they-are-not-scaled-down-why
往期推薦
如果讓你來(lái)設(shè)計(jì)網(wǎng)絡(luò)
這種本機(jī)網(wǎng)絡(luò) IO 方法,性能可以翻倍!
留不住客戶?該從你的系統(tǒng)上找找原因了!
明明還有大量?jī)?nèi)存,為啥報(bào)錯(cuò)“無(wú)法分配內(nèi)存”?
點(diǎn)分享
點(diǎn)收藏
點(diǎn)點(diǎn)贊
點(diǎn)在看
總結(jié)
以上是生活随笔為你收集整理的Kubernetes 的自动伸缩你用对了吗?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 开发者看过来,5 行代码实现身份认证,A
- 下一篇: Colima:MacOS 上的极简容器运