要掌握 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(步骤)
-
下载官方部署文件(适配 K8s 1.24+,低版本需调整):
bashwget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
-
编辑
components.yaml
,在spec.containers.args
中添加--kubelet-insecure-tls
(跳过 Kubelet 证书验证,测试环境用;生产环境需配置证书):
yamlspec: 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 # 新增这行(测试环境)
-
部署并验证:
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
预期结果:
-
随着压测进行,
TARGETS
中的 "当前 CPU 使用率" 会从 5% 上升到 50% 以上; -
HPA 检测到指标超标后,会逐步将
REPLICAS
从 2 扩容到 4、6...(直到 CPU 使用率降至 50% 左右); -
查看 Deployment 副本数,确认已扩容:
bashkubectl 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
预期结果:
- CPU 使用率逐步下降到 50% 以下;
- 等待 5 分钟(默认缩容冷却时间) 后,HPA 会将副本数从 6 逐步缩回到 2(minReplicas);
- 最终
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 指标达标但不扩缩容
排查步骤:
- 查看 HPA 事件,确认是否有 "忽略扩缩容" 的原因(如冷却时间未到);
- 检查 Deployment 的副本数是否已达
maxReplicas
(扩容上限)或minReplicas
(缩容下限); - 验证指标是否真实达标:用
kubectl top pod <pod-name>
查看单个 Pod 的指标,确认不是 "平均指标达标但单个 Pod 未达标"。
6.3 自定义指标无法使用
需确认:
- 已部署自定义指标适配器(如 k8s-prometheus-adapter);
- 自定义指标已通过
custom.metrics.k8s.io
API 暴露; - HPA 的
metrics
字段配置正确(参考适配器文档)。
7 学习路径总结
掌握 HPA 的核心步骤可归纳为:
- 基础准备:部署 Metrics Server,理解指标采集逻辑;
- 入门实践:基于 CPU / 内存指标创建 HPA,模拟负载验证扩缩容;
- 进阶学习:配置自定义指标(如 Prometheus 指标)、自定义扩缩容行为;
- 生产落地:结合监控工具(如 Grafana)观察 HPA 效果,优化策略。