Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS ECS Create Scheduled Tasks (cron) via Cloudformation

We want to create ScheduledTasks in AWS ECS via CloudFormation. Is there a programmatic way to create via boto or cloudformation?

like image 533
siliconsenthil Avatar asked Jun 13 '17 16:06

siliconsenthil


People also ask

Does ECS use CloudFormation?

Amazon ECS supports creating clusters, task definitions, services, and task sets in AWS CloudFormation. The following examples demonstrate how to create resources with these templates using the AWS CLI.

How do I run a scheduled task in ECS?

Open the Amazon ECS console at https://console.aws.amazon.com/ecs/ . Choose the cluster your scheduled tasks are run in. On the Cluster: cluster-name page, choose the Scheduled Tasks tab.


2 Answers

In order to define a scheduled ECS task in CloudFormation, you need to define a "AWS::Events::Rule" resource with an ECS task as a target.

"TaskSchedule": {
  "Type": "AWS::Events::Rule",
  "Properties": {
    "Description": "dump data every workday at 10",
    "Name": "dump-data",
    "ScheduleExpression": "cron(0 10 ? * MON-FRI *)",
    "State": "ENABLED",
    "Targets": [
      {
        "Id": "dump-data-ecs-task",
        "RoleArn": {
          "Fn::GetAtt": ["TaskSchedulerRole", "Arn"]
        },
        "EcsParameters": {
          "TaskDefinitionArn": {
            "Ref": "TaskDefinition"
          },
          "TaskCount": 1
        },
        "Arn": {
          "Fn::GetAtt": ["EcsCluster", "Arn"]
        }
      }
    ]
  }
}
like image 77
Mark Avatar answered Oct 22 '22 08:10

Mark


Troposphere now allows to define ECS scheduled task, you need three resources for that,

  1. the task definition:

    from troposphere.ecs import (
        ContainerDefinition,
        TaskDefinition,
    )
    
    scheduled_worker_task_definition = TaskDefinition(
        "ScheduledWorkerTask",
        template=template,
        ContainerDefinitions=[
            ContainerDefinition(
                Name="ScheduledWorker",
                Cpu=200,
                Memory=300,
                Essential=True,
                Image="<image>",
                EntryPoint=['<entry_point>']
            ),  
        ],  
    )
    
  2. The role to run the task:

    from troposphere import iam
    
    run_task_role = iam.Role(
        "RunTaskRole",
        template=template,
        AssumeRolePolicyDocument=dict(Statement=[dict(
            Effect="Allow",
            Principal=dict(Service=["events.amazonaws.com"]),
            Action=["sts:AssumeRole"],
        )]),
        Path="/",
        Policies=[
            iam.Policy(
                PolicyName="RunTaskPolicy",
                PolicyDocument=dict(
                    Statement=[dict(
                        Effect="Allow",
                        Action=[
                            "ecs:RunTask",
                        ],
                        Resource=["*"],
                        Condition=dict(
                            ArnEquals={
                                "ecs:cluster": GetAtt(cluster, "Arn"),
                            }
                        )
                    )],
                ),
            ),
        ],
    )
    
  3. The event rule that schedules the task:

    from troposphere.events import Rule, Target, EcsParameters
    
    Rule(
        "SchedulingRule",
        template=template,
        Description="My schedule task rule",
        State="ENABLED",
        ScheduleExpression="rate(30 minutes)",
        Targets=[
            Target(
                Id="ScheduledWorkerTaskDefinitionTarget",
                RoleArn=GetAtt(run_task_role, "Arn"),
                Arn=GetAtt(cluster, "Arn"),
                EcsParameters=EcsParameters(
                    TaskCount=1,
                    TaskDefinitionArn=Ref(scheduled_worker_task_definition),
                ),
            ),
        ]
    )
    

Where the JSON output looks like:

    ...
    "ScheduledWorkerTask": {
        "Condition": "Deploy",
        "Properties": {
            "ContainerDefinitions": [
                {
                    "Cpu": 200,
                    "EntryPoint": [
                        "<entry_point>"
                    ],
                    "Essential": "true",
                    "Image": {
                        "Fn::Join": [
                            "",
                            [
                                {
                                    "Ref": "AWS::AccountId"
                                },
                                ".dkr.ecr.",
                                {
                                    "Ref": "AWS::Region"
                                },
                                ".amazonaws.com/",
                                {
                                    "Ref": "ApplicationRepository"
                                },
                                ":",
                                "<image>"
                            ]
                        ]
                    },
                    "Memory": 300,
                    "Name": "ScheduledWorker"
                }
            ]
        },
        "Type": "AWS::ECS::TaskDefinition"
    },

    "SchedulingRule": {
        "Properties": {
            "Description": "My schedule task rule",
            "ScheduleExpression": "rate(30 minutes)",
            "State": "ENABLED",
            "Targets": [
                {
                    "Arn": {
                        "Fn::GetAtt": [
                            "Cluster",
                            "Arn"
                        ]
                    },
                    "EcsParameters": {
                        "TaskCount": 1,
                        "TaskDefinitionArn": {
                            "Ref": "ScheduledWorkerTask"
                        }
                    },
                    "Id": "ScheduledWorkerTaskDefinitionTarget",
                    "RoleArn": {
                        "Fn::GetAtt": [
                            "RunTaskRole",
                            "Arn"
                        ]
                    }
                }
            ]
        },
        "Type": "AWS::Events::Rule"
    },

    "RunTaskRole": {
        "Properties": {
            "AssumeRolePolicyDocument": {
                "Statement": [
                    {
                        "Action": [
                            "sts:AssumeRole"
                        ],
                        "Effect": "Allow",
                        "Principal": {
                            "Service": [
                                "events.amazonaws.com"
                            ]
                        }
                    }
                ]
            },
            "Path": "/",
            "Policies": [
                {
                    "PolicyDocument": {
                        "Statement": [
                            {
                                "Action": [
                                    "ecs:RunTask"
                                ],
                                "Condition": {
                                    "ArnEquals": {
                                        "ecs:cluster": {
                                            "Fn::GetAtt": [
                                                "Cluster",
                                                "Arn"
                                            ]
                                        }
                                    }
                                },
                                "Effect": "Allow",
                                "Resource": [
                                    "*"
                                ]
                            }
                        ]
                    },
                    "PolicyName": "RunTaskPolicy"
                }
            ]
        },
        "Type": "AWS::IAM::Role"
    },
    ...

More info at https://jeanphix.github.io/2017/10/04/ecs-scheduled-cron-task-with-cloudformation/

like image 43
jeanphix Avatar answered Oct 22 '22 07:10

jeanphix