昨天我們用 kubectl scale 手動調整了 Deployment 的副本數,但在真實環境裡,流量高峰和低谷是動態的,不可能 24 小時盯著手動擴縮。
今天的主角是 HPA(Horizontal Pod Autoscaler),它能根據 CPU、Memory 等指標,自動幫你調整 Pod 數量。流量一來,Pod 自動長出來;流量退了,Pod 自動收回去。
整篇會涵蓋:安裝 Metrics Server → 建立測試 Deployment → 設定 HPA → 壓測觸發自動擴容 → 觀察縮容。
以下操作皆在 master 節點 執行。
HPA 的核心流程很簡單:
replicas;低於目標,就減少 replicas
用一張圖來看:

💡 HPA 調整的是 Deployment 的 replicas 數量,也就是「水平擴展」。如果要調整單一 Pod 的資源上限(CPU / Memory),那是 VPA(Vertical Pod Autoscaler) 的工作,不在今天的範圍。
HPA 需要 Metrics API 才能取得指標數據,最常見的做法是安裝 metrics-server。
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
安裝後確認 Pod 狀態:
kubectl get pods -n kube-system | grep metrics-server
如果你跟我一樣用 kubeadm 建叢集,大概率會看到 metrics-server 一直是 0/1:
metrics-server-7cfb66fcc-k88bf 0/1 Running 0 165m
這是因為 kubelet 使用的是自簽憑證,metrics-server 預設會驗證 TLS 憑證,驗不過就無法連線。
解法: 加上 --kubelet-insecure-tls 參數
kubectl edit deployment metrics-server -n kube-system
找到 args 區塊,加上這行:
args:
- --cert-dir=/tmp
- --secure-port=10250
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --metric-resolution=15s
- --kubelet-insecure-tls # 加這行

存檔退出後 metrics-server 會自動重啟,等個 30 秒再確認。
kubectl top nodes
kubectl top pods
看到數值出來就代表成功了:

說明
--kubelet-insecure-tls會略過 Metrics Server 與 kubelet 通訊時的 TLS 憑證驗證,適合用於測試或學習環境。正式環境不建議使用此參數,應配置可被信任的 kubelet 憑證。若使用 GKE、EKS 等託管 Kubernetes 服務,也可透過平台提供的整合方式或官方元件部署 Metrics Server。
要讓 HPA 正常運作,Deployment 的 Pod 必須設定 resource requests,這樣 HPA 才有基準值來計算使用率。
我們用 Kubernetes 官方的 hpa-example 映像檔,這是一個會消耗 CPU 的簡單 PHP 應用:
# 建立 Deployment
kubectl create deployment php-apache --image=registry.k8s.io/hpa-example
# 設定 CPU request 為 200m(0.2 核心)
kubectl set resources deployment php-apache --requests=cpu=200m
# 建立 Service 讓它可以被存取
kubectl expose deployment php-apache --port=80
確認 Pod 正在運行:
kubectl get pods
kubectl top pods
為什麼要設定 resource requests?
HPA 會根據 實際使用量與 requests 的比例 計算資源使用率。
如果 Pod 沒有設定 requests,HPA 就無法計算使用率百分比,也無法據此進行擴縮。
現在來建立 HPA,目標是:當 CPU 使用率超過 50% 時自動擴容,最少 1 個 Pod,最多 10 個。
kubectl autoscale deployment php-apache --cpu=50% --min=1 --max=10
確認 HPA 建立成功:
kubectl get hpa

目前 CPU 使用率是 0%,遠低於 50% 的目標,所以只跑 1 個 Pod。
重頭戲來了。開另一個終端,用 busybox 持續打流量:
kubectl run -i --tty load-generator --rm --image=busybox --restart=Never \
-- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"
回到原本的終端,觀察 HPA 的變化:
kubectl get hpa -w
大約 1~2 分鐘後,你會看到 TARGETS 的 CPU 使用率開始飆升,replicas 也跟著增加:

同時看 Pod 的狀態:
kubectl get pods
Pod 數量從 1 個自動長到了好幾個!這就是 HPA 在工作。

💡 HPA 的擴容速度取決於指標變化幅度。如果使用率遠超目標值,它會一次拉起較多 Pod;如果只是略超,則會逐步增加。
回到跑 load-generator 的終端,按 Ctrl + C 停止壓測。
然後繼續觀察 HPA:
kubectl get hpa -w
你會發現 CPU 使用率慢慢降下來,但 Pod 數量不會馬上減少。
為什麼縮容比較慢?
HPA 預設設有 stabilization window(穩定視窗),縮容時會觀察一段時間,預設為 5 分鐘。這項機制可避免因短時間流量波動而頻繁調整副本數。當資源使用率持續低於目標值後,HPA 才會逐步減少 Pod 數量。
等 5 分鐘太久了?我們可以直接編輯 HPA,在 spec 下新增 behavior 欄位:
kubectl edit hpa php-apache
找到 spec 區塊,在 metrics 同層加上 behavior:

存檔退出後,確認設定已生效
YAML 欄位說明
stabilizationWindowSeconds: 30:將縮容穩定視窗設定為 30 秒。HPA 會參考這段時間內的縮容建議,避免因短暫的指標下降而立即減少副本數。預設值為 300 秒。policies:定義縮容速率。此處設定每 15 秒最多可減少目前 100% 的 Pod,代表在條件允許的情況下,可以一次縮減至minReplicas。behavior:用於設定 HPA 的擴縮行為,僅支援autoscaling/v2,autoscaling/v1不支援此欄位。
現在可以再壓測一次,停止後觀察縮容 —— 這次大約 30 秒就會開始收 Pod 了!
今天我們完成了 HPA 的完整流程:
| 步驟 | 做了什麼 |
|---|---|
| 安裝 Metrics Server | 提供 CPU / Memory 指標給 HPA(含 kubeadm TLS 問題排除) |
| 建立 Deployment | 設定 resource requests 作為 HPA 的計算基準 |
| 建立 HPA | 設定目標 CPU 50%,最少 1 最多 10 個 Pod |
| 壓測觀察 | 流量上來 → Pod 自動增加;流量下降 → Pod 自動回收 |
| 調整 behavior | 用 kubectl edit 修改縮容穩定視窗從 300s → 30s |
HPA 讓擴縮容從手動變自動,你的服務終於有了面對流量波動的能力。但 Pod 再多,外面的人也要連得進來才有用 — 明天我們來搞定 Service,讓流量真正找到你的 Pod!