为什么需要 Cluster Autoscaler

在 Kubernetes 集群的日常运营中,资源管理始终是运维团队面临的核心挑战。Horizontal Pod Autoscaler(HPA)可以自动调整 Pod 副本数来应对负载变化,但当集群节点资源已经耗尽、无法调度新的 Pod 时,HPA 也无能为力——因为根本就没有足够的”车位”来停放更多的”车”。这正是 Cluster Autoscaler 要解决的核心问题。
Cluster Autoscaler 是 Kubernetes 官方提供的自动扩缩容组件,它负责在节点资源不足时自动向云服务商申请新节点,在节点资源空闲时自动释放节点。简单来说:HPA 管理 Pod 数量,Cluster Autoscaler 管理节点数量。两者配合使用,才能实现真正的”弹性伸缩”。
想象一个典型的电商场景:促销活动期间流量暴增,HPA 检测到 CPU 使用率超过阈值,将某个服务的 Pod 从 10 个扩容到 50 个。但集群只有 5 个节点,每个节点最多运行 8 个 Pod,总共只能容纳 40 个 Pod。这时 Cluster Autoscaler 检测到有 10 个 Pod 处于 Pending 状态,自动向云平台申请 2 个新节点加入集群。活动结束后,流量回落,HPA 将 Pod 缩减到 10 个,Cluster Autoscaler 发现节点利用率持续低于阈值,自动释放多余的节点。
Cluster Autoscaler 的工作原理
要正确配置和使用 Cluster Autoscaler,首先需要理解其核心决策逻辑。
扩容触发条件
Cluster Autoscaler 每隔 10 秒(默认 –scan-interval)检查一次集群中是否存在因资源不足而无法调度的 Pod。当以下条件同时满足时触发扩容:
- 存在 Pending 状态的 Pod(状态为
1Unschedulable
)
- 该 Pod 无法被任何现有节点调度
- 增加新节点后,该 Pod 能够被成功调度
值得注意的是,Cluster Autoscaler 并不会因为单个不可调度的 Pod 就立刻扩容。它会考虑多个因素,包括 Pod 的优先级(PriorityClass)、节点亲和性约束、以及是否有更优的调度方案。
缩容触发条件
缩容逻辑相对复杂,需要满足以下所有条件:
- 节点利用率低于阈值(默认 50%,可通过
1--scale-down-utilization-threshold
配置)
- 节点上的所有 Pod 可以被调度到其他节点
- 节点上不存在”不可迁移”的 Pod(如带有
1cluster-autoscaler.kubernetes.io/safe-to-evict: false
注解的 Pod)
- 距离上次缩容已经超过一定时间(默认 10 分钟,通过
1--scale-down-delay-after-add
等参数控制)
缩容判断周期由
1 | --scale-down-unneeded-time |
控制,默认为 10 分钟。这意味着节点需要持续低于利用率阈值 10 分钟以上才会被考虑缩容,这可以避免因流量短暂波动而频繁地添加和删除节点。
关键决策流程
| 阶段 | 动作 | 时间窗口 |
|---|---|---|
| 扫描 | 检查 Pending Pod 和低利用率节点 | 每 10 秒 |
| 扩容决策 | 模拟调度,确定需要的新节点规格和数量 | 实时 |
| 扩缩容冷却 | 扩容后等待节点 Ready | ~3-5 分钟 |
| 缩容评估 | 持续监测节点利用率 | 10 分钟以上 |
| 缩容执行 | 驱赶 Pod 并删除节点 | 视 Pod 迁移时间而定 |
部署与配置实战
接下来我们以 AWS(通过
1 | eksctl |
管理)和阿里云(ACK)两个平台为例,演示如何部署和配置 Cluster Autoscaler。
在 AWS EKS 上部署
在 EKS 上部署 Cluster Autoscaler 最简单的方式是使用官方 Helm Chart:
1
2
3
4
5
6
7
8
9
10
11 # 添加 Helm 仓库
helm repo add autoscaler https://kubernetes.github.io/autoscaler
helm repo update
# 部署 Cluster Autoscaler
helm upgrade --install cluster-autoscaler autoscaler/cluster-autoscaler \
--namespace kube-system \
--set autoDiscovery.clusterName=my-eks-cluster \
--set awsRegion=us-east-1 \
--set rbac.serviceAccount.name=cluster-autoscaler \
--set rbac.serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::123456789:role/cluster-autoscaler-role
注意,这里需要提前创建好 IAM 角色并绑定正确的权限策略。最小权限策略示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeAutoScalingInstances",
"autoscaling:DescribeLaunchConfigurations",
"autoscaling:DescribeTags",
"autoscaling:SetDesiredCapacity",
"autoscaling:TerminateInstanceInAutoScalingGroup"
],
"Resource": "*"
}
]
}

在阿里云 ACK 上部署
阿里云 ACK 的 Cluster Autoscaler 通常以组件形式集成在集群中,也可以通过 Helm 手动部署:
1
2
3
4
5
6
7
8
9 # 创建命名空间
kubectl create namespace kube-system
# 使用阿里云官方 Helm Chart
helm repo add ack-autoscaler https://cs-charts.oss-cn-hangzhou.aliyuncs.com
helm install cluster-autoscaler ack-autoscaler/cluster-autoscaler \
--namespace kube-system \
--set region=cn-hangzhou \
--set clusterId=c82d8c6b8d4c84c63a99f8a1b2c3d4e5f
阿里云版本的 Cluster Autoscaler 与 ACK 的节点池(Node Pool)深度集成,支持按量付费和抢占式实例混合部署。
关键配置参数详解
Cluster Autoscaler 提供了丰富的配置参数,合理设置这些参数是保证集群稳定性的关键。
扩缩容行为控制
| 参数 | 默认值 | 说明 | ||
|---|---|---|---|---|
|
10s | 检查 Pending Pod 和空闲节点的间隔 | ||
|
10m | 新节点加入后等待多久才开始评估缩容 | ||
|
0s | 节点删除后等待多久再次评估 | ||
|
3m | 缩容失败后等待多久重试 | ||
|
10m | 节点持续空闲多久才被标记为可删除 | ||
|
0.5 | 节点利用率低于此值才考虑缩容(0~1) | ||
|
无限制 | 集群最大节点数,防止无限扩容 | ||
|
无限制 | 集群总 CPU 核数上限 | ||
|
无限制 | 集群总内存上限(如 min:50GB,max:200GB) |
生产环境推荐配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 # 合理的生产配置示例
command:
- ./cluster-autoscaler
- --v=4
- --stderrthreshold=info
- --logtostderr=true
- --cloud-provider=aws
- --skip-nodes-with-local-storage=false
- --expander=least-waste
- --balance-similar-node-groups=true
- --scale-down-enabled=true
- --scale-down-delay-after-add=15m
- --scale-down-unneeded-time=15m
- --scale-down-utilization-threshold=0.4
- --max-nodes-total=100
- --cores-total=min:8,max:400
- --memory-total=min:32GB,max:1600GB
这里我们设置了 15 分钟的缩容冷却时间,降低到 40% 的利用率阈值,同时限制了集群最大 100 个节点、400 核 CPU 和 1.6TB 内存,防止因异常流量导致成本失控。
与 HPA 的协同工作
Cluster Autoscaler 和 HPA 是 Kubernetes 弹性伸缩体系中相辅相成的两个组件。理解它们如何协同工作,是设计弹性基础设施的关键。
一个典型的协同流程如下:
- 流量增加 → HPA 检测到 Pod CPU/内存使用率上升
- HPA 扩容 → 增加 Deployment 的 Replicas 数量
- Pod Pending → 新 Pod 因节点资源不足进入 Pending 状态
- CA 扩容 → Cluster Autoscaler 检测到 Pending Pod,申请新节点
- 节点就绪 → 新节点加入集群,Pending Pod 被调度运行
- 流量回落 → HPA 缩减 Pod 副本数
- 节点空闲 → Cluster Autoscaler 检测到低利用率节点并缩容
实际部署中,需要注意 HPA 的扩容策略和 Cluster Autoscaler 的扫描间隔之间的配合。如果 HPA 扩容过快(例如设置了
1 | behavior.scaleUp.stabilizationWindowSeconds |
过短),可能会触发不必要的节点扩容。推荐配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-app-hpa
spec:
maxReplicas: 100
minReplicas: 3
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 100
periodSeconds: 15
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
这个配置让 HPA 扩容相对激进(每 15 秒最多翻倍),但缩容非常保守(稳定窗口 5 分钟,每 60 秒最多缩 10%),避免与 Cluster Autoscaler 产生”振荡效应”。

Pod 级别的缩容保护
不是所有 Pod 都应该被 Cluster Autoscaler 随意驱赶。对于有状态应用或关键服务,我们需要设置缩容保护机制。
使用注解阻止 Pod 被驱逐
1
2
3
4
5
6
7
8
9 apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-cluster
spec:
template:
metadata:
annotations:
cluster-autoscaler.kubernetes.io/safe-to-evict: "false"
设置了
1 | safe-to-evict: false |
后,Cluster Autoscaler 不会驱逐该 Pod,因此包含此 Pod 的节点也不会被缩容。这确保了 Redis 集群这样的有状态服务不会因为节点缩容而丢失数据。
使用 PodDisruptionBudget
更精细的控制方式是使用 PodDisruptionBudget(PDB),它允许你在节点缩容时保证应用的最小可用副本数:
1
2
3
4
5
6
7
8
9 apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-app-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: web-app
Cluster Autoscaler 在缩容时会尊重 PDB 的限制——如果驱逐某个 Pod 会导致可用副本数低于
1 | minAvailable |
,则不会执行驱逐。PDB 比
1 | safe-to-evict |
注解更灵活,推荐作为首选方案。
多实例类型与扩展器策略
在多可用区和多实例类型的场景下,Cluster Autoscaler 需要决定扩容哪种类型的节点。这通过
1 | --expander |
参数控制,支持以下几种策略:
| 策略名 | 行为 | 适用场景 | ||
|---|---|---|---|---|
|
随机选择一个满足条件的节点组 | 测试环境 | ||
|
选择能调度最多 Pod 的节点组 | 批量任务 | ||
|
选择资源浪费最少的节点组 | 成本敏感场景 | ||
|
按优先级列表选择 | 混合实例策略 | ||
|
选择价格最低的节点组 | 成本优先(仅 AWS) |
生产环境推荐组合使用优先级和价格策略。例如优先使用 Spot 实例,如果 Spot 不可用则回退到按量付费实例:
1
2
3
4
5
6
7
8
9
10
11
12 # ConfigMap 定义节点组优先级
apiVersion: v1
kind: ConfigMap
metadata:
name: cluster-autoscaler-priority-expander
namespace: kube-system
data:
priorities: |-
10:
- spot-instances.*
5:
- on-demand-instances.*
成本优化实战
Cluster Autoscaler 在成本优化方面扮演着关键角色。以下是几个经过验证的降本策略:
1. 混合实例类型
在 AWS 上,可以创建包含多种实例类型的节点组,利用 Spot 实例大幅降低成本。配置节点组时指定多个实例类型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 # eksctl 配置示例
nodeGroups:
- name: mixed-instances
minSize: 2
maxSize: 50
instancesDistribution:
instanceTypes:
- m5.large
- m5a.large
- m5n.large
- m6i.large
onDemandBaseCapacity: 2
onDemandPercentageAboveBaseCapacity: 30
spotAllocationStrategy: capacity-optimized
这样配置后,70% 的额外节点使用 Spot 实例,成本可降低 60-70%。
2. 设置合理的上下限
通过
1 | --max-nodes-total |
和各个节点组的
1 | minSize |
/
1 | maxSize |
,设置明确的上限和下限,避免成本失控:
1
2
3
4
5
6
7
8 # 每个节点组设置明确的规模限制
nodeGroups:
- name: cpu-optimized
minSize: 3
maxSize: 20
- name: gpu-optimized
minSize: 0
maxSize: 5
3. 结合节点自动释放策略
对于非关键工作负载,可以设置较短的缩容等待时间,更快释放闲置资源。但对于关键业务,建议延长缩容等待时间以避免抖动。
故障排查与监控
Cluster Autoscaler 在生产环境中运行时,可能会遇到各种问题。以下是常见的排查方法。
查看日志
1
2
3
4
5 # 查看 Cluster Autoscaler Pod 日志
kubectl -n kube-system logs -l app.kubernetes.io/name=cluster-autoscaler --tail=100
# 查看扩容决策日志(需要设置 --v=4 以上)
kubectl -n kube-system logs -l app.kubernetes.io/name=cluster-autoscaler | grep "Expanding Node Group"
检查 Pending Pod 的原因
1
2
3
4
5 # 查看 Pending Pod 的详细状态
kubectl get pods --all-namespaces --field-selector=status.phase=Pending
# 查看调度失败原因
kubectl describe pod <pending-pod-name> | grep -A 20 Events
监控指标
Cluster Autoscaler 暴露了 Prometheus 指标,可以通过以下关键指标监控其运行状态:
-
1cluster_autoscaler_unschedulable_pods_count
— 不可调度 Pod 数量
-
1cluster_autoscaler_nodes_count
— 集群节点总数
-
1cluster_autoscaler_scale_up_in_progress
— 是否正在扩容
-
1cluster_autoscaler_scaled_up_nodes_total
— 累计扩容节点数
-
1cluster_autoscaler_scaled_down_nodes_total
— 累计缩容节点数
-
1cluster_autoscaler_failed_scale_ups_total
— 扩容失败次数
通过 Grafana 仪表盘可视化这些指标,可以直观地了解集群的扩缩容行为和成本变化趋势。
常见问题与最佳实践
扩容太慢怎么办?
默认情况下,从触发扩容到新节点 Ready 通常需要 3-5 分钟。如果业务对扩容速度要求更高,可以考虑:
- 使用 Prewarming / Overprovisioning 策略:维持少量”占位 Pod”(使用低优先级的 Pause 容器),让 Cluster Autoscaler 提前准备好缓冲节点
- 设置更短的
1--scan-interval
(如 5 秒)
- 使用云服务商的”缓冲区”功能(如 AWS 的 Buffer 实例)
Overprovisioning 的典型配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 apiVersion: apps/v1
kind: Deployment
metadata:
name: overprovisioning
namespace: kube-system
spec:
replicas: 2
selector:
matchLabels:
app: overprovisioning
template:
metadata:
labels:
app: overprovisioning
spec:
priorityClassName: overprovisioning-low
containers:
- name: pause
image: registry.k8s.io/pause:3.9
resources:
requests:
cpu: 500m
memory: 512Mi
缩容太慢怎么办?
- 缩短
1--scale-down-unneeded-time
(如降低到 5 分钟)
- 降低
1--scale-down-utilization-threshold
(如 0.3)
- 排除不需要缩容保护的命名空间
节点一直处于缩容评估中但不执行?
常见的阻塞原因包括:
- 节点上有带
1safe-to-evict: false
的 Pod
- 节点上有 Kube 系统 Pod(默认不会被驱逐)
- PDB 阻止了 Pod 驱逐
- 节点上的 Pod 分散度不够,无法合并到其他节点
使用以下命令可以查看具体阻塞原因:
1
2 # 查看 Cluster Autoscaler 对每个节点的评估状态
kubectl -n kube-system logs -l app.kubernetes.io/name=cluster-autoscaler | grep "scale-down"
总结
Cluster Autoscaler 是 Kubernetes 弹性架构中不可或缺的组件,它与 HPA 配合使用,实现了从 Pod 到节点的全栈弹性伸缩。合理配置 Cluster Autoscaler 不仅能保证业务的稳定性,还能显著降低云资源成本。
关键要点回顾:
- 扩容由 Pending Pod 触发,通常在 3-5 分钟内完成节点就绪
- 缩容需要节点持续低利用率 10 分钟以上,受到 PDB 和注解的保护约束
- 成本控制通过设置节点组上下限、混合实例类型、合理的扩展器策略来实现
- 监控告警基于 Prometheus 指标,及时发现扩缩容异常
- Overprovisioning 可以应对突发流量的扩容延迟问题
在实际生产环境中,建议先在测试集群中充分验证 Cluster Autoscaler 的配置参数,观察其对业务的影响,再逐步推广到生产集群。记住,弹性伸缩的设计目标是”够用就好”——过度配置会导致成本浪费,配置不足则影响业务可用性。
汤不热吧