第3回CloudFormationテンプレートの実行(ECS)
さて第3回の今回は、本記事に記載のCloudFormationテンプレートを用いて、自動デプロイのデプロイ先となるECSとECRを構築していきます。
前回:[社内勉強会資料] CloudFormationで構築する自動デプロイ環境 ~ 2/6
CloudFormationで作成するリソース
- CloudFormationテンプレートを使って、以下のAWSリソースを作成します。
- ECR
- ALB
- Listener
- TargetGroup
- ECS
- Cluster
- Service
- TaskDefinition
- IAM
- Role
- CloudWatch
- LogGroup
CloudFormationテンプレート
ecr.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: ECR template
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "Environment Name"
Parameters:
- ProjectEnvironment
- Label:
default: "ECR Repository Configuration"
Parameters:
- ImageTagMutability
Parameters:
ProjectEnvironment:
Type: String
Default: 'usecase-auto-deploy'
# 同じタグによる上書きを許可する(デフォルト)
ImageTagMutability:
Description: The tag mutability setting for the repository.
Type: String
Default: MUTABLE
AllowedValues:
- IMMUTABLE
- MUTABLE
Resources:
ECRRepository:
Type: AWS::ECR::Repository
Properties:
RepositoryName: !Sub "${ProjectEnvironment}-ecr"
ImageTagMutability: !Ref ImageTagMutability
# ライフサイクル : イメージが20個以上になった場合、古い順に削除する
LifecyclePolicy:
LifecyclePolicyText: |
{
"rules": [
{
"rulePriority": 1,
"description": "Delete more than 20 images",
"selection": {
"tagStatus": "any",
"countType": "imageCountMoreThan",
"countNumber": 20
},
"action": {
"type": "expire"
}
}
]
}
Outputs:
ECRRepository:
Value: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ECRRepository}"
Export:
Name: !Sub "${ProjectEnvironment}-ecr-uri"
fargate.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description:
Create Fargate and ALB
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "Project Name Prefix"
Parameters:
- ProjectName
- Label:
default: "InternetALB Configuration"
Parameters:
- InternetALBName
- TargetGroupName
- CertificateArn
- HostedZoneName
- WebsiteDomainName
- Label:
default: "Fargate for ECS Configuration"
Parameters:
- ECSClusterName
- ECSTaskName
- ECSTaskCPUUnit
- ECSTaskMemory
- ECSContainerName
- ECSImageName
- ECSServiceName
- ECSTaskDesiredCount
- Label:
default: "Scaling Configuration"
Parameters:
- TaskMinContainerCount
- TaskMaxContainerCount
ParameterLabels:
InternetALBName:
default: "InternetALBName"
TargetGroupName:
default: "TargetGroupName"
ECSClusterName:
default: "ECSClusterName"
ECSTaskName:
default: "ECSTaskName"
ECSTaskCPUUnit:
default: "ECSTaskCPUUnit"
ECSTaskMemory:
default: "ECSTaskMemory"
ECSContainerName:
default: "ECSContainerName"
ECSImageName:
default: "ECSImageName"
ECSServiceName:
default: "ECSServiceName"
ECSTaskDesiredCount:
default: "ECSTaskDesiredCount"
Parameters:
ProjectName:
Default: usecase-auto-deploy
Type: String
#InternetALB
InternetALBName:
Type: String
Default: "alb"
#TargetGroupName
TargetGroupName:
Type: String
Default: "tg"
#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"
#ECSServiceName
ECSServiceName:
Type: String
Default: "service"
#ECSTaskDesiredCount
ECSTaskDesiredCount:
Type: Number
Default: 1
TaskMinContainerCount:
Type: Number
Description: Minimum number of containers to run for the service
Default: 1
MinValue: 1
ConstraintDescription: Value must be at least one
TaskMaxContainerCount:
Type: Number
Description: Maximum number of containers to run for the service when auto scaling out
Default: 2
MinValue: 1
ConstraintDescription: Value must be at least one
Resources:
TargetGroup:
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
Properties:
VpcId:
Fn::ImportValue: !Sub "${ProjectName}-vpc"
Name: !Sub "${ProjectName}-${TargetGroupName}"
Protocol: HTTP
Port: 80
TargetType: ip
HealthCheckEnabled: true
HealthCheckPath: '/index.html'
Matcher:
HttpCode: "302,200"
InternetALB:
Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
Properties:
Name: !Sub "${ProjectName}-${InternetALBName}"
Tags:
- Key: Name
Value: !Sub "${ProjectName}-${InternetALBName}"
Scheme: "internet-facing"
LoadBalancerAttributes:
- Key: "deletion_protection.enabled"
Value: false
- Key: "idle_timeout.timeout_seconds"
Value: 60
SecurityGroups:
- Fn::ImportValue: !Sub "${ProjectName}-ALBSecurityGroupId"
Subnets:
- Fn::ImportValue: !Sub "${ProjectName}-ALBSubnetId1"
- Fn::ImportValue: !Sub "${ProjectName}-ALBSubnetId2"
ALBListener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
DefaultActions:
- TargetGroupArn: !Ref TargetGroup
Type: forward
LoadBalancerArn: !Ref InternetALB
Port: 80
Protocol: HTTP
ECSCluster:
Type: "AWS::ECS::Cluster"
Properties:
ClusterName: !Sub "${ProjectName}-${ECSClusterName}"
ECSLogGroup:
Type: "AWS::Logs::LogGroup"
Properties:
LogGroupName: !Sub "/ecs/logs/${ProjectName}-ecs-group"
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${ProjectName}-ECSTaskExecutionRolePolicy-${AWS::Region}"
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
ECSTaskDefinition:
Type: "AWS::ECS::TaskDefinition"
Properties:
Cpu: !Ref ECSTaskCPUUnit
ExecutionRoleArn: !Ref ECSTaskExecutionRole
Family: !Sub "${ProjectName}-${ECSTaskName}"
Memory: !Ref ECSTaskMemory
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
ContainerDefinitions:
- Name: "app"
Image:
!Sub
- "${ECR_URI}:latest"
- ECR_URI: {"Fn::ImportValue": !Sub "${ProjectName}-ecr-uri"}
Command:
- "/bin/sh -c \"echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' > /var/www/html/index2.html && /root/run_apache.sh\""
EntryPoint:
- "sh"
- "-c"
Environment:
- Name: 'AWS_REGION'
Value: 'ap-northeast-1'
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref ECSLogGroup
awslogs-region: !Ref "AWS::Region"
awslogs-stream-prefix: !Ref ProjectName
MemoryReservation: 128
Essential: true
PseudoTerminal: true
PortMappings:
- HostPort: 80
Protocol: tcp
ContainerPort: 80
ECSService:
Type: AWS::ECS::Service
DependsOn: ALBListener
Properties:
Cluster: !Ref ECSCluster
DesiredCount: !Ref ECSTaskDesiredCount
LaunchType: FARGATE
LoadBalancers:
-
TargetGroupArn: !Ref TargetGroup
ContainerPort: 80
ContainerName: "app"
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- Fn::ImportValue: !Sub "${ProjectName}-ECSSecurityGroupId"
Subnets:
- Fn::ImportValue: !Sub "${ProjectName}-ECSSubnetId1"
- Fn::ImportValue: !Sub "${ProjectName}-ECSSubnetId2"
ServiceName: !Sub "${ProjectName}-${ECSServiceName}"
TaskDefinition: !Ref ECSTaskDefinition
ECR構築
まずはDockerコンテナの実体となるイメージを配置するためのECRの構築から進めましょう。
ECR構築:ecr.yamlの実行 ステップ1
- テンプレートの準備で「テンプレートの準備完了」を選択
- テンプレートの指定で「テンプレートファイルのアップロード」を選択
- テンプレートファイルのアップロードで「ecr.yaml」(上記) をアップロード
- [次へ」をクリック
ECR構築:ecr.yamlの実行 ステップ2
ECR構築:ecr.yamlの実行 ステップ3
ECR構築:ecr.yamlの実行 ステップ4
ECR構築:スタック作成の結果を確認
ECR構築:リソースの確認
ECR構築:コンテナイメージのPush
- コマンドプロンプト (ここではPowerShellを前提としています。) を開き、下記コマンドを実行します
Docker Desktopは起動しておいてください。
# 各自 GitHubの auto-deploy を git cloneしたディレクトリに移動します
PS cd C:\git\auto-deploy
# 各自リージョンで置換してください
PS $region=“リージョン (例 : ap-northeast-1)”
PS $account_id=ECRを作成したAWSアカウントID (例 : 1234567)
# Macの場合
$ region=“リージョン (例 : ap-northeast-1)”
$ account_id=ECRを作成したAWSアカウントID (例 : 1234567)
# ECRへログイン
PS aws ecr get-login-password --region $region | docker login --username AWS --password-stdin "$account_id.dkr.ecr.$region.amazonaws.com"
# コンテナイメージをビルド
PS docker build -t "$account_id.dkr.ecr.$region.amazonaws.com/usecase-auto-deploy-ecr:latest" .
# コンテナイメージをECRへプッシュ
PS docker push "$account_id.dkr.ecr.$region.amazonaws.com/usecase-auto-deploy-ecr:latest"
ECRへのログイン時、必要に応じてプロファイルを指定してください。
# プロファイルの指定方法
PS aws ecr get-login-password --region $region --profile handson | ~
ECR構築:ECRの確認
ECSの構築
続けて、直前の手順でECRにPushしたコンテナを起動するためのECSの構築を行います。
ECSの構築:fargate.yamlの実行 ステップ1
- テンプレートの準備で「テンプレートの準備完了」を選択
- テンプレートの指定で「テンプレートファイルのアップロード」を選択
- テンプレートファイルのアップロードで「fargate.yaml」(添付ファイル参照) をアップロード
- [次へ」をクリック
ECSの構築:fargate.yamlの実行 ステップ2
ECSの構築:fargate.yamlの実行 ステップ3
ECS構築:スタック作成の結果を確認
連載の第3回となる今回はここまで。
次回第4回は、自動デプロイの実行に必要な権限(IAMロール)を構築していきます。