我正在尝试使用 CloudFormation 复制单个容器的极其基本的手动配置的 AWS ECS Fargate 部署。看来我快到了;生成的堆栈会旋转一个我可以访问的容器。但没有日志。
我比较了我的手动任务(通过 UI 创建)和 CloudFormation 任务,并向容器定义添加了相同的日志配置,但只是将日志组从
/ecs/foo
更改为 /ecs/bar
:
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-create-group: true
awslogs-group: '/ecs/bar'
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: 'ecs'
但是现在任务无法启动容器。它给出这样的错误:
Resourceinitializationerror: failed to validate logger args: create stream has been retried 1 times: failed to create Cloudwatch log group: AccessDeniedException: User: arn:aws:sts::…:assumed-role/ecsTaskExecutionRole/… is not authorized to perform: logs:CreateLogGroup on resource: arn:aws:logs:us-east-1:…:log-group:/ecs/bar:log-stream: because no identity-based policy allows the logs:CreateLogGroup action status code: 400, request id: … : exit status 1
一个文档页面提到了这个
logs:CreateLogGroup
许可,并说:
要使用
选项,请将awslogs-create-group
添加为内联 IAM 策略。logs:CreateLogGroup
但我不明白的是我的 CloudFormation 模板与通过 UI 手动创建的堆栈有何不同。通过查看为手动创建的堆栈生成的模板,两个任务定义似乎都指示
ecsTaskExecutionRole
。我的 CloudFormation 模板任务定义如下:
ExecutionRoleArn: 'arn:aws:iam::…:role/ecsTaskExecutionRole'
手动创建的堆栈如何能够创建日志组,但我的独立的从头开始的 CloudFormation 模板却不能?我应该在哪里注明
logs:CreateLogGroup
权限?手动创建的堆栈似乎没有指示任何内联策略。 (诚然,由于某种原因,手动创建的任务定义似乎没有使用 CloudFormation 堆栈,所以它可能有一些我在 UI 中没有看到的隐藏设置。)
如果我希望任务使用
awslogs-create-group
自动动态创建日志组,则正确的方法似乎是拥有包含 logs:CreateLogGroup
权限的 IAM 策略,如使用 awslogs 日志驱动程序中所述。 (我仍然不明白如何在 UI 中手动创建任务定义导致创建日志组。)与 ECS 资源初始化错误 相关的另一个页面表示我需要“添加 logs:CreateLogGroup
作为内联 IAM 策略” ,但没有人能够提供如何在 CloudFormation 中执行此操作的示例。我确信我能弄清楚……
但是,在我看来,最好的做法是在 CloudFormation 模板本身中声明和配置
AWS::Logs::LogGroup
资源,而不是让服务动态创建日志组。 (感谢 AWS CloudFormation - 初学者到高级(实践指南) Udemy 课程启发了这种方法。)因此,我会在 CloudFormation 中声明这样的日志组:
BarLogGroup:
Type: AWS::Logs::LogGroup
DeletionPolicy: Retain
Properties:
LogGroupName: '/ecs/bar'
然后为了避免重复,在日志配置中引用日志组:
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref BarLogGroup
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: 'ecs'
这完全解决了运行时权限和动态创建的问题。日志组也是一种资源,由于任务依赖于它,我们不妨与其他资源一起以声明方式描述它。这种方式日志组的创建取决于创建堆栈的角色的权限,而不是任务本身,这似乎更合适。
(我添加了删除策略,假设您希望保留日志,即使您删除/重新创建堆栈也是如此。)
进行上述更改后,我的 CloudFormation EC Fargate 堆栈现在可以像手动创建的堆栈一样运行并生成日志,因此这种方法是成功的。
正如您所注意到的,如果您想使用 awslogs-create-group,则 messages:CreateLogGroup 需要位于 AWS::Batch::JobDefinition 的 ExecutionRoleArn 属性中引用的角色上。如果您添加以下内容,这应该会起作用:
ManagedPolicyArns:
- arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
那个角色。
但不建议这样做。这就是我的模板中的内容:
logGroup:
Type: 'AWS::Logs::LogGroup'
Properties:
RetentionInDays: 14
LogGroupName: my-project
job:
Type: AWS::Batch::JobDefinition
Properties:
JobDefinitionName: myjob
ContainerProperties:
Image: !Sub '${ECRRepo}/${Image}'
ExecutionRoleArn: !GetAtt execRole.Arn
JobRoleArn: !GetAtt jobRole.Arn
ResourceRequirements:
- Value: 8192
Type: MEMORY
- Value: 1
Type: VCPU
Command:
- echo
- hello
- world
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-datetime-format: '%Y-%m-%dT%H:%M:%S.%f%z'
awslogs-region: !Sub '${AWS::Region}'
awslogs-group: !Ref logGroup
EphemeralStorage:
SizeInGiB: 100
PlatformCapabilities:
- FARGATE
Type: container
execRole:
Type: AWS::IAM::Role
Properties:
RoleName: myexecrole
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
- arn:aws:iam::aws:policy/.AmazonEC2ContainerRegistryReadOnly
但是我遇到了下一个类似的错误。该作业无法创建日志流。这让我困惑了好几个小时。因此 exec 角色用于创建作业,并且需要能够访问镜像存储库,或许还可以创建日志组。作业在 JobRoleArn 中指定的角色下运行。这终于对我有用了:
jobRole:
Type: AWS::IAM::Role
Properties:
RoleName: myjobrole
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: MyS3AndLoggingPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:ListBucket
- s3:DeleteObject
Resource:
- !Sub 'arn:${AWS::Partition}:s3:::${bucketName}'
- !Sub 'arn:${AWS::Partition}:s3:::${bucketName}/*'
- Effect: Allow
Action:
- logs:PutLogEvents
- logs:CreateLogStream
Resource: !Sub 'arn:${AWS::Partition}:logs:*:*:log-group:${logGroup}:log-stream:*'
我希望这对某人有帮助。