HPA总结
背景
應用擴容是指在應用接收到的并發請求已經處于其處理請求極限邊界的情形下,擴展處理能力而確保應用高可用的技術手段。
- Horizontal Scaling
所謂橫向伸縮是指通過增加應用實例數量分擔負載的方式來提升應用整體處理能力的方式。 - Vertical Scaling
所謂縱向伸縮是指通過增加單個應用實例資源以提升單個實例處理能力,進而提升應用整體處理能力的方式。
云原生下應用擴縮容都有哪些方式呢?
- HPA:Horizatontal Pod Autoscaler,規定資源使用值,最小和最大實例數量
- VPA:Vertical Pod Autoscaler,規定最小和最大資源使用量。沒有生產可用,暫不介紹。
- Cluster Autoscaler:pod處于pending狀態集群擴容,介紹在這里
介紹
- HPA 是 Kubernetes 的一種資源對象,能夠根據某些指標對在 statefulSet、 replica Set、 deployment 等集合中的Pod 數量進行橫向動態伸縮,使運行在上面的服務對指標的變化有一定的自適應能力。
- 因節點計算資源固定,當 Pod 調度完成并運行以后,動態調整計算資源變得較為困難,因此橫向擴展具有更大優勢,HPA 是擴展應用能力的第一選擇。
- 多個沖突的 HPA 同時創建到同一個應用的時候會有無法預期的行為,因此需要小心維護 HPA規則。
- HPA 依賴于 Metrics-Server。
HPA spec
cat hpa.yaml apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata:name: php-apache spec: # HPA 的伸縮對象描述,HPA會動態修改該對象的Pod 數量scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: php-apache # HPA 的最小 Pod 數量和最大 Pod 數量minReplicas: 1maxReplicas: 10# 監控的指標數組,支持多種類型的指標共存metrics:- type: Resourceresource:name: cputarget:type: UtilizationaverageUtilization: 50HPA 的指標類型即metrics
- 對于按 Pod 統計的資源指標(如 CPU),控制器從資源指標 API 中獲取每一個HPA指定的 Pod 的度量值,如果設置了目標使用率,控制器獲取每個 Pod 中的容器資源使用情況,并計算資源使用率。如果設置了 target 值,將直接使用原始數據(不再計算百分比)。
- 如果 Pod 使用自定義指標,控制器機制與資源指標類似,區別在于自定義指標只使用原始值,而不是使用率。
- 如果 Pod 使用對象指標和外部指標(每個指標描述一個對象信息)比如QPS,這個指標將直接根據目標設定值相比較,并生成一個上面提到的擴縮比例。在 autoscaling/v2beta2 版本 API中,這個指標也可以根據 Pod 數量平分后再計算。
Resource 類型的指標
- type: Resourceresource:name: cpu# Utilization 類型的目標值,Resource 類型的指標只支持 Utilization 和 AverageValue 類型的目標值target:type: UtilizationaverageUtilization: 50Pods 類型的指標
- type: Podspods:metric:name: packets-per-second# AverageValue 類型的目標值,Pods 指標類型下只支持 AverageValue 類型的目標值target:type: AverageValueaverageValue: 1kHPA算法
按照 Pod 中所有 container 的資源使用平均值來計算,期望副本數=當前副本數 *(當前指標 / 期望指標)
當前度量值為 200m,目標設定值為 100m,那么由于 200.0/100.0== 2.0,副本數量將會翻倍。
如果當前指標為 50m,副本數量將會減半,因為 50.0/100.0== 0.5。
如果計算出的擴縮比例接近1.0(根據–horizontal-pod-autoscaler-tolerance 參數全局配置的容忍值,默認為 0.1),將會放棄本次擴縮。
滾動升級時的擴縮容
- 當你為一個 Deployment 配置自動擴縮時,你要為每個 Deployment 綁定一個HPA。
- HPA管理 Deployment 的 replicas字段。
- Deployment Controller 負責設置下層 ReplicaSet 的 replicas 字段,以便確保在上線及后續過程副本個數合適。
為什么deploymentSpec中的replicas字段的類型為*int, 而不是int?
因為replicas字段被HPA控制的時候,可能replicas不需要更新。如果使用int類型,需要給定replicas字段一個值。而使用指針類型,只需要不填replicas就可以了。
擴縮策略
擴容時:假如一個應用平時的cpu使用率是20%,突然使用率達到了100%,根據HPA的算法會使pod數量翻5倍。對基礎架構和業務都有壓力。
縮容時:假如pod數量是10個,需要縮容80%,如果一次性全部縮掉,業務可能會有影響。
這種情況就可以使用HPA的高級策略。
在 spec 字段的 behavior 部分可以指定一個或多個擴縮策略。
kubectl explain --api-version=autoscaling/v2beta2 hpa.spec.behavior.scaleUp快速擴容
- 擴容時,立即新增當前9倍數量的副本數,即立即擴容到當前10倍的 Pod 數量,當然也不能超過 maxReplicas 的限制。
- pod數量:1-> 10 -> 100 -> 1000
- 沒有縮容策略,即默認負載減小后5分鐘開始縮容。
緩慢擴容
- 每次擴容只新增 1 個 Pod
緩慢縮容
- 縮容時,60秒內只能縮5個pod或者60秒內只能縮容10%的pod
這樣就能保證業務的縮容是平滑的,數據指標下降也是平滑的,不是突然的下降。防止突然的流量高峰導致部分請求失敗。
禁止自動縮容
- 如如果你的業務非常關鍵,不希望自動縮容,需要手動或者其他controller來縮容,可以設置禁止自動縮容。
擴縮容靈敏度(冷卻/延遲支持)
- 當使用HPA管理一組副本擴縮時,有可能因為指標動態的變化造成頻繁的擴縮容,這種情況稱為抖動 (Thrashing)
- –horizontal-pod-autoscaler-downscale-stabilization:設置縮容冷卻時間窗口長度。默認值是5分鐘
延長擴容時間窗口
- 某些大數據處理的業務,可能短時間內業務堆積,擴容出很多的pod,造成資源的浪費。我們希望可以快速擴容但是又不那么靈敏,因為即使不擴容業務也可以很快處理掉。
- 擴容時,需要先等待 5 分鐘的時間窗口,如果5分鐘內負載降下來了就不再擴容,如果負載持續超過擴容閥值才擴容,每次擴容新增 20 個 Pod。
延長縮容時間窗口
- 負載降下來后,等待 10 分鐘再開始縮容,每次只縮容 5 個 Pod。
自定義指標
Kubernetes 默認提供 CPU 和內存作為 HPA 彈性伸縮的指標,如果有更復雜的場景需求,比如基于業務單副本 QPS 大小來進行自動擴縮容,可以安裝 prometheus-adapter 來實現基于自定義指標的 Pod 擴縮容。
官方地址:https://github.com/kubernetes-sigs/prometheus-adapter
栗子
httpserver鏡像,暴露了 httpserver_requests_total 指標,記錄 HTTP 的請求,通過這個指標可以計算出該業務程序的 QPS 值。
部署deployment,service
apiVersion: apps/v1 kind: Deployment metadata:name: httpserver spec:replicas: 1selector:matchLabels:app: httpservertemplate:metadata:labels:app: httpserverspec:containers:- name: httpserverimage: httpserver:v1imagePullPolicy: Always --- apiVersion: v1 kind: Service metadata:name: httpserverlabels:app: httpserverannotations:prometheus.io/scrape: "true"prometheus.io/path: "/metrics"prometheus.io/port: "http" spec:type: ClusterIPports:- port: 80protocol: TCPname: httpselector:app: httpserverprometheus采集QPS指標
方式一:修改promtheus配置文件
如果部署的是prometheus-opreator,修改配置文件參考這里的附錄
- job_name: httpserverscrape_interval: 5skubernetes_sd_configs:- role: endpointsrelabel_configs:- action: keepsource_labels:- __meta_kubernetes_service_label_appregex: httpserver- action: keepsource_labels:- __meta_kubernetes_endpoint_port_nameregex: http方式二:配置 ServiceMonitor
apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata:name: httpserver spec:endpoints:- port: httpinterval: 5s#namespaceSelector:#matchNames:#- xxxselector:matchLabels:app: httpserver部署prometheus-adapter
實例
metrics-server已經部署在集群中了。以php為例。
pod的cpu到達500m,pod的limits設定是500m
pod已經自動擴容
HPA的缺點
-
如果創建了2個hpa對象,指定了同樣的target后,這2個規則會沖突,可能會出問題。
-
基于指標的彈性有滯后效應,因為彈性控制器操作的鏈路過長。
-
從應用負載超出國值到 HPA 完成擴容之間的時間差包括:
- 應用指標數據已經超出閾值
- HPA 定期執行指標收集滯后效應;
- HPA 控制 Deployment 進行擴容的時間;
- Pod 調度,運行時啟動掛載存儲和網絡的時間;
- 應用啟動到服務就緒的時間。
-
很可能在突發流量出現時,還沒完成彈性擴容,服務實例已經被流量擊垮。
可能遇到的問題
由于hpa是按照 Pod 中所有 container 的資源使用平均值來計算的,如果 Pod 中有多個 container,它們的資源使用相差較大,可能導致某個 container 高負載了還不擴容。
比如有個pod,它有2個容器,一個是業務容器,一個是sidecar,業務容器CPU使用為100%,而sidecar容器CPU使用為0,那么這個pod CPU使用率就會被當作50%,而hpa設置的CPU閾值是60%,那么這個pod就不會被擴容。
如何解決
參考地址:https://github.com/kubernetes/enhancements/tree/master/keps/sig-autoscaling/1610-container-resource-autoscaling
它允許hpa根據容器使用的資源來進行擴縮容。
一個栗子:
pod有2個容器:application和log。當application容器的CPU使用率達到50%即進行擴容,并且不管log容器CPU使用率;或者pod整體的CPU使用率達到50%進行擴容。
apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata:name: mission-critical spec:scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: mission-criticalminReplicas: 1maxReplicas: 10metrics:- type: ContainerResourceresource:name: cpucontainer: applicationtarget:type: UtilizationaverageUtilization: 50- type: PodResourceresource:name: cputarget:type: UtilizationaverageUtilization: 50總結
- 上一篇: HPA
- 下一篇: APP2SD图文储存卡分区教程