Kubernetes 的 Horizontal Pod Autoscaler (HPA) 是处理突发流量和资源波动的关键机制。HPA 能够根据观测到的 CPU 利用率、内存使用量或自定义指标,自动调整 Deployment 或 ReplicaSet 中 Pod 的副本数量。
本文将通过一个实际的案例,演示如何配置 HPA,并使用负载生成器模拟流量高峰,观察 Kubernetes 自动扩容的全过程。
前提条件
- 一个正在运行的 Kubernetes 集群(例如 Minikube 或任何云服务商提供的集群)。
- 已安装 kubectl。
- Metrics Server 已安装并运行。 HPA 依赖 Metrics Server 来获取 Pod 的 CPU 和内存使用数据。大多数 K8s 集群默认安装,如果未安装,可以使用以下命令安装:
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
步骤一:部署应用与配置资源请求
HPA 依赖于 Pod 定义中设定的资源请求(requests.cpu)来计算利用率百分比。如果没有设置资源请求,HPA 将无法基于 CPU 利用率进行扩缩容。
我们将部署一个基于 k8s.gcr.io/hpa-example 镜像的 Deployment,该镜像是一个简单的 PHP/Apache 容器,当被访问时会消耗 CPU。
创建文件 app.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
selector:
matchLabels:
app: php-apache
replicas: 1
template:
metadata:
labels:
app: php-apache
spec:
containers:
- name: php-apache
image: registry.k8s.io/hpa-example
ports:
- containerPort: 80
resources:
requests:
cpu: 200m # 请求 200 milli-CPU
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
spec:
ports:
- port: 80
selector:
app: php-apache
type: LoadBalancer # 或者 NodePort/ClusterIP,取决于你的环境
应用部署:
kubectl apply -f app.yaml
步骤二:创建 Horizontal Pod Autoscaler
现在我们定义 HPA 规则。我们的目标是:当 Pod 的平均 CPU 利用率超过 50% 时,启动扩容,最小副本数为 1,最大副本数为 10。
创建文件 hpa.yaml:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: php-apache-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache # 目标 Deployment 的名称
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50 # 目标平均 CPU 利用率 50%
应用 HPA 配置:
kubectl apply -f hpa.yaml
检查 HPA 状态:
kubectl get hpa
# NAME REFERENCE TARGET MINPODS MAXPODS REPLICAS AGE
# php-apache-hpa Deployment/php-apache 0%/50% 1 10 1 30s
此时,目标 CPU 利用率为 50%,当前利用率为 0%,副本数为 1。
步骤三:模拟突发流量(负载生成)
我们将启动一个临时的 busybox Pod,并让它不断向 php-apache 服务发起请求,模拟突发流量,从而推高 CPU 利用率。
执行以下命令,启动负载生成器:
kubectl run -it --rm load-generator --image=busybox /bin/sh
# 此时进入 load-generator 容器内部
# 在容器内部执行以下命令,持续访问服务:
while true; do wget -q -O - http://php-apache; done
步骤四:观察自动扩缩容过程
保持负载生成器运行,并在另一个终端持续监控 HPA 状态:
kubectl get hpa -w
你会观察到 TARGET 列的数值迅速上升,超过 50%。一旦稳定超过目标值(HPA 默认需要等待约 30 秒的稳定期),K8s 就会触发扩容:
| NAME | REFERENCE | TARGET | MINPODS | MAXPODS | REPLICAS | AGE |
|---|---|---|---|---|---|---|
| php-apache-hpa | Deployment/php-apache | 150%/50% | 1 | 10 | 1 | 2m |
| php-apache-hpa | Deployment/php-apache | 150%/50% | 1 | 10 | 3 | 2m (扩容到3个副本) |
同时,检查 Pod 状态,可以看到新的 Pod 正在创建中:
kubectl get pods
# php-apache-xxxx-yyyy Running
# php-apache-xxxx-zzzz ContainerCreating
# php-apache-xxxx-wwww ContainerCreating
随着副本数的增加(例如达到 3 或 4 个),总的 CPU 负载被分散,单个 Pod 的平均 CPU 利用率会下降,最终回到目标值 50% 附近,扩容停止。
步骤五:停止负载并观察缩容
在 load-generator 容器的终端中,使用 Ctrl+C 停止 while 循环,停止流量。
再次观察 HPA 状态。当 CPU 利用率降至目标值以下并持续一段时间(默认缩容冷却期为 5 分钟)后,HPA 会自动触发缩容,将副本数逐渐减少到 minReplicas (1) 的值。
关键总结:HPA 的工作原理
HPA 扩容的核心公式是:
$$\text{所需副本数} = \lceil\frac{\text{当前指标值}}{\text{目标指标值}} \times \text{当前副本数}\rceil$$
例如,如果当前平均 CPU 利用率为 150%,目标是 50%,当前副本数是 1:
$$\text{所需副本数} = \lceil\frac{150\%}{50\%} \times 1\rceil = 3$$
K8s 会立即将副本数调整为 3。
汤不热吧