為什麼需要 HPA#
像搶票系統、訂餐平台這類服務,每天都有可預期的尖峰時段:午餐時間外送平台流量必定爆衝。但人工每天定時把副本拉高再拉低不僅費神,還無法應付突如其來、無法預期的流量高峰。
水平擴縮(Horizontal Pod Autoscaler, HPA)的價值就在這裡 — 在十幾秒內就能對指標變化做出反應,自動把 Deployment 的副本數往上推或往下收,讓服務在尖峰自動擴容、平時收回資源。
動手前的準備#
在開始之前,要先確認叢集已經安裝好 Metrics Server,因為 HPA 依靠它收集 CPU、記憶體等指標:
kubectl top node預期輸出類似:
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
docker-desktop 258m 6% 5717Mi 72%如果還沒裝,請參考前一章「Metrics Server 安裝」。
HPA 設定檔總覽#
下面先用一份骨架說明 HPA 的主要欄位,完整可運作的 YAML 留到「實際演練」段落。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:
scaleTargetRef: # 指向要被擴縮的 Deployment/ReplicaSet
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
metrics: # 可同時混合多種 type
- type: Resource # CPU / 記憶體(Metrics Server 提供)
- type: Pods # 每 Pod 的自訂指標(取平均)
- type: Object # 以單一 K8s 物件(如 Ingress)的指標為條件
- type: External # 非 K8s 來源(例如 message queue 長度)
behavior: # 擴縮節奏控制,多半用預設即可
scaleDown: { stabilizationWindowSeconds: 300, ... }
scaleUp: { stabilizationWindowSeconds: 0, ... }幾個重要欄位:
apiVersion:autoscaling/v2beta2之後才能用 Metrics Server 的記憶體當指標。spec.minReplicas/spec.maxReplicas:副本數的下限與上限,不能設成 0。spec.metrics[].type:Resource:Kubernetes 已知的資源指標(CPU、記憶體),描述當前擴縮目標中每個 Pod 的使用情形。Pods:當前擴縮目標每個 Pod 的自訂指標,比較前會先平均。pods.metric.selector可以視為labelSelector,用來縮小指標範圍。Object:以單一 Kubernetes 物件(例如 Ingress)的指標當作觸發條件,需要透過describedObject提供足夠資訊。External:以非 Kubernetes 物件的外部指標當觸發條件,必須提供metric.name與metric.selector。
target.type:Utilization(以 Request 百分比,僅 Resource 適用)、AverageValue(跨 Pod 均值)、Value(單一目標值)。behavior:stabilizationWindowSeconds:當指標顯示要縮容時,HPA 會回看過去這段時間內的最大期望值,避免副本數抖動太頻繁。scaleUp/scaleDownpolicy:每隔periodSeconds一段時間,副本變化幅度不會超過Percent或Pods所指定的數量。
實際演練#
部署示範服務#
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
selector:
matchLabels:
run: php-apache
replicas: 1
template:
metadata:
labels:
run: php-apache
spec:
containers:
- name: php-apache
image: registry.k8s.io/hpa-example
ports:
- containerPort: 80
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 500m
memory: 512Mi
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
labels:
run: php-apache
spec:
ports:
- port: 80
selector:
run: php-apache設定 HPA#
# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80部署:
kubectl apply -f ./deployment.yaml
kubectl apply -f ./hpa.yaml模擬壓力測試#
開一個無窮迴圈打 php-apache:
kubectl run -i --tty load-generator --rm --image=busybox:1.28 --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"另一個 terminal 持續觀察 HPA:
kubectl get hpa --watch可以看到副本數從 1 一路跟著 CPU 使用率攀升而擴展:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
php-apache Deployment/php-apache 0%/80%, <unknown>/50% 1 10 1 3s
php-apache Deployment/php-apache 1%/80%, 0%/50% 1 10 1 33s
php-apache Deployment/php-apache 1%/80%, 98%/50% 1 10 3 63s
php-apache Deployment/php-apache 2%/80%, 29%/50% 1 10 3 94s
php-apache Deployment/php-apache 2%/80%, 33%/50% 1 10 3 2m4s小結#
HPA 提供了最直觀的水平擴縮能力,但在真正的高流量正式環境中,還需要更細緻的設定與更多外部指標來搭配。Kubernetes 預設的 HPA 在「兩分鐘內擴出上千台」這類場景上幫不上忙;那時就會用上 Prometheus、Grafana 等更完整的監控與指標體系。下一章會接著看垂直擴縮(Vertical Pod Autoscaler, VPA)。
原文出處#
- GitHub:https://github.com/MikeHsu0618/2022-ithelp/tree/main/Day26
- iThome:https://ithelp.ithome.com.tw/articles/10298858