一文帶你掌握Kubernetes VPA(Pod縱向自動擴縮)
簡介
之前的文章我們介紹了HPA(Horizontal Pod Autoscaler)的實現(xiàn),HPA一般被稱為橫向擴展,與HPA不同的Vertical Pod Autoscaler ( VPA ) 會自動調(diào)整 Pod 的 CPU 和內(nèi)存屬性,被稱為縱向擴展。VPA可以給出服務(wù)運行所適合的CPU和內(nèi)存配置,省去估計服務(wù)占用資源的時間,更合理的使用資源。當(dāng)然,VPA也可根據(jù)資源的使用情況“調(diào)整”pod的資源。這里的調(diào)整我們用了雙引號,因為他的實現(xiàn)機制是重建而不是動態(tài)增加。下面是一個實際的例子:假設(shè)我的memory limits是100Mi,但是現(xiàn)在已經(jīng)用到了98Mi,如果再大的話就oom了,此時vpa會在垂直方向上提升你的memory limits的大小。這種vpa比較適合一些資源消耗比較大的應(yīng)用,例如es,你給大了資源浪費,給小了,又不夠。所以vpa就派上用場了。當(dāng)然,vpa不像hpa默認集成在k8s里面的,需要你自己去配置的。
VPA 與 HPA
從根本上來說,VPA 和 HPA 之間的區(qū)別在于它們的擴展方式。HPA 通過添加或刪除pod進行擴展,從而水平擴展容量。然而,VPA 通過增加或減少現(xiàn)有 Pod 容器內(nèi)的 CPU 和內(nèi)存資源來進行擴展,從而垂直擴展容量。下表更詳細地解釋了 Kubernetes VPA 和 HPA 之間的差異。
需要調(diào)整容量 | 水平縮放 (HPA) | 垂直縮放 (VPA) |
更多資源 | 添加更多 Pod | 增加現(xiàn)有 pod 容器的 CPU 或內(nèi)存資源 |
資源較少 | 刪除 Pod | 減少現(xiàn)有 Pod 容器的 CPU 或內(nèi)存資源 |
工作原理
圖片
VPA 的組成部分
VPA 部署具有三個主要組件:VPA Recommender、VPA Updater和VPA Admission Controller。讓我們看一下每個組件的作用。VPA Recommender:
- 監(jiān)控資源利用率并計算目標值。
- 查看指標歷史記錄、OOM 事件和 VPA 部署規(guī)范并建議公平請求。根據(jù)定義的限制請求比例提高/降低限制。
VPA 更新程序:
- 驅(qū)逐那些需要新資源限制的 Pod。
- 如果定義了“updateMode: Auto”,則實現(xiàn)推薦器建議的任何內(nèi)容。
VPA 準入控制器:
- 每當(dāng) VPA 更新程序逐出并重新啟動 Pod 時,都會在新 Pod 啟動之前更改 CPU 和內(nèi)存設(shè)置(使用 Webhook)。
- 當(dāng) Vertical Pod Autoscaler 設(shè)置為“Auto”的 updateMode 時,如果需要更改 Pod 的資源請求,則驅(qū)逐 Pod。由于 Kubernetes 的設(shè)計,修改正在運行的 pod 的資源請求的唯一方法是重新創(chuàng)建 pod。
Kubernetes VPA 工作模式
圖片
- 用戶配置VPA。
- VPA Recommender 從指標服務(wù)器讀取 VPA 配置和資源利用率指標。
- VPA Recommender 提供 Pod 資源推薦。
- VPA Updater 讀取 Pod 資源建議。
- VPA Updater 啟動 Pod 終止。
- 部署意識到 Pod 已終止,并將重新創(chuàng)建 Pod 以匹配其副本配置。
- 當(dāng) Pod 處于重新創(chuàng)建過程中時,VPA 準入控制器會獲取 Pod 資源推薦。由于 Kubernetes 不支持動態(tài)更改正在運行的 pod 的資源限制,因此 VPA 無法使用新的限制更新現(xiàn)有 pod。它會終止使用過時限制的 pod。當(dāng) Pod 的控制器向 Kubernetes API 服務(wù)請求替換時,VPA 準入控制器會將更新的資源請求和限制值注入到新 Pod 的規(guī)范中。
- 最后,VPA 準入控制器會覆蓋對 Pod 的建議。在我們的示例中,VPA 準入控制器向 Pod 添加了一個“250m”CPU。
最佳實踐
既然你知道了大致原理,讓我們開始動手操作你吧
克隆代碼
# git clone https://github.com/kubernetes/autoscaler.git
由于某些原因拉不到鏡像,改yaml修改優(yōu)先使用本地鏡像
# cd autoscaler/vertical-pod-autoscaler/deploy
# sed -i 's/Always/IfNotPresent/g' recommender-deployment.yaml
# sed -i 's/Always/IfNotPresent/g' admission-controller-deployment.yaml
# sed -i 's/Always/IfNotPresent/g' updater-deployment.yaml
# 拉取鏡像
# docker pull giantswarm/vpa-admission-controller:0.14.0
# docker pull giantswarm/vpa-recommender:0.14.0
# docker pull giantswarm/vpa-updater:0.14.0
# 修改tag
# docker tag giantswarm/vpa-updater:0.14.0 registry.k8s.io/autoscaling/vpa-updater:0.14.0
# docker tag giantswarm/vpa-recommender:0.14.0 registry.k8s.io/autoscaling/vpa-recommender:0.14.0
# docker tag giantswarm/vpa-admission-controller:0.14.0 registry.k8s.io/autoscaling/vpa-admission-controller:0.14.0
# cd autoscaler/vertical-pod-autoscaler/hack
# 安裝腳本安裝之前保證你的K8S集群的metrics-server已安裝,并且openssl升級到1.1.1或更高版本
# ./vpa-up.sh
等待安裝完成
# kubectl get pods -n kube-system | grep vpa
kube-system vpa-admission-controller-75bffbf8d8-6hxqq 1/1 Running 0 5m9s
kube-system vpa-recommender-748c55b5bf-kqqjc 1/1 Running 0 4m34s
kube-system vpa-updater-679d5dcdd6-lslc7 1/1 Running 0 4m15s
使用VPA,您需要為要自動計算資源需求的每個控制器插入一個Vertical Pod Autoscaler資源。這將是最常見的Deployment。VPA有四種運行模式
- "Auto":VPA 在創(chuàng)建 pod 時分配資源請求,并使用首選更新機制在現(xiàn)有 pod 上更新它們。目前這相當(dāng)于"Recreate"(見下文)。一旦 pod 請求的免重啟(“就地”)更新可用,它可能會被該"Auto"模式用作首選的更新機制。注意:VPA 的此功能是實驗性的,可能會導(dǎo)致您的應(yīng)用程序停機,當(dāng)目前運行的pod的資源達不到VPA的推薦值,就會執(zhí)行pod驅(qū)逐,重新部署新的足夠資源的服務(wù)
- "Recreate":VPA 在創(chuàng)建 Pod 時分配資源請求,并在現(xiàn)有 Pod 上更新它們,當(dāng)請求的資源與新建議有很大差異時(尊重 Pod 中斷預(yù)算,如果定義)。這種模式應(yīng)該很少使用,只有當(dāng)您需要確保在資源請求發(fā)生變化時重新啟動 Pod 時。否則,更喜歡這種"Auto"模式,一旦它們可用,就可以利用重新啟動免費更新。注意:VPA 的此功能是實驗性的,可能會導(dǎo)致您的應(yīng)用程序停機
- "Initial":VPA 僅在創(chuàng)建 pod 時分配資源請求,以后不會更改它們
- "Off":VPA 不會自動更改 Pod 的資源需求。這些建議是經(jīng)過計算的,并且可以在 VPA 對象中進行檢查。這種模式僅獲取資源推薦值,但是不更新Pod
創(chuàng)建一個updateMode: Auto 的VPA
# 將updateMode中的requests 改為 CPU:50m,Memory: 50Mi,同時將updateMode修改為Auto
# 創(chuàng)建一個pod和svc
# kubectl get pods -n vpa
NAME READY STATUS RESTARTS AGE
nginx-8454bb78d8-67pth 1/1 Running 0 9s
nginx-8454bb78d8-6efsh 1/1 Running 0 9s
# kubectl get svc -n vpa
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx NodePort 10.0.200.5 <none> 80:45425/TCP 15s
# 進行壓測,壓測到一半時,突然連接斷了,說明POD被重新創(chuàng)建了
# ab -c 1000 -n 100000 http://192.168.0.191:45425/
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.0.191 (be patient)
apr_socket_recv: Connection reset by peer (104)
Total of 187078 requests completed
# 查看vpa
# kubectl describe vpa nginx-vpa -n vpa | tail -n 20
Conditions:
Last Transition Time: 2023-09-07T15:41:32Z
Status: True
Type: RecommendationProvided
Recommendation:
Container Recommendations:
Container Name: nginx
Lower Bound: #容器的最小估計值
Cpu: 100m
Memory: 262144k
Target: #目標估計是我們用于設(shè)置資源請求的估計
Cpu: 350m
Memory: 262144k
Uncapped Target: #無上限目標估計是在沒有minAllowed和maxAllowed限制的情況下產(chǎn)生的目標估計
Cpu: 350m
Memory: 262144k
Upper Bound: #上限是容器的最大建議資源估計
Cpu: 2
Memory: 405160855
Events: <none>
# 查看pod被重新創(chuàng)建了 稍高的配置
# kubectl get pods -n vpa
NAME READY STATUS RESTARTS AGE
nginx-daecsfv8d8-see8h 1/1 Running 0 4m
nginx-daecsfv8d8-fsise 1/1 Running 0 3m
已知的限制
- 每當(dāng) VPA 更新 Pod 資源時,都會重新創(chuàng)建 Pod,這會導(dǎo)致重新創(chuàng)建所有正在運行的容器。Pod 可以在不同的節(jié)點上重新創(chuàng)建。
- VPA 無法保證它驅(qū)逐或刪除以應(yīng)用建議(在Auto和Recreate模式下配置時)的 pod 將成功重新創(chuàng)建。通過將 VPA 與Cluster Autoscaler結(jié)合使用可以部分解決這個問題。
- VPA 不會更新不在控制器下運行的 Pod 的資源。
- 目前,Vertical Pod Autoscaler不應(yīng)與CPU 或內(nèi)存上的Horizontal Pod Autoscaler (HPA)一起使用。但是,您可以在自定義和外部指標上將 VPA 與 HPA結(jié)合使用。
- VPA 準入控制器是一個準入 Webhook。如果您將其他準入 Webhook 添加到集群中,則分析它們?nèi)绾谓换ヒ约八鼈兪欠窨赡芟嗷_突非常重要。準入控制器的順序由 API 服務(wù)器上的標志定義。
- VPA 會對大多數(shù)內(nèi)存不足事件做出反應(yīng),但并非在所有情況下都會做出反應(yīng)。
- VPA 性能尚未在大型集群中進行測試。
- VPA 建議可能會超出可用資源(例如節(jié)點大小、可用大小、可用配額)并導(dǎo)致Pod 處于掛起狀態(tài)。通過將 VPA 與Cluster Autoscaler結(jié)合使用可以部分解決這個問題。
- 與同一 Pod 匹配的多個 VPA 資源具有未定義的行為。
總結(jié)
在本文中,我們使用VPA實現(xiàn)了基于POD對配置進行橫向擴展,合理的使用可以提高對K8S的利用率,實現(xiàn)降本增效。但是目前的VPA也存在一些問題,我個人覺得VPA最大的問題是會對服務(wù)進行重建,重建過程中可能會有流量損失,但是好消息是從1.27 版本動態(tài)調(diào)整容器CPU和內(nèi)存資源限制,無需重啟應(yīng)用程序,在可見的將來,會實現(xiàn)動態(tài)擴容更加順滑,讓我們一起期待~