K8s学习笔记(十八) HPA控制器

要掌握 Kubernetes (K8s) 的 HPA(Horizontal Pod Autoscaler,水平 Pod 自动扩缩容) 控制器,需从「基础概念→前提条件→核心原理→实践操作→高级配置」逐步拆解,最终实现 "理解逻辑 + 动手落地"。以下是系统化的学习指南:

1 HPA 是什么?为什么需要它?

1.1 HPA 的核心作用

HPA 是 K8s 中负责 "根据资源使用率或自定义指标,自动调整 Pod 副本数量" 的控制器,解决以下问题:

  • 高峰期:Pod 负载过高(如 CPU 使用率 90%),自动增加副本(扩容),避免服务卡顿;
  • 低谷期:Pod 负载过低(如 CPU 使用率 10%),自动减少副本(缩容),节省资源。

1.2 HPA 与其他扩缩容的区别

类型 作用范围 触发方式 典型场景
HPA(水平) Pod 副本数(横向扩展) 指标触发(CPU / 内存 / 自定义) 业务流量波动(如电商促销)
VPA(垂直) Pod 资源配额(纵向扩展) 指标触发(资源不足) 单 Pod 性能瓶颈(如内存不够)
手动扩缩容 Pod 副本数 人工执行 kubectl scale 临时调整(如紧急修复)

本文聚焦 HPA,这是生产环境中最常用的自动扩缩容方案。

2 前提条件:HPA 依赖什么?

HPA 本身不收集指标,需依赖外部组件提供 "指标数据",核心依赖是 Metrics Server(K8s 官方的基础指标采集组件)。

2.1 必须部署 Metrics Server

Metrics Server 负责从 Kubelet 采集 Pod/Node 的 基础指标 (CPU 使用率、内存使用率),并通过 K8s API(metrics.k8s.io)暴露给 HPA。

部署 Metrics Server(步骤)
  1. 下载官方部署文件(适配 K8s 1.24+,低版本需调整):

    bash 复制代码
    wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
  2. 编辑 components.yaml,在 spec.containers.args中添加--kubelet-insecure-tls

    (跳过 Kubelet 证书验证,测试环境用;生产环境需配置证书):

    yaml 复制代码
    spec:
      containers:
      - name: metrics-server
        image: k8s.gcr.io/metrics-server/metrics-server:v0.6.4  # 替换为最新版本
        args:
          - --cert-dir=/tmp
          - --secure-port=4443
          - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
          - --kubelet-use-node-status-port
          - --kubelet-insecure-tls  # 新增这行(测试环境)
  3. 部署并验证:

    bash 复制代码
    # 部署
    kubectl apply -f components.yaml
    
    # 检查 Pod 是否运行(命名空间 kube-system)
    kubectl get pods -n kube-system | grep metrics-server
    
    # 验证指标是否能获取(查看 Node/Pod 指标)
    kubectl top node  # 查看节点 CPU/内存使用
    kubectl top pod   # 查看 Pod CPU/内存使用

    ✅ 若 kubectl top能正常输出指标,说明 Metrics Server 部署成功,HPA 可正常获取基础指标。

3 核心原理:HPA 如何决策扩缩容?

3.1 步骤 1:采集指标

HPA 定期(默认 15 秒,可通过 --horizontal-pod-autoscaler-sync-period 调整)从 Metrics Server 或自定义指标源(如 Prometheus)获取指标,支持 3 类指标:

  • 资源指标(Resource Metrics):K8s 内置的 CPU / 内存,基于 Pod 请求(Request)计算使用率(如 "CPU 使用率 50%"= 实际使用 / Request);
  • 容器资源指标(Container Resource Metrics):针对单个容器的 CPU / 内存(而非整个 Pod);
  • 自定义指标(Custom Metrics):业务指标(如 QPS、请求延迟、并发用户数),需依赖 Prometheus + k8s-prometheus-adapter 等组件。

3.2 步骤 2:计算期望副本数

HPA 基于 "当前指标值" 和 "目标指标值",通过公式计算 期望副本数,核心公式如下:

plaintext 复制代码
期望副本数 = ceil(当前副本数 × (当前指标值 / 目标指标值))
  • 例:当前副本数 = 2,目标 CPU 使用率 = 50%,实际 CPU 使用率 = 100%

    期望副本数 = 2 × (100%/50%)=4 → 自动扩容到 4 个副本。

关键约束(避免极端情况):
  • 最小副本数(minReplicas):扩缩容的下限(如至少 2 个副本,避免缩到 0);
  • 最大副本数(maxReplicas):扩缩容的上限(如最多 10 个副本,避免资源耗尽);
  • 容忍阈值:指标波动在 ±10% 内(默认),不触发扩缩容(避免频繁调整);
  • 冷却时间:扩容后需等待 3 分钟(默认)才能再次扩容,缩容后需等待 5 分钟(默认)才能再次缩容(避免 "震荡")。

3.3 步骤 3:执行扩缩容

HPA 通过 K8s API 调用 Deployment/StatefulSet 的 scale 接口,修改其 replicas 字段,实现 Pod 副本数的自动调整。

4 实践操作:从零实现 HPA 扩缩容

4.1 准备测试资源(Deployment + Service)

先创建一个简单的 Nginx Deployment(模拟业务服务),并配置 CPU Request(HPA 计算使用率的基础):

yaml 复制代码
# 新建文件:nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
spec:
  replicas: 2  # 初始副本数
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        resources:
          requests:  # HPA 依赖 Request 计算使用率,必须配置!
            cpu: 100m  # 100 毫核(0.1 CPU)
            memory: 128Mi
          limits:
            cpu: 200m
            memory: 256Mi
---
# 可选:创建 Service(方便外部访问压测)
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
  type: NodePort  # 测试环境用 NodePort 暴露服务

部署资源:

bash 复制代码
kubectl apply -f nginx-deployment.yaml

# 验证:Deployment 副本数是否为 2
kubectl get deploy nginx-deploy
# 输出示例:READY   UP-TO-DATE   AVAILABLE   AGE
#          2/2     2            2           1m

4.2 创建 HPA 资源

通过 YAML 文件创建 HPA,配置 "基于 CPU 使用率的扩缩容规则":

yaml 复制代码
# 新建文件:nginx-hpa.yaml
apiVersion: autoscaling/v2  # 注意版本:v2 支持更多指标(v1 仅支持 CPU)
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  scaleTargetRef:  # 关联的 Deployment(HPA 要控制的目标)
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-deploy
  minReplicas: 2  # 最小副本数(避免缩到 0)
  maxReplicas: 10  # 最大副本数(避免资源耗尽)
  metrics:  # 扩缩容指标配置(这里用 CPU 使用率)
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization  # 基于"使用率"(而非绝对值)
        averageUtilization: 50  # 目标 CPU 使用率:50%

创建 HPA 并验证:

bash 复制代码
# 创建 HPA
kubectl apply -f nginx-hpa.yaml

# 查看 HPA 状态(关键!观察指标和副本数)
kubectl get hpa nginx-hpa -o wide
# 输出示例(初始状态,负载低):
# NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
# nginx-hpa    Deployment/nginx-deploy  5%/50%    2         10        2          1m
  • TARGETS:左侧是 "当前 CPU 使用率"(5%),右侧是 "目标使用率"(50%);
  • REPLICAS:当前副本数(2),未触发扩缩容。

4.3 模拟负载,验证 HPA 扩容

通过 busybox 容器向 Nginx 发送大量请求,触发 CPU 使用率升高,观察 HPA 是否自动扩容。

步骤 1:启动 busybox 压测容器
bash 复制代码
# 启动一个交互式 busybox 容器
kubectl run -it --rm load-generator --image=busybox /bin/sh
步骤 2:在 busybox 内执行压测命令

先获取 Nginx Service 的 ClusterIP(或 NodePort + 节点 IP):

bash 复制代码
# 在 busybox 容器内执行(获取 Nginx Service 的 ClusterIP)
NGINX_SVC_IP=$(kubectl get svc nginx-svc -o jsonpath='{.spec.clusterIP}')

# 执行压测(用 wget 循环请求 Nginx,消耗 CPU)
while true; do wget -q -O /dev/null $NGINX_SVC_IP; done
步骤 3:观察 HPA 状态变化

打开新的终端窗口,每隔 10 秒查看 HPA 状态:

bash 复制代码
watch kubectl get hpa nginx-hpa -o wide
预期结果:
  1. 随着压测进行,TARGETS 中的 "当前 CPU 使用率" 会从 5% 上升到 50% 以上;

  2. HPA 检测到指标超标后,会逐步将 REPLICAS 从 2 扩容到 4、6...(直到 CPU 使用率降至 50% 左右);

  3. 查看 Deployment 副本数,确认已扩容:

    bash 复制代码
    kubectl get deploy nginx-deploy
    # 输出示例:READY   UP-TO-DATE   AVAILABLE   AGE
    #          6/6     6            6           5m

4.4 停止负载,验证 HPA 缩容

步骤 1:停止压测

在 busybox 容器内按 Ctrl+C 停止循环请求,然后退出容器(容器会自动删除):

bash 复制代码
exit
步骤 2:观察 HPA 缩容

继续用 watch 查看 HPA 状态:

bash 复制代码
watch kubectl get hpa nginx-hpa -o wide
预期结果:
  1. CPU 使用率逐步下降到 50% 以下;
  2. 等待 5 分钟(默认缩容冷却时间) 后,HPA 会将副本数从 6 逐步缩回到 2(minReplicas);
  3. 最终 REPLICAS 恢复为 2,TARGETS 回到 5%/50% 左右。

5 高级配置:自定义 HPA 行为

默认的扩缩容规则(如冷却时间、扩容速度)可能不满足生产需求,可通过 behavior 字段自定义 HPA 行为。

示例:自定义扩缩容策略

yaml 复制代码
# 新建文件:nginx-hpa-advanced.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa-advanced
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-deploy
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
  # 自定义扩缩容行为
  behavior:
    scaleUp:  # 扩容策略
      stabilizationWindowSeconds: 60  # 扩容前等待 60 秒(确认指标稳定)
      policies:
      - type: Percent  # 按百分比扩容
        value: 50      # 每次扩容 50% 的副本数(如当前 2 个,扩到 3 个)
        periodSeconds: 60  # 每 60 秒最多扩容一次
    scaleDown:  # 缩容策略
      stabilizationWindowSeconds: 300  # 缩容前等待 300 秒(避免误缩容)
      policies:
      - type: Fixed  # 按固定数量缩容
        value: 1      # 每次缩容 1 个副本
        periodSeconds: 120  # 每 120 秒最多缩容一次

部署后,HPA 会按自定义的策略扩缩容,更贴合生产环境的稳定性需求。

6 常见问题与排查技巧

在使用 HPA 时,经常会遇到 "指标获取失败""不扩缩容" 等问题,以下是高频问题的排查方法:

6.1 HPA 状态显示 "unknown"(指标获取失败)

bash 复制代码
# 查看 HPA 详细事件(关键!)
kubectl describe hpa nginx-hpa
常见原因:
  • Metrics Server 未部署或运行异常:检查 kubectl get pods -n kube-system | grep metrics-server
  • Pod 未配置 CPU Request:HPA 无法计算使用率,需在 Deployment 中添加 resources.requests.cpu
  • 网络问题:Metrics Server 无法访问 Kubelet,检查网络策略或防火墙。

6.2 HPA 指标达标但不扩缩容

排查步骤:
  1. 查看 HPA 事件,确认是否有 "忽略扩缩容" 的原因(如冷却时间未到);
  2. 检查 Deployment 的副本数是否已达 maxReplicas(扩容上限)或 minReplicas(缩容下限);
  3. 验证指标是否真实达标:用 kubectl top pod <pod-name> 查看单个 Pod 的指标,确认不是 "平均指标达标但单个 Pod 未达标"。

6.3 自定义指标无法使用

需确认:

  • 已部署自定义指标适配器(如 k8s-prometheus-adapter);
  • 自定义指标已通过 custom.metrics.k8s.io API 暴露;
  • HPA 的 metrics 字段配置正确(参考适配器文档)。

7 学习路径总结

掌握 HPA 的核心步骤可归纳为:

  1. 基础准备:部署 Metrics Server,理解指标采集逻辑;
  2. 入门实践:基于 CPU / 内存指标创建 HPA,模拟负载验证扩缩容;
  3. 进阶学习:配置自定义指标(如 Prometheus 指标)、自定义扩缩容行为;
  4. 生产落地:结合监控工具(如 Grafana)观察 HPA 效果,优化策略。
相关推荐
开发者导航1 天前
【开发者导航】支持多存储方式的开源文件列表程序:OpenList
人工智能·学习·阿里云·信息可视化
GISer_Jing1 天前
前端学习总结——AI&主流前沿方向篇
前端·人工智能·学习
荣光波比1 天前
K8S(九)—— Kubernetes持久化存储深度解析:从Volume到PV/PVC与动态存储
云原生·容器·kubernetes
William_cl1 天前
一、前置基础(MVC学习前提)_核心特性_【C# 泛型入门】为什么说 List<T>是程序员的 “万能收纳盒“?避坑指南在此
学习·c#·mvc
Nan_Shu_6141 天前
熟悉RuoYi-Vue-Plus4.8.2-后端
学习
XiangrongZ1 天前
江协科技STM32课程笔记(四)—定时器TIM(输入捕获)
笔记·科技·stm32
koo3641 天前
李宏毅机器学习笔记24
人工智能·笔记·机器学习
xyx-3v1 天前
SPI四种工作模式
stm32·单片机·嵌入式硬件·学习
老虎06271 天前
黑马点评学习笔记02(Mabatis—plus)
笔记·学习