CloudFormationでFargateのタスクのスケジューリングを構築する #Fargate

VPC構築済みの環境や、同じVPC内に複数のタスクのスケジューリングのFargateを複数構築するときに使えるCloudFormationテンプレートを作成してみました。 Fargateに関連するCloudwatch Logsの設定も含まれています。自分が使いたいFargateのサンプルが見つからなかったので作成しました。 どなたかのお役に立てれば光栄です。
2019.11.12

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、コカコーラ大好きカジです。

VPC構築済みの環境や、同じVPC内に複数のタスクのスケジューリングのFargateを複数構築するときに使えるCloudFormationテンプレートを作成してみました。 Fargateに関連するCloudwatch Logsの設定も含まれています。 また、自分が使いたいFargateのサンプルが見つからなかったので作成しました。 どなたかのお役に立てれば光栄です。

前提条件

  • VPC、サブネット、ECS Task用のSecurity Groupが構築済み
  • Fargateを配置するサブネットは、NATゲートウェイ経由でインターネット通信またはPrivate LinkでECRへ通信可能
  • ECRリポジトリが構築済みで、DockerイメージをPushしておくこと、無い場合はこちらのブロクでDockerイメージの作成とECRを構築してください。

スケジューリングのFargateの構築

文末のCloudFormationテンプレートでCreate Stackしてください。

Crate Stack時に、VPC、Subnet、Security Group、ECRを指定するようにしています。そのほかはそのままでOKです。

途中、ECS用のIAM Roleを作成するためIAMの許可にチェックを入れます。

Create Stackが正常に終わると以下のようになります。正常にできない場合は、ネットワーク構成や指定しているVPC、サブネットに誤りがないか確認しましょう。

あと、テスト起動するよう、スケジュールを1dayから、cronの時間指定へ変更して動作させてみます。

起動すると以下の表示になります。

コンテナ側のIPアドレスは以下の部分で確認します。

起動しているコンテナは、nginxのコンテナなので、外部からcurlコマンドでコンテナへアクセスすると、以下のようにnginxが表示されます。

$ curl -v http://10.1.21.66
* Rebuilt URL to: http://10.1.21.66/
* Trying 10.1.21.66...
* TCP_NODELAY set
* Connected to 10.1.21.66 (10.1.21.66) port 80 (#0)
> GET / HTTP/1.1
> Host: 10.1.21.66
> User-Agent: curl/7.61.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.15.8
< Date: Tue, 12 Nov 2019 06:29:56 GMT
< Content-Type: text/html
< Content-Length: 612
< Last-Modified: Wed, 26 Dec 2018 23:21:49 GMT
< Connection: keep-alive
< ETag: "5c240d0d-264"
< Accept-Ranges: bytes
<


<style>
    body {<br />
        width: 35em;<br />
        margin: 0 auto;<br />
        font-family: Tahoma, Verdana, Arial, sans-serif;<br />
    }<br />
</style>

 
<h1>Welcome to nginx!</h1>
If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.

For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.

<em>Thank you for using nginx.</em>


* Connection #0 to host 10.1.21.66 left intact

CloudFormationテンプレート

実行タイミングについては、「ScheduleExpression: rate(1 day)」の部分を変更してください。cron形式でも記載できます。

sample-fargate-schedle.yaml

AWSTemplateFormatVersion: "2010-09-09"
Description:
Fargate and ALB Create

Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "Project Name Prefix"
Parameters:
- ProjectName

- Label:
default: "Fargate for ECS Configuration"
Parameters:
- ECSClusterName
- ECSTaskName
- ECSTaskCPUUnit
- ECSTaskMemory
- ECSContainerName
- ECSImageName
- ECSServiceName
- ECSTaskDesiredCount
- ECSScheduleRuleName
- ECSScheduleTargetName

ParameterLabels:
ECSClusterName:
default: "ECSClusterName"
ECSTaskName:
default: "ECSTaskName"
ECSTaskCPUUnit:
default: "ECSTaskCPUUnit"
ECSTaskMemory:
default: "ECSTaskMemory"
ECSContainerName:
default: "ECSContainerName"
ECSImageName:
default: "ECSImageName"
ECSServiceName:
default: "ECSServiceName"
ECSTaskDesiredCount:
default: "ECSTaskDesiredCount"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------#
Parameters:
ProjectName:
Default: sample-fargate-batch
Type: String

#VPCID
VpcId:
Description : "VPC ID"
Type: AWS::EC2::VPC::Id

#ECSSecurity Group
ECSSecurityGroupId:
Type: AWS::EC2::SecurityGroup::Id

#ECSSubnet1
ECSSubnetId1:
Description : "ECS Subnet 1st"
Type : AWS::EC2::Subnet::Id

#ECSSubnet2
ECSSubnetId2:
Description : "ECS Subnet 2st"
Type : AWS::EC2::Subnet::Id

#ECSClusterName
ECSClusterName:
Type: String
Default: "cluster"

#ECSTaskName
ECSTaskName:
Type: String
Default: "task"

#ECSTaskCPUUnit
ECSTaskCPUUnit:
AllowedValues: [ 256, 512, 1024, 2048, 4096 ]
Type: String
Default: "256"

#ECSTaskMemory
ECSTaskMemory:
AllowedValues: [ 256, 512, 1024, 2048, 4096 ]
Type: String
Default: "512"

#ECSContainerName
ECSContainerName:
Type: String
Default: "container"

#ECSImageName
ECSImageName:
Type: String
Default: "xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/kaji-test-ecr:latest"

#ECSServiceName
ECSServiceName:
Type: String
Default: "service"

#ECSTaskDesiredCount
ECSTaskDesiredCount:
Type: Number
Default: 1

#ECSScheduleRuleName
ECSScheduleRuleName:
Type: String
Default: "batch-1day"

#ECSScheduleTargetName
ECSScheduleTargetName:
Type: String
Default: "target"

Resources:

# ------------------------------------------------------------#
# ECS Cluster
# ------------------------------------------------------------#
ECSCluster:
Type: "AWS::ECS::Cluster"
Properties:
ClusterName: !Sub "${ProjectName}-${ECSClusterName}"

# ------------------------------------------------------------#
# ECS LogGroup
# ------------------------------------------------------------#
ECSLogGroup:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: !Sub "/ecs/logs/${ProjectName}-ecs-group"

# ------------------------------------------------------------#
# ECS Task Role IAM Policy
# ------------------------------------------------------------#
ECSTaskRoleIAMPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: !Sub "${ProjectName}-ECSTaskPolicy"
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sqs:SendMessage
Resource: "*"

# ------------------------------------------------------------#
# ECS Task Role
# ------------------------------------------------------------#
ECSTaskRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${ProjectName}-ECSTaskRolePolicy"
Path: /
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- !Ref ECSTaskRoleIAMPolicy

# ------------------------------------------------------------#
# ECS Task Execution Role
# ------------------------------------------------------------#
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${ProjectName}-ECSTaskExecutionRolePolicy"
Path: /
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

# ------------------------------------------------------------#
# ECS TaskDefinition
# ------------------------------------------------------------#
ECSTaskDefinition:
Type: "AWS::ECS::TaskDefinition"
Properties:
Cpu: !Ref ECSTaskCPUUnit
ExecutionRoleArn: !Ref ECSTaskExecutionRole
Family: !Sub "${ProjectName}-${ECSTaskName}"
Memory: !Ref ECSTaskMemory
NetworkMode: awsvpc
TaskRoleArn: !Ref ECSTaskRole
RequiresCompatibilities:
- FARGATE

#ContainerDefinitions
ContainerDefinitions:
- Name: !Sub "${ProjectName}-${ECSContainerName}"
Image: !Ref ECSImageName
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref ECSLogGroup
awslogs-region: !Ref "AWS::Region"
awslogs-stream-prefix: !Ref ProjectName
MemoryReservation: 128
PortMappings:
- HostPort: 80
Protocol: tcp
ContainerPort: 80

# ------------------------------------------------------------#
# ECS Events Rule
# ------------------------------------------------------------#
ECSSchedule:
Type: AWS::Events::Rule
Description: ''
Properties:
State: ENABLED
ScheduleExpression: rate(1 day)
Name: !Ref ECSScheduleRuleName
Targets:
- Id: !Sub "${ECSScheduleRuleName}-${ECSScheduleTargetName}"
Arn: !GetAtt
- ECSCluster
- Arn
RoleArn: !GetAtt
- ECSTaskExecutionRole
- Arn
EcsParameters:
TaskDefinitionArn: !Ref ECSTaskDefinition
TaskCount: !Ref ECSTaskDesiredCount
LaunchType: FARGATE
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: DISABLED
SecurityGroups:
- !Ref ECSSecurityGroupId
Subnets:
- !Ref ECSSubnetId1
- !Ref ECSSubnetId2