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 效果,优化策略。
相关推荐
吃好睡好便好15 小时前
创建上三角矩阵和下三角矩阵
开发语言·学习·线性代数·matlab·矩阵
nashane15 小时前
HarmonyOS 6学习:异步操作中Toast提示框消失之谜与UIContext解决方案实战
学习·华为·harmonyos
知悟之旅15 小时前
你不是在舒适区,你在漂移
学习·生活
MaxineZhou16 小时前
AI学习记录
学习
Bechamz16 小时前
大数据开发学习Day41
大数据·学习
星夜夏空9916 小时前
STM32单片机学习(27) —— SPI相关概念
stm32·单片机·学习
万物皆字节16 小时前
【记录】安装nodejs,miniconda后本地设置
笔记
z2005093016 小时前
【linux学习】linux下进程状态和环境变量的解析
linux·运维·学习
智者知已应修善业16 小时前
【51单片机按键加减最大60显示0不再增加减到0不再减】2023-11-18
c++·经验分享·笔记·算法·51单片机
lunzi_082616 小时前
【学习笔记】《Python编程 从入门到实践》第1章:Python环境搭建与Hello World(完整版)
笔记·python·学习