作成されるリソース
- 基本的なネットワーク
- ECSクラスター(EC2 on ECS)
- CodePipeline
- CodeCommit
- CodeBuild BuildProject
- (ECS Deploy)
※CodePipelineのデプロイステージは未検証のためコメントアウト
テンプレート
ECSクラスターの作成は以下の公式ドキュメントを参考にしています。
AWSTemplateFormatVersion: 2010-09-09
Parameters:
VPCCidrBlock:
Description: The primary IPv4 CIDR block for the VPC.
Type: String
MinLength: '9'
MaxLength: '18'
Default: 10.0.0.0/16
AllowedPattern: '(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})'
SubnetCidrBits:
Description: Subnet CidrBits, alowed bitween 8 and 30.
Type: String
MinLength: '1'
MaxLength: '2'
Default: '24'
AllowedPattern: '(\d{1,2})'
PJPrefix:
Type: String
Default: ecs
ECSAMI:
Description: The Amazon Machine Image ID used for the cluster
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id
CodeCommitSourceBucket:
Type: String
Default: example-bucket
CodeCommitSourceObjectKey:
Type: String
Default: example-key.zip
Mappings:
CidrBits:
'30':
bit: 2
'29':
bit: 3
'28':
bit: 4
'27':
bit: 5
'26':
bit: 6
'25':
bit: 7
'24':
bit: 8
'23':
bit: 9
'22':
bit: 10
'21':
bit: 11
'20':
bit: 12
'19':
bit: 13
'18':
bit: 14
'17':
bit: 15
'16':
bit: 16
'15':
bit: 17
'14':
bit: 18
'13':
bit: 19
'12':
bit: 20
'11':
bit: 21
'10':
bit: 22
'9':
bit: 23
'8':
bit: 24
Resources:
VPC:
Type: 'AWS::EC2::VPC'
Properties:
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
CidrBlock: !Ref VPCCidrBlock
Tags:
- Key: Name
Value: !Sub '${PJPrefix}-VPC'
PublicSubnet1:
Type: 'AWS::EC2::Subnet'
Properties:
AvailabilityZone: !Select
- 0
- 'Fn::GetAZs': !Ref 'AWS::Region'
CidrBlock:
Fn::Select:
- 0
- Fn::Cidr:
- Fn::GetAtt:
- VPC
- CidrBlock
- 4
- Fn::FindInMap:
- CidrBits
- !Ref SubnetCidrBits
- bit
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub '${PJPrefix}-PublicSubnet1'
VpcId: !Ref VPC
PublicSubnet2:
Type: 'AWS::EC2::Subnet'
Properties:
CidrBlock:
Fn::Select:
- 1
- Fn::Cidr:
- Fn::GetAtt:
- VPC
- CidrBlock
- 4
- Fn::FindInMap:
- CidrBits
- !Ref SubnetCidrBits
- bit
AvailabilityZone: !Select
- 1
- 'Fn::GetAZs': !Ref 'AWS::Region'
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub '${PJPrefix}-PublicSubnet2'
VpcId: !Ref VPC
PrivateSubnet1:
Type: 'AWS::EC2::Subnet'
Properties:
CidrBlock:
Fn::Select:
- 2
- Fn::Cidr:
- Fn::GetAtt:
- VPC
- CidrBlock
- 4
- Fn::FindInMap:
- CidrBits
- !Ref SubnetCidrBits
- bit
AvailabilityZone: !Select
- 0
- 'Fn::GetAZs': !Ref 'AWS::Region'
Tags:
- Key: Name
Value: !Sub '${PJPrefix}-PrivateSubnet1'
VpcId: !Ref VPC
PrivateSubnet2:
Type: 'AWS::EC2::Subnet'
Properties:
CidrBlock:
Fn::Select:
- 3
- Fn::Cidr:
- Fn::GetAtt:
- VPC
- CidrBlock
- 4
- Fn::FindInMap:
- CidrBits
- !Ref SubnetCidrBits
- bit
AvailabilityZone: !Select
- 1
- 'Fn::GetAZs': !Ref 'AWS::Region'
Tags:
- Key: Name
Value: !Sub '${PJPrefix}-PrivateSubnet2'
VpcId: !Ref VPC
InternetGateway:
Type: 'AWS::EC2::InternetGateway'
DependsOn: VPC
Properties:
Tags:
- Key: Name
Value: InternetGateway
VPCGatewayAttachment:
Type: 'AWS::EC2::VPCGatewayAttachment'
DependsOn:
- VPC
- InternetGateway
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
PublicRouteTable:
Type: 'AWS::EC2::RouteTable'
Properties:
Tags:
- Key: Name
Value: PublicRouteTable
VpcId: !Ref VPC
PublicRoute:
Type: 'AWS::EC2::Route'
DependsOn: VPCGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnetRouteTableAssociation1:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
DependsOn:
- PublicSubnet1
- PublicRouteTable
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
PublicSubnetRouteTableAssociation2:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
DependsOn:
- PublicSubnet2
- PublicRouteTable
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
ElasticIP1:
Type: 'AWS::EC2::EIP'
Properties:
Domain: vpc
Tags:
- Key: Name
Value: ElasticIP1
ElasticIP2:
Type: 'AWS::EC2::EIP'
Properties:
Domain: vpc
Tags:
- Key: Name
Value: ElasticIP2
NATGateway1:
Type: 'AWS::EC2::NatGateway'
Properties:
AllocationId: !GetAtt
- ElasticIP1
- AllocationId
SubnetId: !Ref PublicSubnet1
Tags:
- Key: Name
Value: NATGateway1
NATGateway2:
Type: 'AWS::EC2::NatGateway'
Properties:
AllocationId: !GetAtt
- ElasticIP2
- AllocationId
SubnetId: !Ref PublicSubnet2
Tags:
- Key: Name
Value: NATGateway2
PrivateRoutetable1:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: PrivateRouteTable1
PrivateRoute1:
Type: 'AWS::EC2::Route'
DependsOn:
- NATGateway1
Properties:
RouteTableId: !Ref PrivateRoutetable1
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NATGateway1
PrivateSubnetRouteTableAssociation1:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
RouteTableId: !Ref PrivateRoutetable1
SubnetId: !Ref PrivateSubnet1
PrivateRoutetable2:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: PrivateRouteTable2
PrivateRoute2:
Type: 'AWS::EC2::Route'
Properties:
RouteTableId: !Ref PrivateRoutetable2
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NATGateway2
PrivateSubnetRouteTableAssociation2:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref PrivateSubnet2
RouteTableId: !Ref PrivateRoutetable2
PrivateRoutetable3:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: PrivateRouteTable3
########### Create ECS Resource ############
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterSettings:
- Name: containerInsights
Value: enabled
ECSAutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
DependsOn:
# This is to ensure that the ASG gets deleted first before these
# resources, when it comes to stack teardown.
- ECSCluster
- EC2Role
Properties:
VPCZoneIdentifier:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
LaunchTemplate:
LaunchTemplateId: !Ref ContainerInstances
Version: !GetAtt ContainerInstances.LatestVersionNumber
MinSize: 2
MaxSize: 10
DesiredCapacity: 2
NewInstancesProtectedFromScaleIn: true
UpdatePolicy:
AutoScalingReplacingUpdate:
WillReplace: "true"
ContainerInstances:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: "asg-launch-template"
LaunchTemplateData:
ImageId: !Ref ECSAMI
InstanceType: t3.medium
IamInstanceProfile:
Name: !Ref EC2InstanceProfile
SecurityGroupIds:
- !Ref ContainerHostSecurityGroup
# This injected configuration file is how the EC2 instance
# knows which ECS cluster on your AWS account it should be joining
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config
yum install -y aws-cfn-bootstrap
/opt/aws/bin/cfn-init -v --stack ${AWS::StackId} --resource ContainerInstances --configsets full_install --region ${AWS::Region} &
# Disable IMDSv1, and require IMDSv2
MetadataOptions:
HttpEndpoint: enabled
HttpTokens: required
TagSpecifications:
- ResourceType: instance
Tags:
- Key: Name
Value: ECS Cluster
EC2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- !Ref EC2Role
CapacityProvider:
Type: AWS::ECS::CapacityProvider
Properties:
AutoScalingGroupProvider:
AutoScalingGroupArn: !Ref ECSAutoScalingGroup
ManagedScaling:
InstanceWarmupPeriod: 60
MinimumScalingStepSize: 1
MaximumScalingStepSize: 100
Status: ENABLED
# Percentage of cluster reservation to try to maintain
TargetCapacity: 100
ManagedTerminationProtection: ENABLED
# Create a cluster capacity provider assocation so that the cluster
# will use the capacity provider
CapacityProviderAssociation:
Type: AWS::ECS::ClusterCapacityProviderAssociations
Properties:
CapacityProviders:
- !Ref CapacityProvider
Cluster: !Ref ECSCluster
DefaultCapacityProviderStrategy:
- Base: 0
CapacityProvider: !Ref CapacityProvider
Weight: 1
# A security group for the EC2 hosts that will run the containers.
# This can be used to limit incoming traffic to or outgoing traffic
# from the container's host EC2 instance.
ContainerHostSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Access to the EC2 hosts that run containers
VpcId: !Ref VPC
# Role for the EC2 hosts. This allows the ECS agent on the EC2 hosts
# to communciate with the ECS control plane, as well as download the docker
# images from ECR to run on your host.
EC2Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
# See reference: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonEC2ContainerServiceforEC2Role
- arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
# This managed policy allows us to connect to the instance using SSM
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
# This is a role which is used within Fargate to allow the Fargate agent
# to download images, and upload logs.
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::Partition}:ecs:${AWS::Region}:${AWS::AccountId}:*
StringEquals:
aws:SourceAccount: AWS::AccountId
Path: /
# This role enables all features of ECS. See reference:
# https://docs.aws.amazon.com/AmazonECS/latest/developerguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonECSTaskExecutionRolePolicy
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
CodeCommit:
Type: AWS::CodeCommit::Repository
Properties:
RepositoryName: app
RepositoryDescription: This is a repository for my project.
Code:
BranchName: main
S3:
Bucket: !Ref CodeCommitSourceBucket
Key: !Ref CodeCommitSourceObjectKey
CodeBuild:
Type: AWS::CodeBuild::Project
Properties:
Artifacts:
Type: CODEPIPELINE
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux2-x86_64-standard:4.0
PrivilegedMode: true
Type: LINUX_CONTAINER
LogsConfig:
CloudWatchLogs:
Status: ENABLED
ServiceRole: !GetAtt CodeBuildRole.Arn
Source:
Type: CODEPIPELINE
TimeoutInMinutes: 5
CodeBuildRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "codebuild.amazonaws.com"
Action:
- "sts:AssumeRole"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSCodeBuildAdminAccess
- arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
Path: /
CodePipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
ArtifactStore:
Location: !Ref S3Bucket
Type: S3
RoleArn: !GetAtt CodePipelineRole.Arn
Stages:
- Name: Source
Actions:
- ActionTypeId:
Category: Source
Owner: AWS
Provider: CodeCommit
Version: 1
Name: Source
Configuration:
BranchName: main
RepositoryName: !GetAtt CodeCommit.Name
FileName: imagedefinitions.json
OutputArtifacts:
- Name: sourceArtifact
RunOrder: 1
- Name: Build
Actions:
- ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: 1
Name: Build
Configuration:
ProjectName: !Ref CodeBuild
InputArtifacts:
- Name: sourceArtifact
OutputArtifacts:
- Name: buildArtifact
RunOrder: 2
# - Name: Deploy
# Actions:
# - ActionTypeId:
# Category: Deploy
# Owner: AWS
# Provider: Amazon ECS
# Version: 1
# Name: Build
# Configuration:
# ClusterName: !Ref ECSCluster
# ServiceName: !Ref ECSCluster
# InputArtifacts:
# - Name: buildArtifact
# RunOrder: 3
S3Bucket:
Type: 'AWS::S3::Bucket'
CodePipelineRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "codepipeline.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: /
RolePolicies:
Type: "AWS::IAM::Policy"
Properties:
PolicyName: "CodePipelinePolicy"
Roles:
- !Ref CodePipelineRole
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "codecommit:CancelUploadArchive"
- "codecommit:GetBranch"
- "codecommit:GetCommit"
- "codecommit:GetUploadArchiveStatus"
- "codecommit:UploadArchive"
Resource: "*"
- Effect: "Allow"
Action:
- "codedeploy:CreateDeployment"
- "codedeploy:GetApplicationRevision"
- "codedeploy:GetDeployment"
- "codedeploy:GetDeploymentConfig"
- "codedeploy:RegisterApplicationRevision"
Resource: "*"
- Effect: "Allow"
Action:
- "codebuild:BatchGetBuilds"
- "codebuild:StartBuild"
Resource: "*"
- Effect: "Allow"
Action:
- "devicefarm:ListProjects"
- "devicefarm:ListDevicePools"
- "devicefarm:GetRun"
- "devicefarm:GetUpload"
- "devicefarm:CreateUpload"
- "devicefarm:ScheduleRun"
Resource: "*"
- Effect: "Allow"
Action:
- "lambda:InvokeFunction"
- "lambda:ListFunctions"
Resource: "*"
- Effect: "Allow"
Action:
- "iam:PassRole"
Resource: "*"
- Effect: "Allow"
Action:
- "elasticbeanstalk:*"
- "ec2:*"
- "elasticloadbalancing:*"
- "autoscaling:*"
- "cloudwatch:*"
- "s3:*"
- "sns:*"
- "cloudformation:*"
- "rds:*"
- "sqs:*"
- "ecs:*"
Resource: "*"