Reputation: 731
I used the following script (anonymised) to create a scheduled Fargate task (and the other needed components):
Transform: AWS::Serverless-2016-10-31
AWSTemplateFormatVersion: "2010-09-09"
Description: Anonymized Description
Parameters:
StackName:
Description: Stack Name
Type: String
ImageTag:
Description: Tag name for image
Type: String
Default: latest
Subnet1:
Description: Subnet 1
Type: String
Subnet2:
Description: Subnet 2
Type: String
VersionId:
Type: String
Description: "The version identifier for this deployment"
Globals:
Function:
Timeout: 3
MemorySize: 128
Resources:
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Anonymized Application
GroupName: anonymized-app
SecurityGroupEgress:
- CidrIp: "0.0.0.0/0"
FromPort: -1
IpProtocol: -1
ToPort: -1
Tags:
- Key: "stack"
Value: !Ref StackName
VpcId: vpc-xxxxxxxxxxxxxxxxx
Repository:
Type: AWS::ECR::Repository
Properties:
RepositoryName: !Ref StackName
Tags:
- Key: "stack"
Value: !Ref StackName
Cluster:
Type: AWS::ECS::Cluster
Properties:
CapacityProviders:
- FARGATE
Tags:
- Key: "stack"
Value: !Ref StackName
CronRule:
Type: AWS::Events::Rule
Properties:
Description: Daily run of the task
EventPattern:
source:
- aws.ec2
detail:
state:
- stopping
ScheduleExpression: "cron(0 7 * * ? *)"
State: ENABLED
Targets:
- Arn: !GetAtt
- Cluster
- Arn
RoleArn: !GetAtt
- ECSTaskRole
- Arn
Id: 'TargetFunctionV1'
EcsParameters:
TaskCount: 1
TaskDefinitionArn: !Ref TaskDefinition
NetworkConfiguration:
AwsVpcConfiguration:
Subnets:
- !Ref Subnet1
- !Ref Subnet2
SecurityGroups:
- !GetAtt SecurityGroup.GroupId
AssignPublicIp: DISABLED
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: anonymized-backend
Cpu: '1024'
Memory: '8192'
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
ExecutionRoleArn: !GetAtt ECSTaskExecutionRole.Arn
TaskRoleArn: !Ref ECSTaskRole
RuntimePlatform:
CpuArchitecture: X86_64
ContainerDefinitions:
- Name: !Sub ${StackName}-taskdefinition
Image: !Sub
- ${RepoUrl}:${ImageTag}
- RepoUrl: !GetAtt Repository.RepositoryUri
PortMappings:
- ContainerPort: 3000
LogConfiguration:
LogDriver: awslogs
Options:
mode: non-blocking
max-buffer-size: 25m
awslogs-group: !Ref LogGroup
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: containerlog
Environment:
- Name: VERSION_ID
Value: !Ref VersionId
LogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: /fargatelogs
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ecs-tasks.amazonaws.com]
Action: ['sts:AssumeRole']
Condition:
ArnLike:
aws:SourceArn: !Sub arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:*
StringEquals:
aws:SourceAccount: !Ref AWS::AccountId
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
ECSTaskRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ecs-tasks.amazonaws.com]
Action: ['sts:AssumeRole']
Condition:
ArnLike:
aws:SourceArn: !Sub arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:*
StringEquals:
aws:SourceAccount: !Ref AWS::AccountId
Path: /
Policies:
- PolicyName: SSMParameterAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ssm:GetParameter
Resource:
- '*'
- PolicyName: S3Access
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:PutObject
- s3:ListBucket
Resource:
- '*'
Outputs:
ClusterName:
Description: Amazon ECS Cluster Name
Value: !Ref Cluster
RepositoryUrl:
Description: URL of the repo
Value: !GetAtt Repository.RepositoryUri
The deployment goes well, and I can see the scheduled task from the console. However, the task will not start at the scheduled time.
I was able to create a similar scheduled task, directly from the console, and it starts instead; a difference in the definition that I see is that Launch type: FARGATE
and Platform version: LATEST
are present in the console-defined one, but I don't see how to provide them in the SAM script.
I expect that they should behave in the same way, why is it not so?
Upvotes: 0
Views: 29
Reputation: 200988
In my experience this is almost always because you use the wrong IAM role for the EventBridge scheduler. You can verify that by looking in your AWS account's CloudTrail.
In your code for the CronRule
Target, you are giving it the ECSTaskRole
. This is incorrect. The ECS Task Definition has the ECSTaskRole
assigned to the task already. What you need to give the CronRule
is an IAM role it can use that will give it permission to execute tasks in your ECS cluster.
In particular, it needs a role with an Assume Role policy that allows sts:AssumeRole
for the service events.amazonaws.com
and the role needs the following IAM permissions:
iam:PassRole
ecs:RunTask
This role configuration is documented here.
Upvotes: 0