K8s · 維運與部署 · 第 32 課 · · 11min read

HPA 自動擴縮容:流量一來自動加 Pod,壓測實戰

手動 kubectl scale 來不及,HPA 看 CPU / Memory 自動加減 Pod。這篇用 hey 工具壓測 nginx,看著 Pod 從 1 個自動長到 10 個,再自動縮回去。

#Kubernetes #HPA #自動擴縮容 #壓測 #autoscale
章節目錄 · 10

為什麼需要 HPA?

電商網站的場景:

  • 平常:2 個 Pod 撐得住流量
  • 雙 11 大促:流量翻 10 倍,2 個 Pod 直接被打爆
  • 凌晨 3 點:沒人逛,10 個 Pod 閒在那邊浪費錢
手動的解法是 \kubectl scale\

\\\bash
kubectl scale deployment my-api --replicas=10 # 大促前
kubectl scale deployment my-api --replicas=2 # 大促後
\
\\

但你不可能 24 小時盯著儀表板。該自動化了

HPA = Horizontal Pod Autoscaler——K8s 看 CPU 使用率,自動幫你加減 Pod。

HPA 怎麼運作?

[Metrics Server] ── 每 15 秒收集 Pod CPU/Memory 用量
        │
        ▼
     [HPA]  ── 比對 target(如 50%),算出該幾個 Pod
        │
        ▼
   [Deployment] ── 改 replicas
        │
        ▼
     [Pods]  ── 自動增減

前提:Resource requests 一定要設

\\\yaml
resources:
requests:
cpu: "100m"
memory: "64Mi"
limits:
cpu: "500m"
memory: "128Mi"
\
\\

為什麼?因為 HPA 算的是百分比

「CPU 使用率 50%」是相對於 requests 的 50%。如果 \requests: 100m\,使用率 50% 就是 50m。沒設 requests,HPA 沒辦法算百分比,直接擺爛不擴容

安裝 metrics-server

HPA 需要 metrics-server 才能取得 CPU 數據。

\\\bash
# minikube
minikube addons enable metrics-server

# k3s(內建,不用裝)
# 自動已啟用
\
\\

確認跑起來:

\\\bash
kubectl top nodes
kubectl top pods
\
\\

如果 \kubectl top\ 顯示數字,就 OK 了。

HPA YAML

\\\yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-resources-demo # 要擴縮的 Deployment
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50 # CPU 超過 50% 就擴容
\
\\

關鍵欄位:

欄位意義
\scaleTargetRef\要擴縮哪個 Deployment
\minReplicas\最少幾個 Pod
\maxReplicas\最多幾個 Pod(防失控)
\averageUtilization\觸發擴容的 CPU 閾值(%)

實作:壓測讓 Pod 自動長出來

Step 1:部署 HPA

\\\bash
kubectl apply -f hpa.yaml
kubectl get hpa
# NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS
# api-hpa Deployment/api-resources-demo /50% 1 10 1
\
\\

剛建立會看到 \\,等 30 秒就會變成 \0%/50%\

Step 2:壓力測試

開兩個終端:

終端 1(觀察):
\\\bash
kubectl get hpa -w
\
\\

終端 2(壓測):
\\\bash
# 進去 Pod 內部,無限呼叫 API
kubectl run -i --tty load-generator --rm \\
--image=busybox --restart=Never -- \\
/bin/sh -c "while true; do wget -q -O- http://api-svc; done"
\
\\

Step 3:看 HPA 自動加 Pod

終端 1 你會看到:

\\\
NAME TARGETS REPLICAS
api-hpa 0%/50% 1
api-hpa 125%/50% 1 ← 流量來了
api-hpa 125%/50% 3 ← 自動加到 3 個
api-hpa 85%/50% 3
api-hpa 85%/50% 5 ← 還是太高,再加
api-hpa 50%/50% 5 ← 平衡了
\
\\

按 Ctrl+C 停掉壓測:

\\\
api-hpa 10%/50% 5 ← 流量降了
api-hpa 0%/50% 5 ← 但還沒縮
... 等 5 分鐘 ...
api-hpa 0%/50% 1 ← 縮回去了
\
\\

為什麼縮容比擴容慢?

擴容快(30 秒內反應),縮容慢(預設 5 分鐘)——這是故意的。

原因:流量是波動的。如果剛降一點就馬上縮,等下流量又來,又得擴,Pod 一直開開關關反而災難。

可以微調 \behavior\

\\\yaml
spec:
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 觀察 5 分鐘才縮
policies:
- type: Percent
value: 50
periodSeconds: 60
\
\\

HPA 沒效?三步驟排查

症狀排查
TARGETS 一直 \\metrics-server 沒裝或沒跑
TARGETS 是 \/50%\ 但 Pod 有跑Deployment 沒設 requests
CPU 100% 但不擴容沒到 maxReplicas 嗎?看 HPA event
\\\bash kubectl describe hpa api-hpa # 看 events 區塊找原因 \\\

重點整理

  • HPA = K8s 自動 scale:流量大自動加、流量小自動砍
  • 必須設 \resources.requests\——HPA 算的是百分比
  • 必須有 metrics-server——HPA 看不到數據就擺爛
  • 擴容快(30s)、縮容慢(5min)——避免抖動
  • 進階版:VPA(垂直擴縮)、KEDA(事件驅動擴縮)

下一步

服務有 Probe、有 limits、有自動擴容——但誰都能 \kubectl delete pod\ 把它砍掉

實習生不小心 \kubectl delete deployment\,整個服務就沒了。該管權限了

下一篇:RBAC — 讓只讀帳號真的只能讀

📅 下一篇RBAC:讓只讀帳號真的只能讀
Role / RoleBinding / ServiceAccount 三件套——實作一個「只能 get/list,不能 delete」的帳號。
📚 完整系列總覽K8s 系列教學首頁(共 40 課,按學習路徑順序排)