如何为AWS Batch Fargate作业授予S3与DynamoDB访问权限?
问题分析与解决方案
错误原因
你遇到的Unable to get IAM security credentials from EC2 Instance Metadata Service错误,核心问题是混淆了AWS Batch Fargate作业的两种IAM角色:执行角色(executionRole)和任务角色(jobRole),且未正确为容器应用配置任务角色:
- executionRole:仅负责任务执行层面的操作,比如拉取ECR镜像、写入CloudWatch日志,不需要S3/DynamoDB权限。
- jobRole:才是容器内应用代码用来访问AWS服务(S3、DynamoDB)的角色,应用通过任务角色获取凭证,而非EC2元数据服务。
你的代码把两种角色的职责混在一起,只指定了executionRole,却未配置jobRole,导致应用无法获取合法访问凭证。
修正步骤与代码
1. 拆分执行角色与任务角色
分别创建executionRole和jobRole,明确各自权限范围:
- executionRole:保留ECR和日志相关权限
- jobRole:分配S3和DynamoDB的访问权限
2. 在JobDefinition中同时配置两个角色
在容器配置里分别指定executionRole和jobRole属性,让Fargate正确加载对应角色的凭证。
修正后的完整代码
import { ComputeEnvironment, ComputeResourceType, JobDefinition, JobQueue, PlatformCapabilities } from "@aws-cdk/aws-batch-alpha"; import { Duration, Stack, StackProps } from "aws-cdk-lib"; import { ITable } from "aws-cdk-lib/aws-dynamodb"; import { IVpc } from "aws-cdk-lib/aws-ec2"; import { ContainerImage } from "aws-cdk-lib/aws-ecs"; import { PolicyDocument, PolicyStatement, Role, ServicePrincipal } from "aws-cdk-lib/aws-iam"; import { IBucket } from "aws-cdk-lib/aws-s3"; import { Construct } from "constructs"; import { stage } from ".."; export interface CapsJobStackProps extends StackProps { mainBucket: IBucket; capsTable: ITable; vpc: IVpc } export class CapsJobStack extends Stack { constructor(scope: Construct, id: string, private props: CapsJobStackProps) { super(scope, id, props); const computeEnvironment = new ComputeEnvironment(this, 'CapsComputeEnvironment', { computeResources: { type: ComputeResourceType.FARGATE, vpc: props.vpc, maxvCpus: 2 }, }); const jobQueue = new JobQueue(this, 'CapsJobQueue', { computeEnvironments: [{computeEnvironment, order: 1}] }); // 执行角色:负责镜像拉取、日志写入等任务执行操作 const executionRole = new Role(this, 'CapsExecutionRole', { assumedBy: new ServicePrincipal("ecs-tasks.amazonaws.com"), inlinePolicies: { EcsExecution: new PolicyDocument({ statements: [ new PolicyStatement({ actions: ["ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage", "logs:CreateLogStream", "logs:PutLogEvents" ], resources: ["*"] }) ] }) } }); // 任务角色:容器应用用来访问S3和DynamoDB的角色 const jobRole = new Role(this, 'CapsJobRole', { assumedBy: new ServicePrincipal("ecs-tasks.amazonaws.com"), }); props.capsTable.grantReadWriteData(jobRole); props.mainBucket.grantReadWrite(jobRole); const jobDefinition = new JobDefinition(this, 'CapsJob', { container: { image: ContainerImage.fromAsset('../src/Caps.Uploader', { file: 'DockerfileCdk' }), environment: { "OD_ENVIRONMENT": stage, "OD_BUCKET": props.mainBucket.bucketName, "OD_CAPSTABLE": props.capsTable.tableName }, executionRole: executionRole, // 指定执行角色 jobRole: jobRole, // 指定任务角色(关键!之前遗漏了这一步) vcpus: 0.25, memoryLimitMiB: 512 }, timeout: Duration.days(1), retryAttempts: 3, platformCapabilities: [PlatformCapabilities.FARGATE] }); } }
关键改动说明
- 拆分
executionRole和jobRole,明确各自职责边界 - 在
JobDefinition的容器配置中新增jobRole属性,修正了之前角色混用的问题 - 任务角色仅保留S3和DynamoDB的权限,执行角色专注于镜像拉取和日志相关操作
这样配置后,容器内的应用就能通过任务角色获取合法IAM凭证,正常访问S3和DynamoDB,同时避免元数据服务相关错误。
内容的提问来源于stack exchange,提问作者Jesús López
相关产品推荐
相关产品推荐

