4. AWS Batch 环境搭建:计算环境与作业队列

好,咱们直接进入正题。这一章要搞定的,是 AWS Batch 里最核心的两个组件——计算环境和作业队列。说白了,计算环境就是你的算力池,作业队列就是任务调度器。两个搭对了,你的 Batch 工作流才能跑得稳。

⚠️ 注意:创建顺序有讲究。必须先建计算环境,再建作业队列。反过来会报错,我在项目里试过,白费半天时间。
AWS Batch 核心组件关系图 用户作业提交 作业队列 (Job Queue) 计算环境(Compute Environment) 管理型 EC2 / Fargate / Spot 最小vCPU / 最大vCPU / 实例类型 计算环境(Compute Environment) 管理型 EC2 / Fargate / Spot 最小vCPU / 最大vCPU / 实例类型 后端 ECS 集群(自动管理) 每个作业队列必须关联至少一个计算环境,计算环境自动创建 ECS 集群

4.1 计算环境:你的算力池

计算环境(Compute Environment)是 AWS Batch 的核心资源池。它决定了用什么样的机器、多大算力、按需还是竞价。我最初踩过坑——随便选几个参数就创建,结果跑的作业要么资源不够,要么浪费钱。

4.1.1 类型选择:托管型 vs 非托管型

类型说明适用场景
托管型(Managed)AWS 自动管理 EC2 实例的扩缩容绝大多数场景,推荐
非托管型(Unmanaged)你自行管理底层实例特殊定制需求,极少用

我一般直接用托管型。省心,AWS 会根据作业压力自动扩缩,半夜不跑作业时自动缩减到最小,帮你省钱。非托管型……说实话,除非你有非常特殊的网络或安全要求,否则别碰。

4.1.2 实例类型与分配策略

嗯,这里要注意。AWS Batch 允许你指定一组实例类型,而不是单一类型。比如可以混用 c5、m5、r5 系列。我个人习惯把计算密集型(c系)和通用型(m系)放在一起,让 Batch 根据作业需求自动选。

分配策略也很关键。主要有两种:

  • BEST_FIT:从当前可用实例里选最合适的。如果你的实例池里已经有空余的 c5.large,它会优先重用,而不是新开一台。适合稳定负载。
  • BEST_FIT_PROGRESSIVE:逐步尝试更优实例。它会先尝试最小的,如果不够再升。适合混合负载,但扩缩慢一点。
💡 技巧:我跑过的一个项目需要同时处理 CPU 密集和内存密集任务,我用了 BEST_FIT_PROGRESSIVE + 指定了 c5、r5 两个家族。Batch 会自动给 CPU 任务分配 c5,给内存任务分配 r5,很智能。

4.1.3 vCPU 上下限设置

这是最容易踩坑的地方。Min vCPU 和 Max vCPU 必须合理。曾经我有个项目,Min 设了 0,Max 设了 256,结果小规模测试时 Batch 只启动一个实例,作业排队等了好久。后来我调高 Min 到 4,确保至少有几台机器待命。

参数建议值踩坑经验
Min vCPU0(节省)或 4(常驻)设为 0 时第一次作业启动慢,但省钱
Max vCPU根据作业峰值估算设太小作业排队,设太大浪费钱
Desired vCPU可选,一般留空手动设置后 Batch 会强制保持该数量

4.1.4 使用 Spot 实例节省成本

如果你能接受作业被中断(比如支持 checkpoint 的深度学习训练),强烈建议用 Spot 实例。AWS Batch 原生支持「使用 Spot 实例的托管计算环境」。我算过一笔账:同样跑 1000 个作业,用 Spot 可以省 60%-80%。

⚠️ 重要:Spot 实例可能被回收。你的作业必须能处理中断,否则白跑。建议给每个作业加 checkpoint 机制,或把中间结果存到 S3。

创建 Spot 计算环境时,需要指定一个 Spot 占比。比如 100% 表示全部用 Spot。我个人习惯设 100%,但如果任务必须保证完成,可以混用一些 On-Demand。

# 创建托管计算环境(使用 AWS CLI)
aws batch create-compute-environment \
    --compute-environment-name my-spot-env \
    --type MANAGED \
    --state ENABLED \
    --compute-resources type=SPOT,minvCpus=0,maxvCpus=256,desiredvCpus=0,instanceTypes=c5.large,c5.xlarge,c5.2xlarge,subnets=subnet-xxx,securityGroupIds=sg-xxx,spotIamFleetRole=arn:aws:iam::xxx:role/spot-fleet-role,ec2KeyPair=my-key

4.2 作业队列:任务调度中枢

作业队列(Job Queue)把作业分发给计算环境。你可以建立多个队列,每个队列绑定不同的计算环境,实现优先级或资源隔离。

4.2.1 队列与计算环境的关联

一个作业队列可以关联 1 到多个计算环境。我通常会配两个:一个用 Spot 省钱(优先级低),一个用 On-Demand 保底(优先级高)。作业提交时如果 Spot 环境有空闲,就走 Spot;否则自动 fallback 到 On-Demand。

# 创建作业队列,关联两个计算环境
aws batch create-job-queue \
    --job-queue-name my-mixed-queue \
    --state ENABLED \
    --priority 1 \
    --compute-environment-order order=1,computeEnvironment=my-spot-env \
    --compute-environment-order order=2,computeEnvironment=my-ondemand-env

注意顺序:order 序号小的优先级高。我把 Spot 放在 order=1,表示优先用 Spot 省钱。On-Demand 作为备份只当 Spot 满了才用。

4.2.2 优先级设置

每个作业队列有一个优先级(1-1000,数字越大优先级越高)。不同队列之间按优先级调度。比如你可以建一个 high-priority 队列(priority=100)专门跑线上业务,一个 batch-queue(priority=50)跑离线数据分析。

我见过有人把两个队列的优先级设得一样,结果两个队列的作业混在一起,谁也抢不到资源。所以优先级最好有明显梯度,比如 100、50、10。

4.2.3 状态管理

队列可以随时启用/禁用。禁用后,已在队列中的作业会继续等待,但不再接收新作业。如果你要维护底层计算环境,可以先禁用队列,等维护完再启用。

📌 最佳实践:在 CI/CD 流程中,每次部署作业逻辑前,先禁用队列,确认所有运行中的作业结束后再更新。我曾经因为没停队列就更新了计算环境配置,导致部分作业失败。

4.3 避坑指南:创建过程的典型陷阱

  • IAM 角色权限不足:创建计算环境时,Batch 服务角色需要 ec2:DescribeInstances、ecs:CreateCluster 等权限。少一个就报错。建议直接用 AWS 托管的 AWSBatchServiceRole,省事。
  • 子网和安全组不匹配:选 VPC、子网时,确保子网能访问 ECR(如果拉取镜像)和 S3(如果读写数据)。没有 NAT Gateway 的私有子网会导致作业卡死。
  • Spot 实例的 IAM Fleet Role:使用 Spot 实例必须指定 spotIamFleetRole,否则创建计算环境直接失败。这个角色需要用 AmazonEC2SpotFleetTaggingRole 策略。
  • 实例类型不兼容:某些实例类型(比如 p3.2xlarge)需要 EFA 或特殊驱动,Batch 不一定自动配置。建议先在 EC2 测试跑通,再用到 Batch 里。

4.4 快速上手指南:三步搞定

  1. 创建计算环境:选托管型 + Spot 实例 + 合理 vCPU 范围 + 合适的实例家族。
  2. 创建作业队列:关联上述计算环境,设置 priority=1。
  3. 提交测试作业:用一个简单的 echo 或 sleep 作业验证队列通不通。

你可以在 AWS 控制台或 CLI 里执行。我习惯先把配置写成 JSON 文件,方便版本管理:

{
  "computeEnvironmentName": "my-test-env",
  "type": "MANAGED",
  "state": "ENABLED",
  "computeResources": {
    "type": "SPOT",
    "minvCpus": 0,
    "maxvCpus": 64,
    "instanceTypes": ["c5.large", "c5.xlarge"],
    "subnets": ["subnet-12345678"],
    "securityGroupIds": ["sg-12345678"],
    "spotIamFleetRole": "arn:aws:iam::123456789012:role/spot-fleet-role",
    "ec2KeyPair": "my-key"
  },
  "serviceRole": "arn:aws:iam::123456789012:role/AWSBatchServiceRole"
}

用命令行创建:

aws batch create-compute-environment --cli-input-json file://my-env.json

然后创建队列:

aws batch create-job-queue --job-queue-name my-test-queue --state ENABLED --priority 10 --compute-environment-order order=1,computeEnvironment=my-test-env
💡 快速验证:创建完建议用 aws batch describe-compute-environments 查看状态,VALID 表示正常。如果显示 INVALID,看 describe 输出的 reason 字段,通常能定位问题。

好了,这一章的核心就是计算环境和作业队列的搭配。记得多测试几次,特别是 Spot 中断场景。下一环节我们实际提交一个作业跑起来看看。