背景
在K8s 1.18之前,HPA擴容是無法調(diào)整靈敏度的:
1.對于縮容,由kube-controller-manager的--horizontal-pod-autoscaler-downscale-stabilization-window參數(shù)控制縮容時間窗口,默認(rèn)5分鐘,即負(fù)載減小后至少需要等5分鐘才會縮容。
2.對于擴容,由hpa controller固定的算法、硬編碼的常量因子來控制擴容速度,無法自定義。
這樣的設(shè)計邏輯導(dǎo)致用戶無法自定義HPA的擴縮容靈敏度,而不同的業(yè)務(wù)場景對于擴容容靈敏度要求可能是不一樣的,比如:
1.對于有流量突發(fā)的關(guān)鍵業(yè)務(wù),在需要的時候應(yīng)該快速擴容(即便可能不需要,以防萬一),但縮容要慢(防止另一個流量高峰)。
2.對于一些需要處理大量數(shù)據(jù)的離線業(yè)務(wù),在需要的時候應(yīng)該盡快擴容以減少處理時間,不需要那么多資源的時候應(yīng)該盡快縮容以節(jié)約成本。
3.處理常規(guī)數(shù)據(jù)/網(wǎng)絡(luò)流量的業(yè)務(wù),它們可能會以一般的方式擴大和縮小規(guī)模,以減少抖動。
HPA在K8s 1.18迎來了一次更新,在之前v2beta2版本上新增了擴縮容靈敏度的控制,不過版本號依然保持v2beta2不變。
如何使用
這次更新實際就是在HPA Spec下新增了一個behavior字段,下面有scaleUp和scaleDown兩個字段分別控制擴容和縮容的行為。
下面給出一些使用場景的示例。
快速擴容
當(dāng)你的應(yīng)用需要快速擴容時,可以使用類似如下的HPA配置:
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
minReplicas: 1
maxReplicas: 1000
metrics:
- pods:
metric:
name: k8s_pod_rate_cpu_core_used_limit
target:
averageValue: "80"
type: AverageValue
type: Pods
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
behavior: # 這里是重點
scaleUp:
policies:
- type: percent
value: 900%
上面的配置表示擴容時立即新增當(dāng)前9倍數(shù)量的副本數(shù),即立即擴容到當(dāng)前10倍的Pod數(shù)量,當(dāng)然也不能超過maxReplicas的限制。
假如一開始只有1個Pod,如果遭遇流量突發(fā),它將以飛快的速度進行擴容,擴容時Pod數(shù)量變化趨勢如下:
1->10->100->1000
沒有配置縮容策略,將等待全局默認(rèn)的縮容時間窗口(--horizontal-pod-autoscaler-downscale-stabilization-window,默認(rèn)5分鐘)后開始縮容。
快速擴容,緩慢縮容
如果流量高峰過了,并發(fā)量驟降,如果用默認(rèn)的縮容策略,等幾分鐘后Pod數(shù)量也會隨之驟降,如果Pod縮容后突然又來一個流量高峰,雖然可以快速擴容,但擴容的過程畢竟還是需要一定時間的,如果流量高峰足夠高,在這段時間內(nèi)還是可能造成后端處理能力跟不上,導(dǎo)致部分請求失敗。這時候我們可以為HPA加上縮容策略,HPA behavior配置示例如下:
behavior:
scaleUp:
policies:
- type: percent
value: 900%
scaleDown:
policies:
- type: pods
value: 1
periodSeconds: 600 # 每 10 分鐘只縮掉 1 個 Pod
上面示例中增加了scaleDown的配置,指定縮容時每10分鐘才縮掉1個Pod,大大降低了縮容速度,縮容時的Pod數(shù)量變化趨勢如下:
1000 -> … (10 min later) -> 999
這個可以讓關(guān)鍵業(yè)務(wù)在可能有流量突發(fā)的情況下保持處理能力,避免流量高峰導(dǎo)致部分請求失敗。
緩慢擴容
如果想要你的應(yīng)用不太關(guān)鍵,希望擴容時不要太敏感,可以讓它擴容平穩(wěn)緩慢一點,為HPA加入下面的behavior:
behavior:
scaleUp:
policies:
- type: pods
value: 1 # 每次擴容只新增 1 個 Pod
假如一開始只有1個Pod,擴容時它的Pod數(shù)量變化趨勢如下:
1 -> 2 -> 3 -> 4
禁止自動縮容
如果應(yīng)用非常關(guān)鍵,希望擴容后不自動縮容,需要人工干預(yù)或其它自己開發(fā)的controller來判斷縮容條件,可以使用類型如下的behavior配置來禁止自動縮容:
behavior:
scaleDown:
policies:
- type: pods
value: 0
延長縮容時間窗口
縮容默認(rèn)時間窗口是5 min(--horizontal-pod-autoscaler-downscale-stabilization-window),如果我們需要延長時間窗口以避免一些流量毛刺造成的異常,可以指定下縮容的時間窗口,behavior配置示例如下:
behavior:
scaleDown:
stabilizationWindowSeconds: 600 # 等待 10 分鐘再開始縮容
policies:
- type: pods
value: 5 # 每次只縮掉 5 個 Pod
上面的示例表示當(dāng)負(fù)載降下來時,會等待600s(10分鐘)再縮容,每次只縮容5個Pod。
延長擴容時間窗口
有些應(yīng)用經(jīng)常會有數(shù)據(jù)毛刺導(dǎo)致頻繁擴容,而擴容出來的Pod其實沒太大必要,反而浪費資源。比如數(shù)據(jù)處理管道的場景,擴容指標(biāo)是隊列中的事件數(shù)量,當(dāng)隊列中堆積了大量事件時,我們希望可以快速擴容,但又不希望太靈敏,因為可能只是短時間內(nèi)的事件堆積,即使不擴容也可以很快處理掉。
默認(rèn)的擴容算法會在較短的時間內(nèi)擴容,針對這種場景我們可以給擴容增加一個時間窗口以避免毛刺導(dǎo)致擴容帶來的資源浪費,behavior配置示例如下:
behavior:
scaleUp:
stabilizationWindowSeconds: 300 # 擴容前等待 5 分鐘的時間窗口
policies:
- type: pods
value: 20 # 每次擴容新增 20 個 Pod
上面的示例表示擴容時,需要先等待5分鐘的時間窗口,如果在這段時間內(nèi)負(fù)載降下來了就不再擴容,如果負(fù)載持續(xù)超過擴容閥值才擴容,每次擴容新增20個Pod。
小結(jié)
本文介紹了如何利用K8s 1.18的HPA新特性來控制擴縮容的靈敏度,以更好的滿足各種不同場景對擴容速度的需求。
參考資料
HPA介紹:https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/