自动扩缩容
自动扩缩容是 Kubernetes 最重要的特性之一,它让集群能够根据负载自动调整资源,既保证了应用的可用性,又避免了资源浪费。Kubernetes 提供了多种自动扩缩容机制,本章将详细介绍水平 Pod 自动扩缩容(HPA)、垂直 Pod 自动扩缩容(VPA)以及它们的使用方法。
扩缩容的基本概念
在深入了解具体技术之前,我们需要理解两种基本的扩缩容方式。
水平扩缩容 vs 垂直扩缩容
水平扩缩容(Horizontal Scaling)意味着增加或减少 Pod 的副本数量。当负载增加时,启动更多的 Pod 来分担压力;当负载减少时,关闭多余的 Pod 节省资源。这就像是餐厅在繁忙时段增加服务员数量。
垂直扩缩容(Vertical Scaling)意味着调整单个 Pod 的资源配置,比如增加 CPU 或内存的请求量和限制量。这就像是给现有的服务员分配更大的工作区域。
两种方式各有优缺点:
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 水平扩缩容 | 无需重启,响应快,适合无状态应用 | 需要应用支持多副本 | Web 服务、API 服务 |
| 垂直扩缩容 | 不增加复杂度,适合单实例应用 | 需要重启 Pod,调整范围有限 | 数据库、有状态应用 |
水平 Pod 自动扩缩容(HPA)
HorizontalPodAutoscaler(HPA)是 Kubernetes 内置的水平扩缩容控制器,它根据观测到的 CPU 利用率、内存使用量或自定义指标自动调整 Pod 副本数。
HPA 的工作原理
HPA 的核心是一个控制循环,定期检查目标工作负载的指标,然后计算期望的副本数。整个过程可以概括为以下几个步骤:
- 指标采集:HPA 控制器通过 Metrics API 获取当前指标值
- 计算期望副本数:根据当前指标值和目标值计算期望副本数
- 调整副本数:更新工作负载的 replicas 字段
计算公式如下:
例如,当前有 4 个副本,CPU 利用率为 80%,目标利用率为 40%:
前提条件
使用 HPA 需要安装 Metrics Server,它负责收集 Pod 和节点的资源使用指标。
# 安装 Metrics Server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# 验证安装
kubectl get deployment metrics-server -n kube-system
kubectl get pods -n kube-system -l k8s-app=metrics-server
# 测试指标采集
kubectl top nodes
kubectl top pods
如果 Metrics Server 正常工作,kubectl top 命令会显示节点和 Pod 的资源使用情况。
创建 HPA
命令行方式
最简单的方式是使用 kubectl autoscale 命令:
# 为 Deployment 创建 HPA
kubectl autoscale deployment my-app --cpu-percent=50 --min=2 --max=10
# 查看创建的 HPA
kubectl get hpa
这条命令创建了一个 HPA,它会保持 my-app 的 CPU 利用率在 50% 左右,副本数在 2 到 10 之间。
YAML 方式
更推荐使用 YAML 文件定义 HPA,便于版本控制和复用:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
基于多种指标的扩缩容
HPA 支持同时使用多种指标,取计算结果的最大值:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
# CPU 利用率
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
# 内存利用率
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 70
当多个指标同时配置时,HPA 会为每个指标计算期望副本数,然后选择最大的那个值。这样保证了任何一个指标超标都能触发扩容。
自定义指标扩缩容
除了 CPU 和内存,HPA 还支持自定义指标,比如请求速率、队列长度等。这需要安装 Prometheus Adapter 来暴露自定义指标。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 20
metrics:
# 使用 Pods 类型的自定义指标
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: 1000
这个例子中,当每个 Pod 的 HTTP 请求速率超过 1000 次/秒时,就会触发扩容。
扩缩容行为配置
Kubernetes 允许精细控制扩缩容的行为,避免副本数剧烈波动:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
behavior:
# 缩容行为
scaleDown:
stabilizationWindowSeconds: 300 # 稳定窗口 5 分钟
policies:
- type: Percent
value: 10 # 每次最多缩容 10%
periodSeconds: 60
- type: Pods
value: 2 # 每次最多缩容 2 个 Pod
periodSeconds: 60
selectPolicy: Min # 选择限制最严格的策略
# 扩容行为
scaleUp:
stabilizationWindowSeconds: 0 # 无稳定窗口,立即扩容
policies:
- type: Percent
value: 100 # 可以翻倍扩容
periodSeconds: 15
- type: Pods
value: 4 # 每次最多扩容 4 个 Pod
periodSeconds: 15
selectPolicy: Max # 选择允许最大扩容的策略
配置说明:
stabilizationWindowSeconds:稳定窗口期,在此期间内即使指标满足条件也不会执行扩缩容,防止震荡policies:扩缩容策略列表,可以定义多个策略selectPolicy:策略选择方式Max:选择允许最大变化的策略(默认)Min:选择允许最小变化的策略Disabled:禁用该方向的扩缩容
容器级别的资源指标
从 Kubernetes 1.30 开始,HPA 支持容器级别的资源指标,可以针对 Pod 中的特定容器进行扩缩容:
metrics:
- type: ContainerResource
containerResource:
name: cpu
container: application # 指定容器名称
target:
type: Utilization
averageUtilization: 60
这对于包含 sidecar 容器的 Pod 特别有用,可以根据主要应用的资源使用情况扩缩容,忽略 sidecar 的影响。
查看 HPA 状态
# 查看 HPA 列表
kubectl get hpa
# 查看详细信息
kubectl describe hpa my-app-hpa
# 查看扩缩容事件
kubectl get events --field-selector reason=SuccessfulRescale
kubectl get hpa 的输出示例:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
my-app-hpa Deployment/my-app 45%/50% 2 10 4 10m
常见问题排查
HPA 无法获取指标
# 检查 Metrics Server 是否正常运行
kubectl get deployment metrics-server -n kube-system
kubectl get pods -n kube-system -l k8s-app=metrics-server
# 检查 Metrics Server 日志
kubectl logs -n kube-system deployment/metrics-server
Pod 没有设置资源请求
HPA 需要知道 Pod 的资源请求才能计算利用率。如果 Pod 没有设置 resources.requests,HPA 无法工作:
# 确保 Pod 定义中包含资源请求
resources:
requests:
cpu: 100m
memory: 128Mi
扩缩容过于频繁
调整稳定窗口期和扩缩容策略:
behavior:
scaleDown:
stabilizationWindowSeconds: 600 # 增加稳定窗口
scaleUp:
stabilizationWindowSeconds: 60
垂直 Pod 自动扩缩容(VPA)
VerticalPodAutoscaler(VPA)自动调整 Pod 的 CPU 和内存请求,确保应用获得足够的资源而不浪费。与 HPA 不同,VPA 不是 Kubernetes 内置功能,需要单独安装。
VPA 的工作原理
VPA 由三个组件组成:
- Recommender:监控历史资源使用情况,生成资源推荐
- Updater:检查 Pod 是否需要更新,驱逐需要更新的 Pod
- Admission Controller:在 Pod 创建时注入推荐的资源请求
安装 VPA
# 下载 VPA
git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler
# 安装 VPA(需要 kubectl 连接到集群)
./hack/vpa-up.sh
# 验证安装
kubectl get deployment -n kube-system | grep vpa
VPA 更新模式
VPA 支持四种更新模式:
| 模式 | 说明 | 行为 |
|---|---|---|
Off | 推荐 | 只生成推荐,不自动更新 |
Initial | 仅在创建时更新 | 新 Pod 使用推荐值,现有 Pod 不变 |
Recreate | 重建更新 | 驱逐现有 Pod,新 Pod 使用推荐值 |
Auto | 自动 | 目前等同于 Recreate 模式 |
创建 VPA
推荐模式(Off)
先使用 Off 模式观察推荐值:
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: my-app-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
updatePolicy:
updateMode: "Off" # 只生成推荐
resourcePolicy:
containerPolicies:
- containerName: "*"
minAllowed:
cpu: 100m
memory: 128Mi
maxAllowed:
cpu: 2
memory: 4Gi
controlledResources: ["cpu", "memory"]
查看推荐值:
kubectl describe vpa my-app-vpa
输出示例:
Recommendation:
Container Recommendations:
Container Name: app
Lower Bound:
Cpu: 100m
Memory: 256Mi
Target:
Cpu: 250m # 推荐的 CPU 请求
Memory: 512Mi # 推荐的内存请求
Uncapped Target:
Cpu: 250m
Memory: 512Mi
Upper Bound:
Cpu: 500m
Memory: 1Gi
自动更新模式
确认推荐值合理后,切换到 Auto 模式:
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: my-app-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: "*"
minAllowed:
cpu: 100m
memory: 128Mi
maxAllowed:
cpu: 2
memory: 4Gi
资源边界控制
VPA 允许设置资源的最小和最大边界,防止资源设置过低或过高:
resourcePolicy:
containerPolicies:
- containerName: app
mode: Auto
minAllowed:
cpu: 100m
memory: 256Mi
maxAllowed:
cpu: 4
memory: 8Gi
# 设置资源边界为推荐值的百分比
minReplicas: 1
maxReplicas: 100
HPA 与 VPA 的配合使用
HPA 和 VPA 可以配合使用,但需要谨慎配置以避免冲突。
配合原则
- 不要对同一资源同时启用 HPA 和 VPA 的 CPU 扩缩容
- HPA 负责副本数,VPA 负责单个 Pod 的资源配置
- HPA 使用自定义指标或内存指标,VPA 负责 CPU
推荐配置
# VPA 配置 - 管理资源配置
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: my-app-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
updatePolicy:
updateMode: "Initial" # 只在创建时更新
resourcePolicy:
containerPolicies:
- containerName: "*"
controlledResources: ["cpu"] # VPA 只管理 CPU
---
# HPA 配置 - 管理副本数
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: memory # HPA 使用内存指标
target:
type: Utilization
averageUtilization: 70
集群自动扩缩容(Cluster Autoscaler)
当 Pod 因资源不足无法调度时,Cluster Autoscaler 可以自动添加节点;当节点长时间闲置时,可以自动删除节点。
工作原理
- 监控集群中 Pending 的 Pod
- 如果有 Pod 因资源不足无法调度,触发扩容
- 计算需要的节点数,请求云提供商创建节点
- 当节点利用率低于阈值(默认 50%)且持续一定时间,触发缩容
部署示例
在云环境中部署 Cluster Autoscaler:
apiVersion: apps/v1
kind: Deployment
metadata:
name: cluster-autoscaler
namespace: kube-system
spec:
selector:
matchLabels:
app: cluster-autoscaler
template:
metadata:
labels:
app: cluster-autoscaler
spec:
serviceAccountName: cluster-autoscaler
containers:
- name: cluster-autoscaler
image: k8s.gcr.io/autoscaling/cluster-autoscaler:v1.8.0
command:
- ./cluster-autoscaler
- --scale-down-unneeded-time=10m
- --balance-similar-node-groups
- --expander=priority
env:
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: aws-credentials
key: access-key-id
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: aws-credentials
key: secret-access-key
resources:
limits:
cpu: 100m
memory: 300Mi
requests:
cpu: 100m
memory: 300Mi
最佳实践
1. 始终设置资源请求
HPA 和 VPA 都依赖资源请求来工作:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
2. 合理设置扩缩容范围
spec:
minReplicas: 2 # 保证高可用
maxReplicas: 20 # 防止资源失控
3. 使用稳定窗口防止震荡
behavior:
scaleDown:
stabilizationWindowSeconds: 300
scaleUp:
stabilizationWindowSeconds: 60
4. 先使用 VPA Off 模式观察
不要一开始就启用 VPA Auto 模式,先用 Off 模式观察推荐值是否合理。
5. 配置 Pod 中断预算
自动扩缩容会导致 Pod 重启,配置 PDB 保证服务可用性:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: my-app
6. 监控扩缩容事件
# 实时监控 HPA 事件
kubectl get events -w --field-selector reason=SuccessfulRescale
# 查看 VPA 推荐
kubectl describe vpa my-app-vpa
7. 测试扩缩容行为
使用负载测试工具验证扩缩容是否正常工作:
# 使用 kubectl run 生成负载
kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://my-app; done"
小结
本章我们学习了:
- 扩缩容概念:水平扩缩容和垂直扩缩容的区别
- HPA:基于 CPU/内存/自定义指标的自动扩缩容
- VPA:自动调整 Pod 资源配置
- 配合使用:HPA 和 VPA 如何协同工作
- Cluster Autoscaler:自动调整集群节点数
- 最佳实践:资源请求、稳定窗口、监控等
自动扩缩容是 Kubernetes 弹性伸缩的核心能力,合理配置可以让应用在保证性能的同时最大化资源利用率。
练习
- 安装 Metrics Server 并验证
kubectl top命令 - 创建一个 Deployment 并配置 HPA,测试自动扩缩容
- 安装 VPA,使用 Off 模式查看资源推荐
- 配置扩缩容行为,设置稳定窗口期
- 使用负载生成工具测试 HPA 的扩容效果