讲解

手动 kubectl scale 解决不了「流量半夜暴涨」的问题——总不能定闹钟起来扩副本。HorizontalPodAutoscaler(HPA)按指标自动调整 Deployment/StatefulSet 的副本数:你声明「目标 CPU 利用率 50%,副本数 1 到 3 之间」,HPA 控制器每隔一小段时间算一次「当前指标 ÷ 目标值 × 当前副本数」,向上取整得到期望副本数,再夹在 min/max 之间去改 scale。横向(加副本)叫 Horizontal,对应的还有纵向调 requests 的 VPA(需要额外安装,不作展开)。

HPA 的前置条件是 metrics-server:它是集群的指标管道,从各节点 kubelet 收集 CPU/内存用量,通过 metrics.k8s.io API 提供给 HPA 和 kubectl top。没有它,HPA 的 TARGETS 列会显示 ,控制器拿不到数据就不动作。kind/minikube 默认不带 metrics-server,要手动安装;云上托管集群一般都预装。还有个隐藏前提:按 CPU 利用率伸缩时,「利用率」是相对容器 requests 计算的——没配 requests 的 Deployment 没法用百分比目标,这就是第 17 章强调资源声明的又一个理由。

看一个 HPA 清单的核心字段:scaleTargetRef 指向被伸缩的对象;minReplicas/maxReplicas 划出副本数边界(min 建议至少 2,单副本缩到 0 或 1 都有可用性风险);metrics 里 resource.cpu.target.averageUtilization: 50 表示「所有 Pod 的 CPU 用量均值 ÷ requests 均值 ≈ 50%」。行为调优在 behavior 字段:scaleDown 默认有 5 分钟稳定窗口(防止指标抖动导致副本数来回震荡),scaleUp 默认更激进。理解这个「快扩慢缩」的不对称设计:扩容是救急,缩容是省钱,救急要快,省钱可以等。

示例

先部署一个带 requests 的应用(HPA 按 CPU 利用率伸缩要求容器必须声明 requests):

# wait: deploy/ohmydocs-verify-load
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ohmydocs-verify-load
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ohmydocs-verify-load
  template:
    metadata:
      labels:
        app: ohmydocs-verify-load
    spec:
      containers:
        - name: nginx
          image: nginx:1.27-alpine
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: 100m
              memory: 32Mi
            limits:
              cpu: 500m
              memory: 128Mi

HPA:CPU 均值超过 requests 的 50% 就扩容,副本数范围 1-3(这份清单会被真实 apply):

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: ohmydocs-verify-load
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: ohmydocs-verify-load
  minReplicas: 1
  maxReplicas: 3
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 50

查看 HPA 状态。TARGETS 列显示 /50% 说明 metrics-server 不在——资源本身已生效,只是拿不到指标(本教程验证环境的网络限制见运行摘要):

kubectl get hpa ohmydocs-verify-load
kubectl describe hpa ohmydocs-verify-load | tail -6

metrics-server 可用时的观测手法(kubectl top 直接看各 Pod 的 CPU/内存用量;新 Pod 的指标要等一个抓取周期,脚本里带重试):

# 依赖: metrics-server
ok=0
for i in $(seq 1 12); do
  if kubectl top pods -l app=ohmydocs-verify-load; then ok=1; break; fi
  sleep 15
done
[ "$ok" = "1" ] || { echo "metrics-server 指标迟迟不可用"; exit 1; }
kubectl get hpa ohmydocs-verify-load

本地集群安装 metrics-server 的标准命令(GitHub 发布件,受限网络可能失败——脚本已在验证阶段尝试过一次):

# 仅示意:安装 metrics-server(GitHub 发布件 + 需追加 --kubelet-insecure-tls 补丁,网络受限时不可用)
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

常见坑

  • TARGETS 永远 :metrics-server 没装或没跑起来;HPA 资源创建不需要它,但伸缩需要。kind 上安装后还要追加 --kubelet-insecure-tls 参数。
  • Deployment 没配 requests:按 Utilization 伸缩的 HPA 算不出百分比,事件里直接报 missing request for cpu。
  • 缩容抖动:流量波动导致副本数上下来回跳——behavior.scaleDown.stabilizationWindowSeconds 拉长稳定窗口,或把目标利用率调高一点。
  • minReplicas: 1 的关键服务:缩到单副本时一次节点故障就全站中断;生产关键服务 min 至少 2,且配合 Pod 反亲和分散到不同节点。

小结

HPA = 指标驱动的自动 scale:requests 是百分比基准,metrics-server 是数据来源,behavior 控制快扩慢缩;本地集群记得装 metrics-server 并打 insecure-tls 补丁。下一章收紧权限:RBAC。