AWS CloudFormation
CloudFormationとは
設定ファイルからAWS環境を構築するサービス
AWS Cliからawsコマンドが記載されたシェルを実行してインフラ環境を構築できる
=Infrastructure as Code
=IaC
コンソールから実行する方法とAWS Cliからシェルで実行する方法(後述)がある
テンプレート
CloudFormationで利用するjsonまたはymlファイルで定義する設定ファイル
・AWSTemplateFormatVersion
・Description
・Parameters
・Resources
・Outputs
等
スタック
テンプレートから作成したリソース
テンプレート内で複数のAWSサービスを定義した場合でも1つのスタックとしてまとめられる
VPC作成
AWSコマンド
aws cloudformation deploy
--stack-name aws_test-vpc
--template-file template/vpc.yml
--no-execute-changeset
--parameter-overrides
SystemName=aws_test
vpc.yml
AWSTemplateFormatVersion: ‘2010-09-09’
Description: VPC Network Template
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------#
Parameters:
SystemName:
Type: String
Description: Your System Name.
Resources:
# ------------------------------------------------------------#
# VPC
# ------------------------------------------------------------#
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: ‘true’
EnableDnsHostnames: ‘true’
InstanceTenancy: default
Tags:
- Key: Name
Value: !Sub ${SystemName}-VPC
# ------------------------------------------------------------#
# InternetGateway
# ------------------------------------------------------------#
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub ${SystemName}-IGW
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
# ------------------------------------------------------------#
# Subnet
# ------------------------------------------------------------#
PublicSubnet1a:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
AvailabilityZone: ap-northeast-1a
CidrBlock: 10.0.0.0/24
MapPublicIpOnLaunch: ‘true’
Tags:
- Key: Name
Value: !Sub ${SystemName}-Public-Subnet-1a
VpcId: !Ref VPC
PublicSubnet1c:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
AvailabilityZone: ap-northeast-1c
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: ‘true’
Tags:
- Key: Name
Value: !Sub ${SystemName}-Public-Subnet-1c
VpcId: !Ref VPC
PrivateSubnet1a:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
AvailabilityZone: ap-northeast-1a
CidrBlock: 10.0.10.0/24
MapPublicIpOnLaunch: ‘false’
Tags:
- Key: Name
Value: !Sub ${SystemName}-Private-Subnet-1a
VpcId: !Ref VPC
PrivateSubnet1c:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
AvailabilityZone: ap-northeast-1c
CidrBlock: 10.0.11.0/24
MapPublicIpOnLaunch: ‘false’
Tags:
- Key: Name
Value: !Sub ${SystemName}-Private-Subnet-1c
VpcId: !Ref VPC
PrivateSubnet2a:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
AvailabilityZone: ap-northeast-1a
CidrBlock: 10.0.20.0/24
MapPublicIpOnLaunch: ‘false’
Tags:
- Key: Name
Value: !Sub ${SystemName}-Private-Subnet-2c
VpcId: !Ref VPC
PrivateSubnet2c:
Type: AWS::EC2::Subnet
DependsOn: AttachGateway
Properties:
AvailabilityZone: ap-northeast-1c
CidrBlock: 10.0.21.0/24
MapPublicIpOnLaunch: ‘false’
Tags:
- Key: Name
Value: !Sub ${SystemName}-Private-Subnet-2c
VpcId: !Ref VPC
# ------------------------------------------------------------#
# ElasticIP, NatGateway
# ------------------------------------------------------------#
EIP1a:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
NAT1a:
Type: AWS::EC2::NatGateway
Properties:
AllocationId:
Fn::GetAtt:
- EIP1a
- AllocationId
SubnetId: !Ref PublicSubnet1a
Tags:
- Key: Name
Value: !Sub ${SystemName}-ngw-1a
EIP1c:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
NAT1c:
Type: AWS::EC2::NatGateway
Properties:
AllocationId:
Fn::GetAtt:
- EIP1c
- AllocationId
SubnetId: !Ref PublicSubnet1c
Tags:
- Key: Name
Value: !Sub ${SystemName}-ngw-1c
# ------------------------------------------------------------#
# RouteTable
# ------------------------------------------------------------#
PublicRouteTable:
Type: AWS::EC2::RouteTable
DependsOn: AttachGateway
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${SystemName}-Public-RT
PublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PrivateRouteTable1a:
Type: AWS::EC2::RouteTable
DependsOn: NAT1a
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${SystemName}-Private-RT1a
PrivateRoute1a:
Type: AWS::EC2::Route
DependsOn: NAT1a
Properties:
RouteTableId: !Ref PrivateRouteTable1a
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NAT1a
PrivateRouteTable1c:
Type: AWS::EC2::RouteTable
DependsOn: NAT1c
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${SystemName}-Private-RT1c
PrivateRoute1c:
Type: AWS::EC2::Route
DependsOn: NAT1c
Properties:
RouteTableId: !Ref PrivateRouteTable1c
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NAT1c
PrivateRouteTable2:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${SystemName}-Private-RT2
PublicSubnet1aRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1a
RouteTableId: !Ref PublicRouteTable
PublicSubnet1cRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1c
RouteTableId: !Ref PublicRouteTable
PrivateSubnet1aRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1a
RouteTableId: !Ref PrivateRouteTable1a
PrivateSubnet1cRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1c
RouteTableId: !Ref PrivateRouteTable1c
PrivateSubnet2aRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet2a
RouteTableId: !Ref PrivateRouteTable2
PrivateSubnet2cRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet2c
RouteTableId: !Ref PrivateRouteTable2
# ------------------------------------------------------------#
# Outputs
# ------------------------------------------------------------#
Outputs:
VPC:
Value: !Ref VPC
Export:
Name: !Sub ${SystemName}-VPC
PublicSubnet1a:
Value: !Ref PublicSubnet1a
Export:
Name: !Sub ${SystemName}-PublicSubnet1a
PublicSubnet1c:
Value: !Ref PublicSubnet1c
Export:
Name: !Sub ${SystemName}-PublicSubnet1c
PrivateSubnet1a:
Value: !Ref PrivateSubnet1a
Export:
Name: !Sub ${SystemName}-PrivateSubnet1a
PrivateSubnet1c:
Value: !Ref PrivateSubnet1c
Export:
Name: !Sub ${SystemName}-PrivateSubnet1c
PrivateSubnet2a:
Value: !Ref PrivateSubnet2a
Export:
Name: !Sub ${SystemName}-PrivateSubnet2a
PrivateSubnet2c:
Value: !Ref PrivateSubnet2c
Export:
Name: !Sub ${SystemName}-PrivateSubnet2c
セキュリティグループ作成
AWSコマンド
aws cloudformation deploy
--stack-name handson-securitygroup
--template-file template/securitygroup.yml
--no-execute-changeset
--parameter-overrides
SystemName=handson
AdminIpaddress=255.255.255.255
securitygroup.yml
AWSTemplateFormatVersion: “2010-09-09”
Description: “Security Groups”
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------#
Parameters:
SystemName:
Type: String
Description: Your System Name.
AdminIpaddress:
Type: String
Description: Your Administrator IP Address.
Resources:
# ------------------------------------------------------------#
# Security Groups
# ------------------------------------------------------------#
#-- app-alb-sg --#
appAlbSg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub “${SystemName}-app-alb-sg”
GroupDescription: !Sub “${SystemName}-app-alb-sg”
VpcId:
Fn::ImportValue:
!Sub “${SystemName}-VPC”
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Description: all
Tags:
- Key: Name
Value: !Sub “${SystemName}-app-alb-sg”
#-- admin-alb-sg --#
adminAlbSg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub “${SystemName}-admin-alb-sg”
GroupDescription: !Sub “${SystemName}-admin-alb-sg”
VpcId:
Fn::ImportValue:
!Sub “${SystemName}-VPC”
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: !Ref AdminIpaddress
Description: AdminIpaddress
Tags:
- Key: Name
Value: !Sub “${SystemName}-admin-alb-sg”
#-- app-fargate-sg --#
appFargateSg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub “${SystemName}-app-fargate-sg”
GroupDescription: !Sub “${SystemName}-app-fargate-sg”
VpcId:
Fn::ImportValue:
!Sub “${SystemName}-VPC”
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref appAlbSg
Description: !Sub “${SystemName}-app-alb-sg”
Tags:
- Key: Name
Value: !Sub “${SystemName}-app-fargate-sg”
#-- admin-fargate-sg --#
adminFargateSg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub “${SystemName}-admin-fargate-sg”
GroupDescription: !Sub “${SystemName}-admin-fargate-sg”
VpcId:
Fn::ImportValue:
!Sub “${SystemName}-VPC”
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref adminAlbSg
Description: !Sub “${SystemName}-admin-alb-sg”
Tags:
- Key: Name
Value: !Sub “${SystemName}-admin-fargate-sg”
#-- db-sg --#
dbSg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub “${SystemName}-db-sg”
GroupDescription: !Sub “${SystemName}-db-sg”
VpcId:
Fn::ImportValue:
!Sub “${SystemName}-VPC”
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref appFargateSg
Description: !Sub “${SystemName}-app-fargate-sg”
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref adminFargateSg
Description: !Sub “${SystemName}-admin-fargate-sg”
Tags:
- Key: Name
Value: !Sub “${SystemName}-db-sg”
# ------------------------------------------------------------#
# Outputs
# ------------------------------------------------------------#
Outputs:
appAlbSg:
Value: !Ref appAlbSg
Export:
Name: !Sub “${SystemName}-app-alb-sg”
adminAlbSg:
Value: !Ref adminAlbSg
Export:
Name: !Sub “${SystemName}-admin-alb-sg”
appFargateSg:
Value: !Ref appFargateSg
Export:
Name: !Sub “${SystemName}-app-fargate-sg”
adminFargateSg:
Value: !Ref adminFargateSg
Export:
Name: !Sub “${SystemName}-admin-fargate-sg”
dbSg:
Value: !Ref dbSg
Export:
Name: !Sub “${SystemName}-db-sg”
CodeCommit作成
AWSコマンド
aws cloudformation deploy
--stack-name handson-codecommit
--template-file template/codecommit.yml
--no-execute-changeset
--parameter-overrides
SystemName=handson
codecommit.yml
---
AWSTemplateFormatVersion: ‘2010-09-09’
Description: CodeCommit
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------#
Parameters:
SystemName:
Type: String
Description: Your System Name.
Resources:
# ------------------------------------------------------------#
# CodeCommit
# ------------------------------------------------------------#
codeCommitPhpApp:
Type: AWS::CodeCommit::Repository
Properties:
RepositoryName: !Sub ${SystemName}-codecommit-php-app
RepositoryDescription: !Sub ${SystemName}-codecommit-php-app
# ------------------------------------------------------------#
# Outputs
# ------------------------------------------------------------#
Outputs:
codeCommitPhpApp:
Value: !Ref codeCommitPhpApp
Export:
Name: !Sub ${SystemName}-codecommit-php-app
codeCommitPhpAppName:
Value: !GetAtt codeCommitPhpApp.Name
Export:
Name: !Sub ${SystemName}-codecommit-php-app-name
codeCommitPhpAppArn:
Value: !GetAtt codeCommitPhpApp.Arn
Export:
Name: !Sub ${SystemName}-codecommit-php-app-arn
ECR作成
AWSコマンド
aws cloudformation deploy
--stack-name handson-ecr
--template-file template/ecr.yml
--no-execute-changeset
--parameter-overrides
SystemName=handson
ecr.yml
AWSTemplateFormatVersion: ‘2010-09-09’
Description: ECR
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------#
Parameters:
SystemName:
Type: String
Description: Your System Name.
Resources:
# ------------------------------------------------------------#
# ECR
# ------------------------------------------------------------#
ecrPhpApp:
Type: AWS::ECR::Repository
Properties:
RepositoryName: !Sub ${SystemName}-ecr-php-app
LifecyclePolicy:
LifecyclePolicyText: |
{
”rules”: [
{
”rulePriority”: 1,
”description”: “Delete more than 20 images”,
”selection”: {
”tagStatus”: “any”,
”countType”: “imageCountMoreThan”,
”countNumber”: 20
},
”action”: {
”type”: “expire”
}
}
]
}
# ------------------------------------------------------------#
# Outputs
# ------------------------------------------------------------#
Outputs:
ecrPhpApp:
Value: !GetAtt ecrPhpApp.Arn
Export:
Name: !Sub ${SystemName}-ecr-php-app
RDS作成
事前準備:データベース接続パスワード登録
※コンソールで実行
AWS Systems Manager > パラメータストア > パラメータを作成
名前:DBPassword
値:XXXXXXX
AWSコマンド
aws cloudformation deploy
--stack-name handson-rds
--template-file template/rds.yml
--no-execute-changeset
--parameter-overrides
SystemName=handson
rds.yml
AWSTemplateFormatVersion: ‘2010-09-09’
Description: RDS
# ————————————————————#
# Parameters
# ————————————————————#
Parameters:
SystemName:
Type: String
Description: Your System Name.
Resources:
# ————————————————————#
# ParameterGroup
# ————————————————————#
paramGroup:
Type: AWS::RDS::DBParameterGroup
Properties:
Description: !Sub ${SystemName} rds parameter group
Family: mysql8.0
Tags:
– Key: Name
Value: !Sub ${SystemName}-db-parametergroup
# ————————————————————#
# DBSubnetGroup
# ————————————————————#
dbSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupName: !Sub ${SystemName}-db-subnetgroup
DBSubnetGroupDescription: !Sub ${SystemName}-db-subnetgroup
SubnetIds:
– Fn::ImportValue: !Sub ${SystemName}-PrivateSubnet2a
– Fn::ImportValue: !Sub ${SystemName}-PrivateSubnet2c
Tags:
– Key: Name
Value: !Sub ${SystemName}-db-subnetgroup
# ————————————————————#
# DBInstance
# ————————————————————#
db:
Type: AWS::RDS::DBInstance
Properties:
DBName: !Sub ${SystemName}db
AllocatedStorage: ‘5’
DBInstanceClass: db.t3.micro
DBInstanceIdentifier: !Sub ${SystemName}db
DBSubnetGroupName: !Ref dbSubnetGroup
DBParameterGroupName: !Ref paramGroup
Engine: MySQL
EngineVersion: 8.0.16
MasterUsername: MasterUser
MasterUserPassword: ‘{{resolve:ssm-secure:DBPassword:1}}’
MultiAZ: true
VPCSecurityGroups:
– Fn::ImportValue: !Sub ${SystemName}-db-sg
# ————————————————————#
# Outputs
# ————————————————————#
Outputs:
paramGroup:
Value: !Ref paramGroup
Export:
Name: !Sub ${SystemName}-db-parametergroup
dbSubnetGroup:
Value: !Ref dbSubnetGroup
Export:
Name: !Sub ${SystemName}-db-subnetgroup
db:
Value: !Ref db
Export:
Name: !Sub ${SystemName}-db
dbUser:
Value: MasterUser
Export:
Name: !Sub ${SystemName}-db-user
dbEndpoint:
Value: !GetAtt db.Endpoint.Address
Export:
Name: !Sub ${SystemName}-db-endpoint
dbPort:
Value: !GetAtt db.Endpoint.Port
Export:
Name: !Sub ${SystemName}-db-port
ECS作成
AWSコマンド
aws cloudformation deploy
--stack-name handson-ecs-cluster
--template-file template/ecs-cluster.yml
--no-execute-changeset
--parameter-overrides
SystemName=handson
ecs-cluster.yml
AWSTemplateFormatVersion: ‘2010-09-09’
Description: ECS Cluster
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------#
Parameters:
SystemName:
Type: String
Description: Your System Name.
Resources:
# ------------------------------------------------------------#
# ECS Cluster
# ------------------------------------------------------------#
ecsCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Sub ${SystemName}-cluster
ClusterSettings:
- Name: containerInsights
Value: enabled
logGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /${SystemName}-loggroup
# ------------------------------------------------------------#
# Outputs
# ------------------------------------------------------------#
Outputs:
ecsCluster:
Value: !Ref ecsCluster
Export:
Name: !Sub ${SystemName}-cluster
logGroup:
Value: !Ref logGroup
Export:
Name: !Sub ${SystemName}-loggroup
phpMyAdminコンテナ作成
AWSコマンド
aws cloudformation deploy
--stack-name handson-admin-alb-fargate
--template-file template/admin-alb-fargate.yml
--no-execute-changeset
--capabilities CAPABILITY_IAM
--parameter-overrides
SystemName=handson
admin-alb-fargate.yml
---
AWSTemplateFormatVersion: ‘2010-09-09’
Description: Admin alb fargate
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------#
Parameters:
SystemName:
Type: String
Description: Your System Name.
Resources:
# ------------------------------------------------------------#
# ALB
# ------------------------------------------------------------#
adminALB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub ${SystemName}-admin-alb
Scheme: internet-facing
Type: application
IpAddressType: ipv4
Subnets:
- Fn::ImportValue:
!Sub ${SystemName}-PublicSubnet1a
- Fn::ImportValue:
!Sub ${SystemName}-PublicSubnet1c
SecurityGroups:
- Fn::ImportValue:
!Sub ${SystemName}-admin-alb-sg
adminAlbTg:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub ${SystemName}-admin-alb-tg
Protocol: HTTP
Port: 80
TargetType: ip
VpcId:
Fn::ImportValue:
!Sub ${SystemName}-VPC
HealthCheckProtocol: HTTP
HealthCheckPath: /
HealthCheckPort: traffic-port
HealthyThresholdCount: 5
UnhealthyThresholdCount: 2
HealthCheckTimeoutSeconds: 5
HealthCheckIntervalSeconds: 30
Matcher:
HttpCode: 200
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: 30
adminListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref adminALB
Protocol: HTTP
Port: 80
DefaultActions:
- Type: forward
TargetGroupArn: !Ref adminAlbTg
# ------------------------------------------------------------#
# ECS Task
# ------------------------------------------------------------#
adminTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
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
- arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess
adminTask:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Sub ${SystemName}-admin-task
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
TaskRoleArn: !Ref adminTaskExecutionRole
ExecutionRoleArn: !Ref adminTaskExecutionRole
Cpu: 256
Memory: 512
ContainerDefinitions:
- Name: phpmyadmin
Image: phpmyadmin/phpmyadmin:latest
PortMappings:
- Protocol: tcp
HostPort: 80
ContainerPort: 80
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group:
Fn::ImportValue:
!Sub ${SystemName}-loggroup
awslogs-region: !Sub “${AWS::Region}”
awslogs-stream-prefix: adminTask
Environment:
- Name: PMA_HOST
Value:
Fn::ImportValue: !Sub ${SystemName}-db-endpoint
- Name: PMA_PORT
Value:
Fn::ImportValue: !Sub ${SystemName}-db-port
# ------------------------------------------------------------#
# ECS Service
# ------------------------------------------------------------#
adminService:
Type: AWS::ECS::Service
DependsOn: adminALB
Properties:
ServiceName: !Sub ${SystemName}-admin-service
LaunchType: FARGATE
Cluster:
Fn::ImportValue:
!Sub ${SystemName}-cluster
TaskDefinition: !Ref adminTask
DesiredCount: 1
DeploymentConfiguration:
MinimumHealthyPercent: 50
MaximumPercent: 200
LoadBalancers:
- TargetGroupArn: !Ref adminAlbTg
ContainerName: phpmyadmin
ContainerPort: 80
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: DISABLED
SecurityGroups:
- Fn::ImportValue:
!Sub ${SystemName}-admin-fargate-sg
Subnets:
- Fn::ImportValue:
!Sub ${SystemName}-PrivateSubnet1a
- Fn::ImportValue:
!Sub ${SystemName}-PrivateSubnet1c
# ------------------------------------------------------------#
# Outputs
# ------------------------------------------------------------#
Outputs:
adminALB:
Value: !Ref adminALB
Export:
Name: !Sub ${SystemName}-admin-alb
adminALBUrl:
Value:
Fn::Join:
- “”
- - http://
- Fn::GetAtt: adminALB.DNSName
- /
Export:
Name: !Sub ${SystemName}-admin-alb-url
adminAlbTg:
Value: !Ref adminAlbTg
Export:
Name: !Sub ${SystemName}-admin-alb-tg
adminTask:
Value: !Ref adminTask
Export:
Name: !Sub ${SystemName}-admin-task
adminService:
Value: !Ref adminService
Export:
Name: !Sub ${SystemName}-admin-service
phpアプリ作成
ECRへのpush
AWS接続
aws ecr get-login-password
--region us-east-1 | docker login
--username AWS
--password-stdin 999999999999.dkr.ecr.us-east-1.amazonaws.com
localアプリビルド
docker build -t handson-ecr-php-app .
localアプリタグ設定
docker tag handson-ecr-php-app:latest 999999999999.dkr.ecr.us-east-1.amazonaws.com/handson-ecr-php-app:latest
push
docker push 999999999999.dkr.ecr.us-east-1.amazonaws.com/handson-ecr-php-app:latest
AWSコマンド
aws cloudformation deploy
--stack-name handson-app-alb-fargate
--template-file template/app-alb-fargate.yml
--no-execute-changeset
--capabilities CAPABILITY_IAM
--parameter-overrides
SystemName=handson
ImageUri=999999999999.dkr.ecr.ap-northeast-1.amazonaws.com/handson-ecr-php-app
app-alb-fargate.yml
AWSTemplateFormatVersion: ‘2010-09-09’
Description: App alb fargate
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------#
Parameters:
SystemName:
Type: String
Description: Your System Name.
ImageUri:
Type: String
Description: Application Image URI
Resources:
# ------------------------------------------------------------#
# ALB
# ------------------------------------------------------------#
appALB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub ${SystemName}-app-alb
Scheme: internet-facing
Type: application
IpAddressType: ipv4
Subnets:
- Fn::ImportValue:
!Sub ${SystemName}-PublicSubnet1a
- Fn::ImportValue:
!Sub ${SystemName}-PublicSubnet1c
SecurityGroups:
- Fn::ImportValue:
!Sub ${SystemName}-app-alb-sg
appAlbTg:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub ${SystemName}-app-alb-tg
Protocol: HTTP
Port: 80
TargetType: ip
VpcId:
Fn::ImportValue:
!Sub ${SystemName}-VPC
HealthCheckProtocol: HTTP
HealthCheckPath: /
HealthCheckPort: traffic-port
HealthyThresholdCount: 5
UnhealthyThresholdCount: 2
HealthCheckTimeoutSeconds: 5
HealthCheckIntervalSeconds: 30
Matcher:
HttpCode: 200
TargetGroupAttributes:
- Key: deregistration_delay.timeout_seconds
Value: 30
appListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref appALB
Protocol: HTTP
Port: 80
DefaultActions:
- Type: forward
TargetGroupArn: !Ref appAlbTg
# ------------------------------------------------------------#
# ECS Task
# ------------------------------------------------------------#
appTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
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
- arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess
appTask:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Sub ${SystemName}-app-task
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
TaskRoleArn: !Ref appTaskExecutionRole
ExecutionRoleArn: !Ref appTaskExecutionRole
Cpu: 256
Memory: 512
ContainerDefinitions:
- Name: app
Image: !Ref ImageUri
PortMappings:
- Protocol: tcp
HostPort: 80
ContainerPort: 80
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group:
Fn::ImportValue:
!Sub ${SystemName}-loggroup
awslogs-region: !Sub “${AWS::Region}”
awslogs-stream-prefix: appTask
Environment:
- Name: DBHOST
Value:
Fn::ImportValue: !Sub ${SystemName}-db-endpoint
- Name: DB
Value:
Fn::ImportValue: !Sub ${SystemName}-db
- Name: DBUSER
Value:
Fn::ImportValue: !Sub ${SystemName}-db-user
Secrets:
- Name: DBPASSWORD
ValueFrom: !Sub ${SystemName}-DBPassword
# ------------------------------------------------------------#
# ECS Service
# ------------------------------------------------------------#
appService:
Type: AWS::ECS::Service
DependsOn: appALB
Properties:
ServiceName: !Sub ${SystemName}-app-service
LaunchType: FARGATE
Cluster:
Fn::ImportValue:
!Sub ${SystemName}-cluster
TaskDefinition: !Ref appTask
DesiredCount: 2
DeploymentConfiguration:
MinimumHealthyPercent: 50
MaximumPercent: 200
LoadBalancers:
- TargetGroupArn: !Ref appAlbTg
ContainerName: app
ContainerPort: 80
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: DISABLED
SecurityGroups:
- Fn::ImportValue:
!Sub ${SystemName}-app-fargate-sg
Subnets:
- Fn::ImportValue:
!Sub ${SystemName}-PrivateSubnet1a
- Fn::ImportValue:
!Sub ${SystemName}-PrivateSubnet1c
# ------------------------------------------------------------#
# Outputs
# ------------------------------------------------------------#
Outputs:
appALB:
Value: !Ref appALB
Export:
Name: !Sub ${SystemName}-app-alb
appALBUrl:
Value:
Fn::Join:
- “”
- - http://
- Fn::GetAtt: appALB.DNSName
- /
Export:
Name: !Sub ${SystemName}-app-alb-url
appAlbTg:
Value: !Ref appAlbTg
Export:
Name: !Sub ${SystemName}-app-alb-tg
appTask:
Value: !Ref appTask
Export:
Name: !Sub ${SystemName}-app-task
appService:
Value: !Ref appService
Export:
Name: !Sub ${SystemName}-app-service
PipeLine作成
AWSコマンド
aws cloudformation deploy
--stack-name handson-app-codepipeline
--template-file template/app-codepipeline.yml
--no-execute-changeset
--capabilities CAPABILITY_IAM
--parameter-overrides
SystemName=handson
app-codepipeline.yml
Description: CodePipeline For ECS Fargate with CodeCommit
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------#
Parameters:
SystemName:
Type: String
Description: Your System Name.
Resources:
# ------------------------------------------------------------#
# IAM
# ------------------------------------------------------------#
#-- CodeBuild用Role --#
appCodeBuildServiceRole:
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument:
Version: “2012-10-17”
Statement:
- Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess
- arn:aws:iam::aws:policy/AmazonS3FullAccess
- arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
#-- CodePipeline用Role --#
appCodePipelineServiceRole:
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: codepipeline.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: PipelinePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Resource:
- !Sub arn:aws:s3:::${ArtifactBucket}/*
Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
- s3:GetObjectVersion
- s3:GetBucketVersioning
- Resource: “*”
Effect: Allow
Action:
- codecommit:GetRepository
- codecommit:ListBranches
- codecommit:GetUploadArchiveStatus
- codecommit:UploadArchive
- codecommit:CancelUploadArchive
- codedeploy:CreateDeployment
- codedeploy:GetApplication
- codedeploy:GetApplicationRevision
- codedeploy:GetDeployment
- codedeploy:GetDeploymentConfig
- codedeploy:RegisterApplicationRevision
- codebuild:StartBuild
- codebuild:StopBuild
- codebuild:BatchGet*
- codebuild:Get*
- codebuild:List*
- codecommit:GetBranch
- codecommit:GetCommit
- s3:*
- ecs:*
- elasticloadbalancing:*
- autoscaling:*
- iam:PassRole
# ------------------------------------------------------------#
# S3
# ------------------------------------------------------------#
#-- アーティファクト用S3バケット --#
ArtifactBucket:
Type: AWS::S3::Bucket
# ------------------------------------------------------------#
# CodeBuild
# ------------------------------------------------------------#
appCodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
Name: !Sub ${SystemName}-app-build-project
Artifacts:
Type: CODEPIPELINE
Description: !Sub Building stage for php app
Environment:
ComputeType: BUILD_GENERAL1_SMALL
EnvironmentVariables:
- Name: AWS_ACCOUNT_ID
Value: !Ref AWS::AccountId
- Name: IMAGE_NAME
Value: !Sub ${SystemName}-ecr-php-app
- Name: CONTAINER_NAME
Value: !Sub app
Image: aws/codebuild/amazonlinux2-x86_64-standard:2.0
Type: LINUX_CONTAINER
PrivilegedMode: True
ServiceRole: !Ref appCodeBuildServiceRole
Source:
Type: CODEPIPELINE
TimeoutInMinutes: 30
# ------------------------------------------------------------#
# CodePipeline
# ------------------------------------------------------------#
#-- CodePipeline起動用CloudWatchEvents --#
appCloudWatchEventRole:
Type: ‘AWS::IAM::Role’
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- events.amazonaws.com
Action: ‘sts:AssumeRole’
Path: /
Policies:
- PolicyName: cwe-pipeline-execution
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: ‘codepipeline:StartPipelineExecution’
Resource: !Join
- ”
- - ‘arn:aws:codepipeline:’
- !Ref ‘AWS::Region’
- ‘:’
- !Ref ‘AWS::AccountId’
- ‘:’
- !Ref appCodePipeline
#-- CodePipeline起動用CloudWatchEvents --#
appCloudwatchEventsRule:
Type: AWS::Events::Rule
Properties:
EventPattern:
source:
- aws.codecommit
detail-type:
- CodeCommit Repository State Change
resources:
- Fn::ImportValue: !Sub ${SystemName}-codecommit-php-app-arn
detail:
event:
- referenceCreated
- referenceUpdated
referenceType:
- branch
referenceName:
- master
Targets:
- Arn: !Join
- ”
- - ‘arn:aws:codepipeline:’
- !Ref ‘AWS::Region’
- ‘:’
- !Ref ‘AWS::AccountId’
- ‘:’
- !Ref appCodePipeline
Id: !Sub ${SystemName}-app-codepipeline
RoleArn: !GetAtt appCloudWatchEventRole.Arn
#-- CodePipeline --#
appCodePipeline:
Type: AWS::CodePipeline::Pipeline
DependsOn: ArtifactBucket
Properties:
ArtifactStore:
Location: !Ref ArtifactBucket
Type: S3
Name: !Sub ${SystemName}-app-codepipeline
RestartExecutionOnUpdate: false
RoleArn: !GetAtt appCodePipelineServiceRole.Arn
Stages:
- Name: Source
Actions:
- Name: SourceAction
ActionTypeId:
Category: Source
Owner: AWS
Provider: CodeCommit
Version: 1
OutputArtifacts:
- Name: SourceOutput
Configuration:
RepositoryName:
Fn::ImportValue: !Sub ${SystemName}-codecommit-php-app-name
BranchName: master
PollForSourceChanges: false
RunOrder: 1
- Name: Build
Actions:
- Name: CodeBuild
InputArtifacts:
- Name: SourceOutput
ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: 1
Configuration:
ProjectName: !Ref appCodeBuildProject
OutputArtifacts:
- Name: CodebuildOutput
RunOrder: 1
- Name: Deploy
Actions:
- Name: appDeploy
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: ECS
Configuration:
ClusterName:
Fn::ImportValue: !Sub ${SystemName}-cluster
ServiceName:
Fn::ImportValue: !Sub ${SystemName}-app-service
FileName: imagedefinitions.json
RunOrder: 1
InputArtifacts:
- Name: CodebuildOutput
# ------------------------------------------------------------#
# Outputs
# ------------------------------------------------------------#
Outputs:
ArtifactBucket:
Value: !Ref ArtifactBucket
Export:
Name: !Sub ${SystemName}-ArtifactBucket