使用 CPA + CA 预热扩容 Node
概述
在 Kubernetes 集群中,业务 Pod 扩容时如果资源不足,Cluster Autoscaler (CA) 会扩容节点,但通常需要 2-5 分钟,导致业务 Pod 长时间 Pending。
本文介绍通过 Cluster Proportional Autoscaler (CPA) 管理低优先级占位 Pod,提前触发 CA 扩容,业务 Pod 获得秒级响应(5-10 秒),响应速度提升 24-60 倍。这种思路和这种思路和阿里云基于ack-autoscaling-placeholder实现容器秒级伸缩 是类似的
工作原理
核心流程:
- CPA 根据节点数量自动管理占位 Pod(运行 pause 容器,最低优先级)
- 业务 Pod 扩容时立即抢占占位 Pod 资源
- 占位 Pod 进入 Pending 状态,触发 CA 扩容节点
- 新节点就绪后,占位 Pod 重新调度,恢复资源缓冲池
优势:
- 部 分业务 Pod 立即获得资源(5-10 秒 vs 2-5 分钟)
- 保持集群始终有一定比例的资源缓冲
- pause 容器实际消耗极少(~1MB 内存,~0.001 核 CPU)
适用场景:
- 在线业务(Web、API)对响应时间敏感
- 突发流量场景(秒杀、营销活动)
- 资源规格统一的业务
- 可承受 10-30% 资源预留成本
容量规划
以 16C32G 节点、4C8G 业务 Pod 为例:
节点规格:16C/32G
系统组件占用:~4C/8G(kubelet、kube-proxy、监控等)
可用资源:12C/24G
可运行业务 Pod(4C/8G):3 个
缓冲策略选择:
| 策略 | nodesPerReplica | 每节点占位 Pod | 资源缓冲 | 适用场景 |
|---|---|---|---|---|
| 保守 | 3 | 0.33 个 | 10-13% | 成本优先 |
| 推荐 | 2 | 0.5 个 | 17-20% | 平衡成本与性能 |
| 水位线 | 0.667 | 1.5 个 | 30-37% | 保证资源水位线 |
| 激进 | 1 | 1 个 | 33% | 极致响应速度 |
计算 nodesPerReplica
方法 1:基于目标缓冲比例
每个节点可运行业务 Pod 数:3 个
目标缓冲比例:20%
每个节点占位 Pod 数 = 3 × 20% = 0.6 个
nodesPerReplica = 1 / 0.6 = 1.67 ≈ 2
方法 2:基于资源水位线(更精确)
目标保留 30% 资源水位线:
步骤 1:每节点需保留 = 16C × 30% = 4.8C
步骤 2:每节点占位 Pod 数 = 4.8C / 4C = 1.2 个
步骤 3:向上调整为 1.5 个(更保守)
步骤 4:nodesPerReplica = 1 / 1.5 = 0.667
不同水位线配置对照:
| 目标水位线 | 每节点保留 | 占位 Pod 数 (4C) | nodesPerReplica | 实际缓冲 |
|---|---|---|---|---|
| 20% | 3.2C | 1 个 | 1.0 | ~25% |
| 30% | 4.8C | 1.5 个 | 0.667 | ~37% |
| 40% | 6.4C | 2 个 | 0.5 | ~50% |
注意:实际缓冲比例因 ceil() 向上取整会略高于目标值。
完整部署方案
步骤 1:创建 PriorityClass
# placeholder-priority.yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: placeholder-priority
value: -10 # 负数表示最低优先级
globalDefault: false
description: "Priority class for placeholder pods"
步骤 2:创建占位 Pod Deployment
# placeholder-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: placeholder-pods
namespace: default
spec:
replicas: 1 # CPA 会自动调整
selector:
matchLabels:
app: placeholder
template:
metadata:
labels:
app: placeholder
spec:
priorityClassName: placeholder-priority
containers:
- name: pause
image: registry.k8s.io/pause:3.9
resources:
requests:
cpu: "4000m"
memory: "8Gi"
limits:
cpu: "4000m"
memory: "8Gi"
# 反亲和性:分散到不同节点
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: placeholder
topologyKey: kubernetes.io/hostname
步骤 3:部署 CPA
推荐策略配置(20% 缓冲):
# placeholder-autoscaler-values.yaml
config:
linear:
nodesPerReplica: 2
min: 2
max: 50
preventSinglePointFailure: false
includeUnschedulableNodes: false
options:
namespace: default
target: "deployment/placeholder-pods"
pollPeriodSeconds: 30
水位线策略配置(30% 缓冲):
config:
linear:
nodesPerReplica: 0.667
min: 2
max: 100
CPA 配置语法说明:
上面的 placeholder-autoscaler-values.yaml 是 Helm Chart 的 values 写法。安装后 Chart 会把 config.linear 转换成 CPA
读取的 ConfigMap,options 会转换成 CPA 容器启动参数。
config:
linear:
nodesPerReplica: 2
min: 2
max: 50
preventSinglePointFailure: false
includeUnschedulableNodes: false
options:
namespace: default
target: "deployment/placeholder-pods"
pollPeriodSeconds: 30
字段含义:
| 字段 | 说明 |
|---|---|
config.linear | 使用线性模式。CPA 还支持 ladder 阶梯模式,但占位 Pod 预热扩容通常使用 linear。 |
nodesPerReplica | 每多少个节点创建 1 个目标副本,支持小数。例如 2 表示每 2 个节点 1 个占位 Pod。 |
coresPerReplica | 每多少个 CPU Core 创建 1 个目标副本,支持小数。可与 nodesPerReplica 二选一或同时配置。 |
min | 副本数下限。用于保证小集群也有最少占位 Pod。 |
max | 副本数上限。用于控制成本,避免大集群中占位 Pod 过多。 |
preventSinglePointFailure | 为 true 且集群节点数大于 1 时,CPA 至少保留 2 个副本。占位 Pod 场景通常由 min 控制即可。 |
includeUnschedulableNodes | 是否把不可调度节点也计入计算。为 false 时会排除 cordon/drain 中的节点,通常更符合资源缓冲语义。 |
options.namespace | 被扩缩容对象所在命名空间。 |
options.target | 被 CPA 调整副本数的目标对象,格式如 deployment/placeholder-pods。 |
options.pollPeriodSeconds | CPA 轮询集群规模并更新副本数的周期。 |
线性模式的核心计算逻辑:
replicas = max(
ceil(cores / coresPerReplica),
ceil(nodes / nodesPerReplica)
)
replicas = min(replicas, max)
replicas = max(replicas, min)
如果只配置 nodesPerReplica,就只按节点数计算;如果同时配置 coresPerReplica 和 nodesPerReplica,CPA 会取两者计算结果中更大的值。
例如 10 个可调度节点、nodesPerReplica: 2 时,目标副本数为 ceil(10 / 2) = 5;如果
nodesPerReplica: 0.667,目标副本数约为 ceil(10 / 0.667) = 15。最后再应用 min 和 max 边界。
安装:
# 添加 Helm 仓库
helm repo add cluster-proportional-autoscaler \
https://kubernetes-sigs.github.io/cluster-proportional-autoscaler
helm repo update
# 安装
helm install placeholder-autoscaler \
cluster-proportional-autoscaler/cluster-proportional-autoscaler \
-f placeholder-autoscaler-values.yaml \
--namespace default
步骤 4:配置业务 Pod 优先级
确保业务 Pod 优先级高于占位 Pod:
spec:
priorityClassName: system-cluster-critical # 或 high-priority
containers:
- name: app
resources:
requests:
cpu: "4000m"
memory: "8Gi"
效果验证
# 查看占位 Pod 分布
kubectl get pods -l app=placeholder -o wide
# 模拟业务 Pod 扩容
kubectl scale deployment business-app --replicas=15
# 观察占位 Pod 被抢占
kubectl get pods -l app=placeholder -w
# 观察业务 Pod 快速获得资源
kubectl get pods -l app=business -w
# 观察 CA 扩容节点
kubectl get nodes -w