title: K8s实战_HPA功能实验
date: 2026-03-11
categories:
  - K8s
tags:
  - 实验
cover:

摘要:这份实战模拟了运维工程师在真实生产中遇到的场景:业务高峰流量导致 CPU 激增,系统自动横向扩容。

实战目标

  • 部署一个 CPU 密集型的 Web 服务。

  • 配置基于 CPU 利用率的 HPA 策略。

  • 使用压测工具模拟高并发流量。

  • 观察 Pod 副本数的动态增减及流量分发。

①编写实战 YAML (hpa-practice.yaml)

将所有的资源合在一个文件中

# 1. 定义业务 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hpa-worker
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hpa-worker
  template:
    metadata:
      labels:
        app: hpa-worker
    spec:
      containers:
      - name: php-apache
        # 这里请替换为你从渡渡鸟拉取的镜像地址
        image: hpa-example:latest 
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 200m   # 必须配置!这是HPA计算的基准
          limits:
            cpu: 500m
---
# 2. 定义对外服务的 Service
apiVersion: v1
kind: Service
metadata:
  name: hpa-worker-service
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: hpa-worker
---
# 3. 定义 HPA 策略
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: worker-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: hpa-worker
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50  # 当CPU达到request的50%(即100m)时触发扩容

执行部署

kubectl apply -f hpa-practice.yaml

②状态检查

检查pod运行状态

kubectl get pod 
#确保是running

检查HPA状态

kubectl get hpa worker-hpa
  • 关键点:如果 TARGETS 列显示 <unknown>/50%,说明 Metrics-Server 没调通或 Pod 还没产生数据,请等待 1 分钟。

  • 正常值:应显示 0%/50%。

③压力测试(模拟负载)

打开两个新的终端窗口,以便实时观察变化。

窗口1:监控HPA动态

# 持续监控副本数和CPU变化
kubectl get hpa worker-hpa -w

窗口2:启动压测容器

使用 busybox 启动一个无限循环的负载生成器。

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://hpa-worker-service; done"

④观察验证

扩容阶段(Scaling Up)

随着压测进行,你会观察到窗口 A 的输出:

  • TARGETS 里的百分比迅速上升(如 150%/50%)。

  • REPLICAS 从 1 变成 3,再变成 6,最终可能达到 10。

  • 运维验证:执行 kubectl get pods,你会看到大量新的 Pod 正在 Creating 或 Running。

负载平滑阶段

当副本数增加到足够多时,平均 CPU 利用率会回落到 50% 左右,副本数停止增长。

缩容阶段(Scaling Down)

在窗口 B 按下 Ctrl+C 停止压测。

  • 注意:副本数并不会立刻减少。

  • 运维知识点:K8s 为了防止“扩缩容震荡”(刚缩容流量又来了),默认有 5 分钟 的缩容冷却期(stabilizationWindowSeconds)。

  • 约 5 分钟后,你会看到 REPLICAS 回到 1。

⑤实战总结

  • 为什么需要 Request? 实验证明,不写 Request,HPA 无法计算百分比,状态永远是 Unknown。

  • Metrics-Server 的重要性:它是 HPA 的“眼睛”。

  • 计算公式验证:如果 1 个 Pod 消耗 300m,目标是 100m (50% of 200m),那么 ceil(1 * (300/100)) = 3,所以副本数会变成 3。

  • 1.35 版本观察:观察在 CentOS 10 上,Pod 的创建速度和资源调度是否均衡地分布在 Node1 和 Node2 上。

拓展实验-内存维度拓展

很多 Java 应用或缓存服务对 CPU 消耗不高,但会因为内存溢出(OOM)导致崩溃。

修改YAML

将指标改为memory

metrics:
- type: Resource
  resource:
    name: memory
    target:
      type: Utilization
      averageUtilization: 70
  • 模拟测试方法: 你不能通过简单的 wget 模拟内存增长。你需要进入 Pod,使用 stress-ng 工具或编写简单的脚本申请内存。

  • 运维排障点: 内存是不可压缩资源。如果 CPU 达到 100%,进程只是变慢;如果内存达到 Limit,进程会被内核 OOM Kill。在实战中观察:HPA 还没来得及扩容,Pod 是否就已经重启了?这就是为什么要合理设置 requests 和 limits 的差值

拓展实验-扩缩灵敏度测试

场景: 生产环境最怕“扩容太慢”和“缩容太快”。

在 K8s 1.35 中,你可以通过 behavior 字段精细控制动作。

  • 实验设计:

    1. 配置一个 快速扩容 策略:一旦超标,立即增加 4 倍副本。

    2. 配置一个 缓慢缩容 策略:为了应对波动,每次缩容只允许掉 1 个 Pod,且等待 10 分钟。

  • 测试点:观察 kubectl get hpa -w 的时间戳,记录从压力消失到副本数真正开始下降的时间间隔。

拓展实验-多指标综合监控

场景: 一个 Web 接口,CPU 高了要扩容,内存高了也要扩容。

  • 实验配置: 在 metrics 数组中同时定义 CPU 和 Memory。

  • 判定逻辑(重要考点): HPA 会取所有指标中计算出的“最大副本数”作为最终目标。

    公式推演:如果根据 CPU 计算需要 5 个副本,根据内存计算需要 8 个副本,HPA 最终会扩容到 8 个。

拓展实验-外部维度监控(Custom Metrics)

这是区分“初级运维”和“资深架构”的分水岭。Metrics-Server 只能看到系统层指标,但运维更关心业务指标。

  • 扩展方向:

    1. 基于 QPS 扩容:配合 Prometheus 和适配器(Prometheus Adapter),根据 Nginx 每秒请求数扩容。

    2. 基于消息队列积压量:如果 RabbitMQ 里的消息堆积了 10000 条,立刻启动更多的消费者 Pod。

拓展实验-结合VPA‘联合演练’

尝试在同一个 Deployment 上同时应用 HPA 和 VPA,观察它们是否会打架。

  • 测试建议:

    1. 给 Pod 开启 VPA 的 Off 模式(仅推荐模式)。

    2. 在 HPA 扩容的过程中,查看 VPA 给出的 Target 建议值是否也随之发生了变化。

    3. 记录下当两者冲突时,系统产生的 Warning 事件。

更多推荐