Contents
概述:AI弹性计算的需求与挑战
AI工作负载,尤其是大规模模型训练和批处理推理,具有显著的突发性和可变性。在这些场景中,预先静态分配大量的GPU资源会导致极高的成本浪费。因此,设计一个能够根据待处理任务(Pending Pods)动态伸缩GPU节点池的弹性调度策略至关重要。
我们将聚焦于如何利用Kubernetes的核心组件——Cluster Autoscaler (CA),结合云服务商的自动伸缩组,实现对GPU资源的按需供给(Scale Up)和节约回收(Scale Down)。
弹性调度的核心组件
要实现GPU集群的弹性调度,我们需要关注以下三个关键点:
- 资源感知(Resource Awareness):Pod必须明确请求GPU资源 (
1nvidia.com/gpu
)。
- 节点伸缩器(Cluster Autoscaler, CA):负责监控集群中处于Pending状态,且等待特定资源(如GPU)的Pod,并根据需要启动新的节点。
- 调度优先级(Priority & Preemption):确保高优先级的训练任务可以抢占低优先级的推理或开发任务,保证核心业务的资源供给。
第一步:配置GPU资源感知和节点组
Cluster Autoscaler需要知道如何从哪个节点池中获取GPU资源。在配置CA时,你需要指定包含GPU节点的Auto Scaling Group (ASG) 或 Managed Instance Group (MIG)。
示例:CA的配置参数(AWS EKS为例)
CA通过分析Pending Pods的
1 | nodeSelector |
、
1 | tolerations |
和资源请求来决定是否需要伸缩。关键在于为GPU节点组设置特定的标签。
1
2
3
4
5
6
7
8
9
10
11
12
13
14 # Cluster Autoscaler Deployment 配置片段
containers:
- name: cluster-autoscaler
image: k8s.gcr.io/cluster-autoscaler:v1.24.0
args:
- --cloud-provider=aws
- --nodes=1:10:arn:aws:autoscaling:region:account:autoScalingGroup/cpu-node-group
# 关键:定义GPU节点池,注意Min/Max限制
- --nodes=0:5:arn:aws:autoscaling:region:account:autoScalingGroup/gpu-training-group
- --kubeconfig=/etc/kubernetes/kubeconfig
# 确保CA识别GPU资源类型
- --expander=most-pods
- --gpu-total-count=nvidia.com/gpu:0-50 # 定义整个集群可以拥有的GPU总数范围
- --skip-nodes-with-system-pods=false
GPU节点标签和污点设置
为了让Pod能够精确调度到GPU节点,GPU节点组应设置唯一的标签和污点。
1
2
3
4
5
6
7 # 节点标签示例
apiVersion: v1
kind: Node
metadata:
labels:
infra-type: gpu
gpu.vendor: nvidia
第二步:定义触发伸缩的弹性AI任务
当AI训练任务提交时,它会请求特定的GPU资源,并使用节点选择器指向GPU节点组。如果当前集群中没有足够的GPU节点,这些Pod将进入Pending状态,从而触发CA。
示例:带有GPU请求的K8s Job
这个Job请求两个NVIDIA GPU,并要求调度到具有
1 | infra-type: gpu |
标签的节点上。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 apiVersion: batch/v1
kind: Job
metadata:
name: elastic-gpu-training
spec:
template:
spec:
nodeSelector:
infra-type: gpu # 确保只调度到GPU节点
containers:
- name: trainer
image: myregistry/tensorflow-trainer:latest
resources:
limits:
nvidia.com/gpu: "2" # 关键:请求2个GPU
requests:
nvidia.com/gpu: "2"
restartPolicy: OnFailure
工作流程:
- 用户提交
1elastic-gpu-training
Job。
- Kube Scheduler 发现需要2个GPU,且需要匹配
1infra-type: gpu
标签的节点。
- 如果没有足够的可用资源,Pod进入 Pending 状态。
- Cluster Autoscaler 检测到 Pending Pod,发现如果启动一个新节点(假设该节点提供4个GPU),该 Pod 就能被满足。
- CA 调用云 API 启动一个新的GPU节点(Scale Up)。
- 新节点加入集群,Kube Scheduler 将 Pod 调度到新节点上,任务开始执行。
第三步:实现弹性回收策略(Scale Down)
弹性计算的关键在于节约。当任务完成后,GPU节点必须被及时回收。
Cluster Autoscaler 在默认情况下通过以下机制实现回收:
- 空闲时间阈值(
1--scale-down-unneeded-time
)
:如果一个节点在指定时间内(默认为10分钟)处于未被任何Pod请求资源的状态,则视为可以被回收。 - 排水机制(Draining):在回收节点前,CA会尝试将节点上的所有非系统Pod迁移到其他节点上(如果存在)。
对于AI训练节点,通常配置较短的空闲时间,以确保高昂的GPU资源能够尽快释放。
1
2
3 # CA Scale Down 优化参数示例
--scale-down-unneeded-time=5m # 节点空闲5分钟即可尝试回收
--scale-down-utilization-threshold=0.5 # 节点资源利用率低于50%时考虑回收
结合优先级抢占(Priority/Preemption)
为了防止低优先级任务占用资源,阻碍回收,建议为AI工作负载设置K8s优先级类别(PriorityClass)。
1
2
3
4
5
6
7
8 # 定义高优先级类别
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority-training
value: 1000000
globalDefault: false
description: "For critical AI training jobs."
将此PriorityClass应用于训练Job,确保训练Pod即使在资源紧张时也能通过抢占机制获得GPU,或优先触发CA进行伸缩,从而保证核心业务的弹性需求。
汤不热吧