1. 项目概述
这个Kubernetes HPA(Horizontal Pod Autoscaler)实战实验,模拟了生产环境中常见的业务流量激增场景。作为一名云原生架构师,我经常需要处理这类自动扩缩容问题。本次实验将带你从零开始,完整实现一个基于CPU指标的自动扩缩容方案,并深入探讨其中的技术细节和实战经验。
HPA是Kubernetes中最实用的自动扩缩容机制之一,它能够根据设定的指标(如CPU、内存使用率)动态调整Pod副本数量。在实际生产环境中,合理配置HPA可以显著提高资源利用率,同时保证服务稳定性。本次实验使用的Kubernetes版本为1.35,运行在CentOS 10系统上。
2. 环境准备与部署
2.1 基础环境检查
在开始实验前,必须确保以下组件正常运行:
- Metrics-Server:这是HPA的核心依赖组件,负责收集资源指标数据。检查是否安装:
bash复制kubectl get pods -n kube-system | grep metrics-server
如果未安装,可以使用以下命令快速部署:
bash复制kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
- kubectl版本:确保客户端版本与集群匹配(1.35+)
bash复制kubectl version --short
- 节点资源:实验至少需要2个Worker节点,每个节点配置2核CPU和4GB内存以上。
2.2 部署应用与HPA
实验使用一个CPU密集型的PHP Apache服务作为测试应用。以下是完整的部署文件(hpa-practice.yaml):
yaml复制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: k8s.gcr.io/hpa-example:latest
ports:
- containerPort: 80
resources:
requests:
cpu: 200m # HPA计算基准值
limits:
cpu: 500m # 容器最大CPU限制
---
apiVersion: v1
kind: Service
metadata:
name: hpa-worker-service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: hpa-worker
---
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
部署命令:
bash复制kubectl apply -f hpa-practice.yaml
关键点:必须为容器配置resources.requests.cpu,否则HPA无法计算利用率百分比。这个值将作为基准(分母)用于计算当前使用率。
3. 实验过程与观察
3.1 初始状态检查
部署完成后,首先验证各组件状态:
- 检查Pod运行状态:
bash复制kubectl get pods -l app=hpa-worker
应看到1个Running状态的Pod。
- 检查HPA状态:
bash复制kubectl get hpa worker-hpa
正常输出应类似:
code复制NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
worker-hpa Deployment/hpa-worker 0%/50% 1 10 1 2m
如果TARGETS列显示<unknown>/50%,通常有两个原因:
- Metrics-Server未正常运行
- Pod刚刚创建,尚未产生足够的监控数据(等待1-2分钟)
3.2 压力测试实施
为了观察HPA的动态调整,我们需要模拟高CPU负载。建议打开三个终端窗口:
窗口1:实时监控HPA状态变化
bash复制kubectl get hpa worker-hpa -w
窗口2:监控Pod数量变化
bash复制kubectl get pods -l app=hpa-worker -w
窗口3:启动负载生成器
bash复制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"
这个命令会创建一个临时Pod,不断向我们的服务发送请求,模拟高并发访问。
3.3 扩容过程观察
随着压测进行,你将观察到以下现象:
-
CPU利用率上升:在窗口1中,TARGETS列的数值会从0%快速上升,可能达到150%甚至更高。
-
Pod自动扩容:当CPU利用率超过50%阈值后,HPA开始增加Pod数量。REPLICAS列会从1逐步增加到3、6,最终可能达到maxReplicas设置的10。
-
新Pod创建:窗口2会显示大量新Pod处于ContainerCreating或Running状态。
扩容过程通常需要1-2分钟完成,具体时间取决于集群资源和调度速度。
3.4 负载均衡验证
当Pod数量增加到一定程度后,CPU利用率会逐渐回落到目标值(50%)附近。此时可以验证流量是否均匀分布:
bash复制kubectl top pods -l app=hpa-worker
输出应显示各Pod的CPU使用率大致相同,证明Service的负载均衡正常工作。
3.5 缩容过程观察
在窗口3按下Ctrl+C停止压测后:
-
CPU利用率下降:窗口1中TARGETS列数值会迅速降为0%。
-
缩容延迟:Kubernetes不会立即减少Pod数量,而是会等待约5分钟(默认冷却期)。这是为了防止"扩缩容震荡"——即刚缩容流量又突然增加的情况。
-
最终状态:约5分钟后,REPLICAS会逐步减少,最终回到minReplicas设置的1。
4. 核心原理深度解析
4.1 HPA算法详解
HPA的核心计算公式为:
code复制期望副本数 = ceil[当前副本数 × (当前指标值 / 目标指标值)]
以我们的实验为例:
- 当前副本数:1
- 当前CPU使用量:300m(即300毫核)
- 目标使用率:50%(基于requests.cpu=200m,即目标值为100m)
- 计算结果:ceil[1 × (300/100)] = 3
因此HPA会将副本数调整为3。
4.2 关键参数解析
-
metrics.type:支持多种指标类型
- Resource:基于CPU、内存等资源指标
- Pods:基于Pod自定义指标
- Object:基于特定对象的指标
-
target.type:
- Utilization:百分比形式(如CPU使用率)
- AverageValue:绝对值形式(如每秒请求数)
-
behavior(K8s 1.18+):控制扩缩容行为
- scaleUp/scaleDown:分别配置扩容和缩容策略
- stabilizationWindowSeconds:稳定窗口期
- policies:调整步长策略
4.3 Metrics-Server工作原理
Metrics-Server通过Kubelet的Summary API收集各节点的资源使用数据,存储在内存中(不持久化)。HPA控制器定期(默认15s)从Metrics-Server获取指标数据,计算后决定是否需要调整副本数。
5. 生产环境最佳实践
5.1 参数配置建议
-
requests与limits比例:
- CPU:limits建议是requests的2-3倍
- 内存:limits不应超过requests的1.5倍(内存是可压缩资源)
-
HPA阈值设置:
- 常规服务:CPU 50-70%,内存60-80%
- 关键业务:适当降低阈值(如CPU 40%),预留更多缓冲
-
副本数范围:
- minReplicas:至少2个,确保高可用
- maxReplicas:根据节点资源合理设置,避免资源耗尽
5.2 常见问题排查
-
HPA状态Unknown:
- 检查Metrics-Server是否运行
- 确认Pod配置了resources.requests
-
扩容不及时:
- 调整HPA的--horizontal-pod-autoscaler-sync-period参数(默认15s)
- 检查集群是否有足够资源
-
指标波动大:
- 适当增加stabilizationWindowSeconds
- 考虑使用多个指标综合判断
5.3 高级配置示例
对于需要快速扩容的场景,可以配置behavior:
yaml复制behavior:
scaleUp:
policies:
- type: Pods
value: 4
periodSeconds: 15
stabilizationWindowSeconds: 0
scaleDown:
policies:
- type: Pods
value: 1
periodSeconds: 600
stabilizationWindowSeconds: 600
这个配置表示:
- 扩容时每次最多增加4个Pod
- 缩容时每次只减少1个Pod,且至少间隔10分钟
6. 扩展实验建议
6.1 基于内存的自动扩缩容
修改HPA配置,使用内存作为指标:
yaml复制metrics:
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
内存测试需要使用专用工具,如:
bash复制kubectl exec -it <pod-name> -- /bin/sh
# 在容器内执行
stress-ng --vm 1 --vm-bytes 300M --vm-keep
特别注意:内存达到limit会导致容器被OOMKill,因此limits设置要谨慎。
6.2 多指标联合扩缩容
HPA支持同时监控多个指标,最终取各指标计算的最大副本数:
yaml复制metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
6.3 自定义指标扩缩容
结合Prometheus实现基于QPS的扩缩容:
- 部署Prometheus和Prometheus Adapter
- 配置自定义指标规则
- HPA配置示例:
yaml复制metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: 100
7. 实战经验总结
经过多次生产环境实践,我总结了以下关键经验:
-
监控先行:在启用HPA前,确保有完善的监控系统(如Prometheus+Grafana),能够实时观察Pod资源使用情况和HPA决策过程。
-
渐进式调整:初次配置时,建议先设置较宽松的阈值和较小的副本范围,观察系统行为后再逐步优化。
-
压力测试:使用真实业务场景的压力测试验证HPA配置,避免理论值与实际表现不符。
-
资源预留:集群必须保留足够资源应对突发扩容,建议至少预留30%的CPU和内存buffer。
-
日志记录:详细记录HPA的决策日志,便于后续分析和优化:
bash复制kubectl describe hpa worker-hpa
- 版本差异:不同Kubernetes版本的HPA行为可能有差异,升级时要特别注意兼容性问题。
在实际生产环境中,HPA通常需要与Cluster Autoscaler配合使用,才能真正实现弹性伸缩。当HPA需要扩容但节点资源不足时,Cluster Autoscaler可以自动添加新节点到集群中。