本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
了解如何將 AWS CloudFormation 基礎結構當做程式碼檔案使用 AWS Proton。 AWS CloudFormation 是一種基礎結構即程式碼 (IaC) 服務,可協助您建立 AWS 資源的模型和設定。您可以在範本中定義基礎結構資源,並在範本檔案格式之上 CloudFormation 使用 Jinja 進行參數化。 AWS Proton 展開參數並呈現完整的 CloudFormation 模板。 CloudFormation 將定義的資源規定為 CloudFormation 堆棧。若要取得更多資訊,請參閱《 AWS CloudFormation 使用指南》 AWS CloudFormation中的「內容」。
AWS Proton 支援 CloudFormation I AWS aC 的管理佈建。
從您自己的現有基礎結構作為代碼文件開始
您可以將自己現有的基礎結構調整為程式碼 (IaC) 檔案,以便搭配 AWS Proton使用。
下列 AWS CloudFormation 範例 [範例 1] 和 [範例 2] 代表您自己現有的 CloudFormation IaC 檔案。 CloudFormation 可以使用這些文件創建兩個不同的 CloudFormation堆棧。
在範例 1 中, CloudFormation IaC 檔案會設定為佈建要在容器應用程式之間共用的基礎結構。在此範例中,會新增輸入參數,以便您可以使用相同的 IaC 檔案來建立多組佈建的基礎結構。每個集合可以有不同的名稱以及一組不同的 VPC 和子網路 CIDR 值。身為系統管理員或開發人員,您可以在使用 IaC 檔案佈建基礎結構資源時,提供這些參數的 CloudFormation值。為了您的方便起見,這些輸入參數標有註釋,並在示例中多次引用。輸出在模板的末尾定義。它們可以在其他 CloudFormation IaC 文件中引用。
在範例 2 中, CloudFormation IaC 檔案會設定為將應用程式部署至範例 1 所佈建的基礎結構。為了您的方便起見,這些參數被評論。
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS Fargate cluster running containers in a public subnet. Only supports
public facing load balancer, and public service discovery namespaces.
Parameters:
VpcCIDR: # input parameter
Description: CIDR for VPC
Type: String
Default: "10.0.0.0/16"
SubnetOneCIDR: # input parameter
Description: CIDR for SubnetOne
Type: String
Default: "10.0.0.0/24"
SubnetTwoCIDR: # input parameters
Description: CIDR for SubnetTwo
Type: String
Default: "10.0.1.0/24"
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
EnableDnsSupport: true
EnableDnsHostnames: true
CidrBlock:
Ref: 'VpcCIDR'
# Two public subnets, where containers will have public IP addresses
PublicSubnetOne:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone:
Fn::Select:
- 0
- Fn::GetAZs: {Ref: 'AWS::Region'}
VpcId: !Ref 'VPC'
CidrBlock:
Ref: 'SubnetOneCIDR'
MapPublicIpOnLaunch: true
PublicSubnetTwo:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone:
Fn::Select:
- 1
- Fn::GetAZs: {Ref: 'AWS::Region'}
VpcId: !Ref 'VPC'
CidrBlock:
Ref: 'SubnetTwoCIDR'
MapPublicIpOnLaunch: true
# Setup networking resources for the public subnets. Containers
# in the public subnets have public IP addresses and the routing table
# sends network traffic via the internet gateway.
InternetGateway:
Type: AWS::EC2::InternetGateway
GatewayAttachement:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref 'VPC'
InternetGatewayId: !Ref 'InternetGateway'
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref 'VPC'
PublicRoute:
Type: AWS::EC2::Route
DependsOn: GatewayAttachement
Properties:
RouteTableId: !Ref 'PublicRouteTable'
DestinationCidrBlock: '0.0.0.0/0'
GatewayId: !Ref 'InternetGateway'
PublicSubnetOneRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetOne
RouteTableId: !Ref PublicRouteTable
PublicSubnetTwoRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetTwo
RouteTableId: !Ref PublicRouteTable
# ECS Resources
ECSCluster:
Type: AWS::ECS::Cluster
# A security group for the containers we will run in Fargate.
# Rules are added to this security group based on what ingress you
# add for the cluster.
ContainerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Access to the Fargate containers
VpcId: !Ref 'VPC'
# This is a role which is used by the ECS tasks themselves.
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ecs-tasks.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy'
# These output values will be available to other templates to use.
Outputs:
ClusterName: # output
Description: The name of the ECS cluster
Value: !Ref 'ECSCluster'
Export:
Name:
Fn::Sub: "${AWS::StackName}-ECSCluster"
ECSTaskExecutionRole: # output
Description: The ARN of the ECS role
Value: !GetAtt 'ECSTaskExecutionRole.Arn'
Export:
Name:
Fn::Sub: "${AWS::StackName}-ECSTaskExecutionRole"
VpcId: # output
Description: The ID of the VPC that this stack is deployed in
Value: !Ref 'VPC'
Export:
Name:
Fn::Sub: "${AWS::StackName}-VPC"
PublicSubnetOne: # output
Description: Public subnet one
Value: !Ref 'PublicSubnetOne'
Export:
Name:
Fn::Sub: "${AWS::StackName}-PublicSubnetOne"
PublicSubnetTwo: # output
Description: Public subnet two
Value: !Ref 'PublicSubnetTwo'
Export:
Name:
Fn::Sub: "${AWS::StackName}-PublicSubnetTwo"
ContainerSecurityGroup: # output
Description: A security group used to allow Fargate containers to receive traffic
Value: !Ref 'ContainerSecurityGroup'
Export:
Name:
Fn::Sub: "${AWS::StackName}-ContainerSecurityGroup"
AWSTemplateFormatVersion: '2010-09-09'
Description: Deploy a service on AWS Fargate, hosted in a public subnet, and accessible via a public load balancer.
Parameters:
ContainerPortInput: # input parameter
Description: The port to route traffic to
Type: Number
Default: 80
TaskCountInput: # input parameter
Description: The default number of Fargate tasks you want running
Type: Number
Default: 1
TaskSizeInput: # input parameter
Description: The size of the task you want to run
Type: String
Default: x-small
ContainerImageInput: # input parameter
Description: The name/url of the container image
Type: String
Default: "public.ecr.aws/z9d2n7e1/nginx:1.19.5"
TaskNameInput: # input parameter
Description: Name for your task
Type: String
Default: "my-fargate-instance"
StackName: # input parameter
Description: Name of the environment stack to deploy to
Type: String
Default: "my-fargate-environment"
Mappings:
TaskSizeMap:
x-small:
cpu: 256
memory: 512
small:
cpu: 512
memory: 1024
medium:
cpu: 1024
memory: 2048
large:
cpu: 2048
memory: 4096
x-large:
cpu: 4096
memory: 8192
Resources:
# A log group for storing the stdout logs from this service's containers
LogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName:
Ref: 'TaskNameInput' # input parameter
# The task definition. This is a simple metadata description of what
# container to run, and what resource requirements it has.
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Ref 'TaskNameInput'
Cpu: !FindInMap [TaskSizeMap, !Ref 'TaskSizeInput', cpu]
Memory: !FindInMap [TaskSizeMap, !Ref 'TaskSizeInput', memory]
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
ExecutionRoleArn:
Fn::ImportValue:
!Sub "${StackName}-ECSTaskExecutionRole" # output parameter from another CloudFormation template
awslogs-region: !Ref 'AWS::Region'
awslogs-stream-prefix: !Ref 'TaskNameInput'
# The service_instance. The service is a resource which allows you to run multiple
# copies of a type of task, and gather up their logs and metrics, as well
# as monitor the number of running tasks and replace any that have crashed
Service:
Type: AWS::ECS::Service
DependsOn: LoadBalancerRule
Properties:
ServiceName: !Ref 'TaskNameInput'
Cluster:
Fn::ImportValue:
!Sub "${StackName}-ECSCluster" # output parameter from another CloudFormation template
LaunchType: FARGATE
DeploymentConfiguration:
MaximumPercent: 200
MinimumHealthyPercent: 75
DesiredCount: !Ref 'TaskCountInput'
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- Fn::ImportValue:
!Sub "${StackName}-ContainerSecurityGroup" # output parameter from another CloudFormation template
Subnets:
- Fn::ImportValue:r CloudFormation template
TaskRoleArn: !Ref "AWS::NoValue"
ContainerDefinitions:
- Name: !Ref 'TaskNameInput'
Cpu: !FindInMap [TaskSizeMap, !Ref 'TaskSizeInput', cpu]
Memory: !FindInMap [TaskSizeMap, !Ref 'TaskSizeInput', memory]
Image: !Ref 'ContainerImageInput' # input parameter
PortMappings:
- ContainerPort: !Ref 'ContainerPortInput' # input parameter
LogConfiguration:
LogDriver: 'awslogs'
Options:
awslogs-group: !Ref 'TaskNameInput'
!Sub "${StackName}-PublicSubnetOne" # output parameter from another CloudFormation template
- Fn::ImportValue:
!Sub "${StackName}-PublicSubnetTwo" # output parameter from another CloudFormation template
TaskDefinition: !Ref 'TaskDefinition'
LoadBalancers:
- ContainerName: !Ref 'TaskNameInput'
ContainerPort: !Ref 'ContainerPortInput' # input parameter
TargetGroupArn: !Ref 'TargetGroup'
# A target group. This is used for keeping track of all the tasks, and
# what IP addresses / port numbers they have. You can query it yourself,
# to use the addresses yourself, but most often this target group is just
# connected to an application load balancer, or network load balancer, so
# it can automatically distribute traffic across all the targets.
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckIntervalSeconds: 6
HealthCheckPath: /
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2
TargetType: ip
Name: !Ref 'TaskNameInput'
Port: !Ref 'ContainerPortInput'
Protocol: HTTP
UnhealthyThresholdCount: 2
VpcId:
Fn::ImportValue:
!Sub "${StackName}-VPC" # output parameter from another CloudFormation template
# Create a rule on the load balancer for routing traffic to the target group
LoadBalancerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- TargetGroupArn: !Ref 'TargetGroup'
Type: 'forward'
Conditions:
- Field: path-pattern
Values:
- '*'
ListenerArn: !Ref PublicLoadBalancerListener
Priority: 1
# Enable autoscaling for this service
ScalableTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
DependsOn: Service
Properties:
ServiceNamespace: 'ecs'
ScalableDimension: 'ecs:service:DesiredCount'
ResourceId:
Fn::Join:
- '/'
- - service
- Fn::ImportValue:
!Sub "${StackName}-ECSCluster"
- !Ref 'TaskNameInput'
MinCapacity: 1
MaxCapacity: 10
RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService
# Create scaling policies for the service
ScaleDownPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
DependsOn: ScalableTarget
Properties:
PolicyName:
Fn::Join:
- '/'
- - scale
- !Ref 'TaskNameInput'
- down
PolicyType: StepScaling
ResourceId:
Fn::Join:
- '/'
- - service
- Fn::ImportValue:
!Sub "${StackName}-ECSCluster" # output parameter from another CloudFormation template
- !Ref 'TaskNameInput'
ScalableDimension: 'ecs:service:DesiredCount'
ServiceNamespace: 'ecs'
StepScalingPolicyConfiguration:
AdjustmentType: 'ChangeInCapacity'
StepAdjustments:
- MetricIntervalUpperBound: 0
ScalingAdjustment: -1
MetricAggregationType: 'Average'
Cooldown: 60
ScaleUpPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
DependsOn: ScalableTarget
Properties:
PolicyName:
Fn::Join:
- '/'
- - scale
- !Ref 'TaskNameInput'
- up
PolicyType: StepScaling
ResourceId:
Fn::Join:
- '/'
- - service
- Fn::ImportValue:
!Sub "${StackName}-ECSCluster"
- !Ref 'TaskNameInput'
ScalableDimension: 'ecs:service:DesiredCount'
ServiceNamespace: 'ecs'
StepScalingPolicyConfiguration:
AdjustmentType: 'ChangeInCapacity'
StepAdjustments:
- MetricIntervalLowerBound: 0
MetricIntervalUpperBound: 15
ScalingAdjustment: 1
- MetricIntervalLowerBound: 15
MetricIntervalUpperBound: 25
ScalingAdjustment: 2
- MetricIntervalLowerBound: 25
ScalingAdjustment: 3
MetricAggregationType: 'Average'
Cooldown: 60
# Create alarms to trigger these policies
LowCpuUsageAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName:
Fn::Join:
- '-'
- - low-cpu
- !Ref 'TaskNameInput'
AlarmDescription:
Fn::Join:
- ' '
- - "Low CPU utilization for service"
- !Ref 'TaskNameInput'
MetricName: CPUUtilization
Namespace: AWS/ECS
Dimensions:
- Name: ServiceName
Value: !Ref 'TaskNameInput'
- Name: ClusterName
Value:
Fn::ImportValue:
!Sub "${StackName}-ECSCluster"
Statistic: Average
Period: 60
EvaluationPeriods: 1
Threshold: 20
ComparisonOperator: LessThanOrEqualToThreshold
AlarmActions:
- !Ref ScaleDownPolicy
HighCpuUsageAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName:
Fn::Join:
- '-'
- - high-cpu
- !Ref 'TaskNameInput'
AlarmDescription:
Fn::Join:
- ' '
- - "High CPU utilization for service"
- !Ref 'TaskNameInput'
MetricName: CPUUtilization
Namespace: AWS/ECS
Dimensions:
- Name: ServiceName
Value: !Ref 'TaskNameInput'
- Name: ClusterName
Value:
Fn::ImportValue:
!Sub "${StackName}-ECSCluster"
Statistic: Average
Period: 60
EvaluationPeriods: 1
Threshold: 70
ComparisonOperator: GreaterThanOrEqualToThreshold
AlarmActions:
- !Ref ScaleUpPolicy
EcsSecurityGroupIngressFromPublicALB:
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: Ingress from the public ALB
GroupId:
Fn::ImportValue:
!Sub "${StackName}-ContainerSecurityGroup"
IpProtocol: -1
SourceSecurityGroupId: !Ref 'PublicLoadBalancerSG'
# Public load balancer, hosted in public subnets that is accessible
# to the public, and is intended to route traffic to one or more public
# facing services. This is used for accepting traffic from the public
# internet and directing it to public facing microservices
PublicLoadBalancerSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Access to the public facing load balancer
VpcId:
Fn::ImportValue:
!Sub "${StackName}-VPC"
SecurityGroupIngress:
# Allow access to ALB from anywhere on the internet
- CidrIp: 0.0.0.0/0
IpProtocol: -1
PublicLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Scheme: internet-facing
LoadBalancerAttributes:
- Key: idle_timeout.timeout_seconds
Value: '30'
Subnets:
# The load balancer is placed into the public subnets, so that traffic
# from the internet can reach the load balancer directly via the internet gateway
- Fn::ImportValue:
!Sub "${StackName}-PublicSubnetOne"
- Fn::ImportValue:
!Sub "${StackName}-PublicSubnetTwo"
SecurityGroups: [!Ref 'PublicLoadBalancerSG']
PublicLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
DependsOn:
- PublicLoadBalancer
Properties:
DefaultActions:
- TargetGroupArn: !Ref 'TargetGroup'
Type: 'forward'
LoadBalancerArn: !Ref 'PublicLoadBalancer'
Port: 80
Protocol: HTTP
# These output values will be available to other templates to use.
Outputs:
ServiceEndpoint: # output
Description: The URL to access the service
Value: !Sub "http://${PublicLoadBalancer.DNSName}"
您可以調整這些檔案以配合使用 AWS Proton。
將您的基礎架構即程式碼帶入 AWS Proton
只要稍作修改,您就可以使用範例 1 做為基礎結構即程式碼 (IaC) 檔案,以供 AWS Proton 用來部署環境的環境範本套裝軟體 (如範例 3 所示)。
您可以使用 Jinja
身為管理員,您可以將 AWS Proton environment.inputs.
命名空間新增至輸入參數。當您在服務 IaC 檔案中參考環境 IaC 檔案輸出時,您可以將environment.outputs.
命名空間新增至輸出 (例如,environment.outputs.ClusterName
)。最後,你用花括號和引號圍住它們。
通過這些修改,您的 CloudFormation IaC 文件可以被 AWS Proton使用。
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS Fargate cluster running containers in a public subnet. Only supports
public facing load balancer, and public service discovery prefixes.
Mappings:
# The VPC and subnet configuration is passed in via the environment spec.
SubnetConfig:
VPC:
CIDR: '{{ environment.inputs.vpc_cidr}}' # input parameter
PublicOne:
CIDR: '{{ environment.inputs.subnet_one_cidr}}' # input parameter
PublicTwo:
CIDR: '{{ environment.inputs.subnet_two_cidr}}' # input parameter
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
EnableDnsSupport: true
EnableDnsHostnames: true
CidrBlock: !FindInMap ['SubnetConfig', 'VPC', 'CIDR']
# Two public subnets, where containers will have public IP addresses
PublicSubnetOne:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone:
Fn::Select:
- 0
- Fn::GetAZs: {Ref: 'AWS::Region'}
VpcId: !Ref 'VPC'
CidrBlock: !FindInMap ['SubnetConfig', 'PublicOne', 'CIDR']
MapPublicIpOnLaunch: true
PublicSubnetTwo:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone:
Fn::Select:
- 1
- Fn::GetAZs: {Ref: 'AWS::Region'}
VpcId: !Ref 'VPC'
CidrBlock: !FindInMap ['SubnetConfig', 'PublicTwo', 'CIDR']
MapPublicIpOnLaunch: true
# Setup networking resources for the public subnets. Containers
# in the public subnets have public IP addresses and the routing table
# sends network traffic via the internet gateway.
InternetGateway:
Type: AWS::EC2::InternetGateway
GatewayAttachement:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref 'VPC'
InternetGatewayId: !Ref 'InternetGateway'
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref 'VPC'
PublicRoute:
Type: AWS::EC2::Route
DependsOn: GatewayAttachement
Properties:
RouteTableId: !Ref 'PublicRouteTable'
DestinationCidrBlock: '0.0.0.0/0'
GatewayId: !Ref 'InternetGateway'
PublicSubnetOneRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetOne
RouteTableId: !Ref PublicRouteTable
PublicSubnetTwoRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetTwo
RouteTableId: !Ref PublicRouteTable
# ECS Resources
ECSCluster:
Type: AWS::ECS::Cluster
# A security group for the containers we will run in Fargate.
# Rules are added to this security group based on what ingress you
# add for the cluster.
ContainerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Access to the Fargate containers
VpcId: !Ref 'VPC'
# This is a role which is used by the ECS tasks themselves.
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ecs-tasks.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy'
# These output values are available to service infrastructure as code files as outputs, when given the
# the 'service_instance.environment.outputs.' namespace, for example, service_instance.environment.outputs.ClusterName.
Outputs:
ClusterName: # output
Description: The name of the ECS cluster
Value: !Ref 'ECSCluster'
ECSTaskExecutionRole: # output
Description: The ARN of the ECS role
Value: !GetAtt 'ECSTaskExecutionRole.Arn'
VpcId: # output
Description: The ID of the VPC that this stack is deployed in
Value: !Ref 'VPC'
PublicSubnetOne: # output
Description: Public subnet one
Value: !Ref 'PublicSubnetOne'
PublicSubnetTwo: # output
Description: Public subnet two
Value: !Ref 'PublicSubnetTwo'
ContainerSecurityGroup: # output
Description: A security group used to allow Fargate containers to receive traffic
Value: !Ref 'ContainerSecurityGroup'
範例 1 和範例 3 中的 IaC 檔案會產生稍微不同的 CloudFormation 堆疊。參數在堆疊範本檔案中的顯示方式不同。範例 1 CloudFormation 堆疊樣板檔案會在堆疊樣板視圖中顯示參數標示 (關鍵字)。範例 3 AWS Proton CloudFormation 基礎結構堆疊範本檔案會顯示參數值。 AWS Proton 輸入參數不會出現在控制台 CloudFormation堆棧參數視圖中。
在範例 4 中, AWS Proton 服務 IaC 檔案對應於範例 2。
AWSTemplateFormatVersion: '2010-09-09'
Description: Deploy a service on AWS Fargate, hosted in a public subnet, and accessible via a public load balancer.
Mappings:
TaskSize:
x-small:
cpu: 256
memory: 512
small:
cpu: 512
memory: 1024
medium:
cpu: 1024
memory: 2048
large:
cpu: 2048
memory: 4096
x-large:
cpu: 4096
memory: 8192
Resources:
# A log group for storing the stdout logs from this service's containers
LogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: '{{service_instance.name}}' # resource parameter
# The task definition. This is a simple metadata description of what
# container to run, and what resource requirements it has.
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: '{{service_instance.name}}'
Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu] # input parameter
Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory]
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
ExecutionRoleArn: '{{environment.outputs.ECSTaskExecutionRole}}' # output from an environment infrastructure as code file
TaskRoleArn: !Ref "AWS::NoValue"
ContainerDefinitions:
- Name: '{{service_instance.name}}'
Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu]
Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory]
Image: '{{service_instance.inputs.image}}'
PortMappings:
- ContainerPort: '{{service_instance.inputs.port}}' # input parameter
LogConfiguration:
LogDriver: 'awslogs'
Options:
awslogs-group: '{{service_instance.name}}'
awslogs-region: !Ref 'AWS::Region'
awslogs-stream-prefix: '{{service_instance.name}}'
# The service_instance. The service is a resource which allows you to run multiple
# copies of a type of task, and gather up their logs and metrics, as well
# as monitor the number of running tasks and replace any that have crashed
Service:
Type: AWS::ECS::Service
DependsOn: LoadBalancerRule
Properties:
ServiceName: '{{service_instance.name}}'
Cluster: '{{environment.outputs.ClusterName}}' # output from an environment infrastructure as code file
LaunchType: FARGATE
DeploymentConfiguration:
MaximumPercent: 200
MinimumHealthyPercent: 75
DesiredCount: '{{service_instance.inputs.desired_count}}' # input parameter
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- '{{environment.outputs.ContainerSecurityGroup}}' # output from an environment infrastructure as code file
Subnets:
- '{{environment.outputs.PublicSubnetOne}}' # output from an environment infrastructure as code file
- '{{environment.outputs.PublicSubnetTwo}}'
TaskDefinition: !Ref 'TaskDefinition'
LoadBalancers:
- ContainerName: '{{service_instance.name}}'
ContainerPort: '{{service_instance.inputs.port}}'
TargetGroupArn: !Ref 'TargetGroup'
# A target group. This is used for keeping track of all the tasks, and
# what IP addresses / port numbers they have. You can query it yourself,
# to use the addresses yourself, but most often this target group is just
# connected to an application load balancer, or network load balancer, so
# it can automatically distribute traffic across all the targets.
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckIntervalSeconds: 6
HealthCheckPath: /
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2
TargetType: ip
Name: '{{service_instance.name}}'
Port: '{{service_instance.inputs.port}}'
Protocol: HTTP
UnhealthyThresholdCount: 2
VpcId: '{{environment.outputs.VpcId}}' # output from an environment infrastructure as code file
# Create a rule on the load balancer for routing traffic to the target group
LoadBalancerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- TargetGroupArn: !Ref 'TargetGroup'
Type: 'forward'
Conditions:
- Field: path-pattern
Values:
- '*'
ListenerArn: !Ref PublicLoadBalancerListener
Priority: 1
# Enable autoscaling for this service
ScalableTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
DependsOn: Service
Properties:
ServiceNamespace: 'ecs'
ScalableDimension: 'ecs:service:DesiredCount'
ResourceId:
Fn::Join:
- '/'
- - service
- '{{environment.outputs.ClusterName}}' # output from an environment infrastructure as code file
- '{{service_instance.name}}'
MinCapacity: 1
MaxCapacity: 10
RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService
# Create scaling policies for the service
ScaleDownPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
DependsOn: ScalableTarget
Properties:
PolicyName:
Fn::Join:
- '/'
- - scale
- '{{service_instance.name}}'
- down
PolicyType: StepScaling
ResourceId:
Fn::Join:
- '/'
- - service
- '{{environment.outputs.ClusterName}}'
- '{{service_instance.name}}'
ScalableDimension: 'ecs:service:DesiredCount'
ServiceNamespace: 'ecs'
StepScalingPolicyConfiguration:
AdjustmentType: 'ChangeInCapacity'
StepAdjustments:
- MetricIntervalUpperBound: 0
ScalingAdjustment: -1
MetricAggregationType: 'Average'
Cooldown: 60
ScaleUpPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
DependsOn: ScalableTarget
Properties:
PolicyName:
Fn::Join:
- '/'
- - scale
- '{{service_instance.name}}'
- up
PolicyType: StepScaling
ResourceId:
Fn::Join:
- '/'
- - service
- '{{environment.outputs.ClusterName}}'
- '{{service_instance.name}}'
ScalableDimension: 'ecs:service:DesiredCount'
ServiceNamespace: 'ecs'
StepScalingPolicyConfiguration:
AdjustmentType: 'ChangeInCapacity'
StepAdjustments:
- MetricIntervalLowerBound: 0
MetricIntervalUpperBound: 15
ScalingAdjustment: 1
- MetricIntervalLowerBound: 15
MetricIntervalUpperBound: 25
ScalingAdjustment: 2
- MetricIntervalLowerBound: 25
ScalingAdjustment: 3
MetricAggregationType: 'Average'
Cooldown: 60
# Create alarms to trigger these policies
LowCpuUsageAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName:
Fn::Join:
- '-'
- - low-cpu
- '{{service_instance.name}}'
AlarmDescription:
Fn::Join:
- ' '
- - "Low CPU utilization for service"
- '{{service_instance.name}}'
MetricName: CPUUtilization
Namespace: AWS/ECS
Dimensions:
- Name: ServiceName
Value: '{{service_instance.name}}'
- Name: ClusterName
Value:
'{{environment.outputs.ClusterName}}'
Statistic: Average
Period: 60
EvaluationPeriods: 1
Threshold: 20
ComparisonOperator: LessThanOrEqualToThreshold
AlarmActions:
- !Ref ScaleDownPolicy
HighCpuUsageAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName:
Fn::Join:
- '-'
- - high-cpu
- '{{service_instance.name}}'
AlarmDescription:
Fn::Join:
- ' '
- - "High CPU utilization for service"
- '{{service_instance.name}}'
MetricName: CPUUtilization
Namespace: AWS/ECS
Dimensions:
- Name: ServiceName
Value: '{{service_instance.name}}'
- Name: ClusterName
Value:
'{{environment.outputs.ClusterName}}'
Statistic: Average
Period: 60
EvaluationPeriods: 1
Threshold: 70
ComparisonOperator: GreaterThanOrEqualToThreshold
AlarmActions:
- !Ref ScaleUpPolicy
EcsSecurityGroupIngressFromPublicALB:
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: Ingress from the public ALB
GroupId: '{{environment.outputs.ContainerSecurityGroup}}'
IpProtocol: -1
SourceSecurityGroupId: !Ref 'PublicLoadBalancerSG'
# Public load balancer, hosted in public subnets that is accessible
# to the public, and is intended to route traffic to one or more public
# facing services. This is used for accepting traffic from the public
# internet and directing it to public facing microservices
PublicLoadBalancerSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Access to the public facing load balancer
VpcId: '{{environment.outputs.VpcId}}'
SecurityGroupIngress:
# Allow access to ALB from anywhere on the internet
- CidrIp: 0.0.0.0/0
IpProtocol: -1
PublicLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Scheme: internet-facing
LoadBalancerAttributes:
- Key: idle_timeout.timeout_seconds
Value: '30'
Subnets:
# The load balancer is placed into the public subnets, so that traffic
# from the internet can reach the load balancer directly via the internet gateway
- '{{environment.outputs.PublicSubnetOne}}'
- '{{environment.outputs.PublicSubnetTwo}}'
SecurityGroups: [!Ref 'PublicLoadBalancerSG']
PublicLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
DependsOn:
- PublicLoadBalancer
Properties:
DefaultActions:
- TargetGroupArn: !Ref 'TargetGroup'
Type: 'forward'
LoadBalancerArn: !Ref 'PublicLoadBalancer'
Port: 80
Protocol: HTTP
Outputs:
ServiceEndpoint: # output
Description: The URL to access the service
Value: !Sub "http://${PublicLoadBalancer.DNSName}"
在範例 5 中, AWS Proton 管線 IaC 檔案會佈建管線基礎結構,以支援範例 4 所佈建的服務執行個體。
Resources:
ECRRepo:
Type: AWS::ECR::Repository
DeletionPolicy: Retain
BuildProject:
Type: AWS::CodeBuild::Project
Properties:
Artifacts:
Type: CODEPIPELINE
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0
PrivilegedMode: true
Type: LINUX_CONTAINER
EnvironmentVariables:
- Name: repo_name
Type: PLAINTEXT
Value: !Ref ECRRepo
- Name: service_name
Type: PLAINTEXT
Value: '{{ service.name }}' # resource parameter
ServiceRole:
Fn::GetAtt:
- PublishRole
- Arn
Source:
BuildSpec:
Fn::Join:
- ""
- - >-
{
"version": "0.2",
"phases": {
"install": {
"runtime-versions": {
"docker": 18
},
"commands": [
"pip3 install --upgrade --user awscli",
"echo 'f6bd1536a743ab170b35c94ed4c7c4479763356bd543af5d391122f4af852460 yq_linux_amd64' > yq_linux_amd64.sha",
"wget https://github.com/mikefarah/yq/releases/download/3.4.0/yq_linux_amd64",
"sha256sum -c yq_linux_amd64.sha",
"mv yq_linux_amd64 /usr/bin/yq",
"chmod +x /usr/bin/yq"
]
},
"pre_build": {
"commands": [
"cd $CODEBUILD_SRC_DIR",
"$(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)",
"{{ pipeline.inputs.unit_test_command }}", # input parameter
]
},
"build": {
"commands": [
"IMAGE_REPO_NAME=$repo_name",
"IMAGE_TAG=$CODEBUILD_BUILD_NUMBER",
"IMAGE_ID=
- Ref: AWS::AccountId
- >-
.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG",
"docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG -f {{ pipeline.inputs.dockerfile }} .", # input parameter
"docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $IMAGE_ID;",
"docker push $IMAGE_ID"
]
},
"post_build": {
"commands": [
"aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml",
"yq w service.yaml 'instances[*].spec.image' \"$IMAGE_ID\" > rendered_service.yaml"
]
}
},
"artifacts": {
"files": [
"rendered_service.yaml"
]
}
}
Type: CODEPIPELINE
EncryptionKey:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
{% for service_instance in service_instances %}
Deploy{{loop.index}}Project:
Type: AWS::CodeBuild::Project
Properties:
Artifacts:
Type: CODEPIPELINE
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0
PrivilegedMode: false
Type: LINUX_CONTAINER
EnvironmentVariables:
- Name: service_name
Type: PLAINTEXT
Value: '{{service.name}}' # resource parameter
- Name: service_instance_name
Type: PLAINTEXT
Value: '{{service_instance.name}}' # resource parameter
ServiceRole:
Fn::GetAtt:
- DeploymentRole
- Arn
Source:
BuildSpec: >-
{
"version": "0.2",
"phases": {
"build": {
"commands": [
"pip3 install --upgrade --user awscli",
"aws proton --region $AWS_DEFAULT_REGION update-service-instance --deployment-type CURRENT_VERSION --name $service_instance_name --service-name $service_name --spec file://rendered_service.yaml",
"aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name"
]
}
}
}
Type: CODEPIPELINE
EncryptionKey:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
{% endfor %}
# This role is used to build and publish an image to ECR
PublishRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Version: "2012-10-17"
PublishRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Effect: Allow
Resource:
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":logs:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :log-group:/aws/codebuild/
- Ref: BuildProject
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":logs:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :log-group:/aws/codebuild/
- Ref: BuildProject
- :*
- Action:
- codebuild:CreateReportGroup
- codebuild:CreateReport
- codebuild:UpdateReport
- codebuild:BatchPutTestCases
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":codebuild:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :report-group/
- Ref: BuildProject
- -*
- Action:
- ecr:GetAuthorizationToken
Effect: Allow
Resource: "*"
- Action:
- ecr:BatchCheckLayerAvailability
- ecr:CompleteLayerUpload
- ecr:GetAuthorizationToken
- ecr:InitiateLayerUpload
- ecr:PutImage
- ecr:UploadLayerPart
Effect: Allow
Resource:
Fn::GetAtt:
- ECRRepo
- Arn
- Action:
- proton:GetService
Effect: Allow
Resource: "*"
- Action:
- s3:GetObject*
- s3:GetBucket*
- s3:List*
- s3:DeleteObject*
- s3:PutObject*
- s3:Abort*
Effect: Allow
Resource:
- Fn::GetAtt:
- PipelineArtifactsBucket
- Arn
- Fn::Join:
- ""
- - Fn::GetAtt:
- PipelineArtifactsBucket
- Arn
- /*
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
- Action:
- kms:Decrypt
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
Version: "2012-10-17"
PolicyName: PublishRoleDefaultPolicy
Roles:
- Ref: PublishRole
DeploymentRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Version: "2012-10-17"
DeploymentRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Effect: Allow
Resource:
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":logs:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :log-group:/aws/codebuild/Deploy*Project*
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":logs:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :log-group:/aws/codebuild/Deploy*Project:*
- Action:
- codebuild:CreateReportGroup
- codebuild:CreateReport
- codebuild:UpdateReport
- codebuild:BatchPutTestCases
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":codebuild:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :report-group/Deploy*Project
- -*
- Action:
- proton:UpdateServiceInstance
- proton:GetServiceInstance
Effect: Allow
Resource: "*"
- Action:
- s3:GetObject*
- s3:GetBucket*
- s3:List*
Effect: Allow
Resource:
- Fn::GetAtt:
- PipelineArtifactsBucket
- Arn
- Fn::Join:
- ""
- - Fn::GetAtt:
- PipelineArtifactsBucket
- Arn
- /*
- Action:
- kms:Decrypt
- kms:DescribeKey
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
- Action:
- kms:Decrypt
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
Version: "2012-10-17"
PolicyName: DeploymentRoleDefaultPolicy
Roles:
- Ref: DeploymentRole
PipelineArtifactsBucketEncryptionKey:
Type: AWS::KMS::Key
Properties:
KeyPolicy:
Statement:
- Action:
- kms:Create*
- kms:Describe*
- kms:Enable*
- kms:List*
- kms:Put*
- kms:Update*
- kms:Revoke*
- kms:Disable*
- kms:Get*
- kms:Delete*
- kms:ScheduleKeyDeletion
- kms:CancelKeyDeletion
- kms:GenerateDataKey
- kms:TagResource
- kms:UntagResource
Effect: Allow
Principal:
AWS:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":iam::"
- Ref: AWS::AccountId
- :root
Resource: "*"
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Principal:
AWS:
Fn::GetAtt:
- PipelineRole
- Arn
Resource: "*"
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Principal:
AWS:
Fn::GetAtt:
- PublishRole
- Arn
Resource: "*"
- Action:
- kms:Decrypt
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Principal:
AWS:
Fn::GetAtt:
- PublishRole
- Arn
Resource: "*"
- Action:
- kms:Decrypt
- kms:DescribeKey
Effect: Allow
Principal:
AWS:
Fn::GetAtt:
- DeploymentRole
- Arn
Resource: "*"
- Action:
- kms:Decrypt
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Principal:
AWS:
Fn::GetAtt:
- DeploymentRole
- Arn
Resource: "*"
Version: "2012-10-17"
UpdateReplacePolicy: Delete
DeletionPolicy: Delete
PipelineArtifactsBucket:
Type: AWS::S3::Bucket
Properties:
VersioningConfiguration:
Status: Enabled
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
KMSMasterKeyID:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
SSEAlgorithm: aws:kms
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
UpdateReplacePolicy: Retain
DeletionPolicy: Retain
PipelineArtifactsBucketEncryptionKeyAlias:
Type: AWS::KMS::Alias
Properties:
AliasName: 'alias/codepipeline-encryption-key-{{ service.name }}'
TargetKeyId:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
UpdateReplacePolicy: Delete
DeletionPolicy: Delete
PipelineRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codepipeline.amazonaws.com
Version: "2012-10-17"
PipelineRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- s3:GetObject*
- s3:GetBucket*
- s3:List*
- s3:DeleteObject*
- s3:PutObject*
- s3:Abort*
Effect: Allow
Resource:
- Fn::GetAtt:
- PipelineArtifactsBucket
- Arn
- Fn::Join:
- ""
- - Fn::GetAtt:
- PipelineArtifactsBucket
- Arn
- /*
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
- Action: codestar-connections:*
Effect: Allow
Resource: "*"
- Action: sts:AssumeRole
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineBuildCodePipelineActionRole
- Arn
- Action: sts:AssumeRole
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineDeployCodePipelineActionRole
- Arn
Version: "2012-10-17"
PolicyName: PipelineRoleDefaultPolicy
Roles:
- Ref: PipelineRole
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
RoleArn:
Fn::GetAtt:
- PipelineRole
- Arn
Stages:
- Actions:
- ActionTypeId:
Category: Source
Owner: AWS
Provider: CodeStarSourceConnection
Version: "1"
Configuration:
ConnectionArn: '{{ service.repository_connection_arn }}'
FullRepositoryId: '{{ service.repository_id }}'
BranchName: '{{ service.branch_name }}'
Name: Checkout
OutputArtifacts:
- Name: Artifact_Source_Checkout
RunOrder: 1
Name: Source
- Actions:
- ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: "1"
Configuration:
ProjectName:
Ref: BuildProject
InputArtifacts:
- Name: Artifact_Source_Checkout
Name: Build
OutputArtifacts:
- Name: BuildOutput
RoleArn:
Fn::GetAtt:
- PipelineBuildCodePipelineActionRole
- Arn
RunOrder: 1
Name: Build {%- for service_instance in service_instances %}
- Actions:
- ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: "1"
Configuration:
ProjectName:
Ref: Deploy{{loop.index}}Project
InputArtifacts:
- Name: BuildOutput
Name: Deploy
RoleArn:
Fn::GetAtt:
- PipelineDeployCodePipelineActionRole
- Arn
RunOrder: 1
Name: 'Deploy{{service_instance.name}}'
{%- endfor %}
ArtifactStore:
EncryptionKey:
Id:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
Type: KMS
Location:
Ref: PipelineArtifactsBucket
Type: S3
DependsOn:
- PipelineRoleDefaultPolicy
- PipelineRole
PipelineBuildCodePipelineActionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":iam::"
- Ref: AWS::AccountId
- :root
Version: "2012-10-17"
PipelineBuildCodePipelineActionRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- codebuild:BatchGetBuilds
- codebuild:StartBuild
- codebuild:StopBuild
Effect: Allow
Resource:
Fn::GetAtt:
- BuildProject
- Arn
Version: "2012-10-17"
PolicyName: PipelineBuildCodePipelineActionRoleDefaultPolicy
Roles:
- Ref: PipelineBuildCodePipelineActionRole
PipelineDeployCodePipelineActionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":iam::"
- Ref: AWS::AccountId
- :root
Version: "2012-10-17"
PipelineDeployCodePipelineActionRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- codebuild:BatchGetBuilds
- codebuild:StartBuild
- codebuild:StopBuild
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":codebuild:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- ":project/Deploy*"
Version: "2012-10-17"
PolicyName: PipelineDeployCodePipelineActionRoleDefaultPolicy
Roles:
- Ref: PipelineDeployCodePipelineActionRole
Outputs:
PipelineEndpoint:
Description: The URL to access the pipeline
Value: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}"
]
}
}
}
Type: CODEPIPELINE
EncryptionKey:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
{% endfor %}
# This role is used to build and publish an image to ECR
PublishRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Version: "2012-10-17"
PublishRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Effect: Allow
Resource:
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":logs:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :log-group:/aws/codebuild/
- Ref: BuildProject
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":logs:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :log-group:/aws/codebuild/
- Ref: BuildProject
- :*
- Action:
- codebuild:CreateReportGroup
- codebuild:CreateReport
- codebuild:UpdateReport
- codebuild:BatchPutTestCases
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":codebuild:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :report-group/
- Ref: BuildProject
- -*
- Action:
- ecr:GetAuthorizationToken
Effect: Allow
Resource: "*"
- Action:
- ecr:BatchCheckLayerAvailability
- ecr:CompleteLayerUpload
- ecr:GetAuthorizationToken
- ecr:InitiateLayerUpload
- ecr:PutImage
- ecr:UploadLayerPart
Effect: Allow
Resource:
Fn::GetAtt:
- ECRRepo
- Arn
- Action:
- proton:GetService
Effect: Allow
Resource: "*"
- Action:
- s3:GetObject*
- s3:GetBucket*
- s3:List*
- s3:DeleteObject*
- s3:PutObject*
- s3:Abort*
Effect: Allow
Resource:
- Fn::GetAtt:
- PipelineArtifactsBucket
- Arn
- Fn::Join:
- ""
- - Fn::GetAtt:
- PipelineArtifactsBucket
- Arn
- /*
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
- Action:
- kms:Decrypt
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
Version: "2012-10-17"
PolicyName: PublishRoleDefaultPolicy
Roles:
- Ref: PublishRole
DeploymentRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Version: "2012-10-17"
DeploymentRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Effect: Allow
Resource:
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":logs:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :log-group:/aws/codebuild/Deploy*Project*
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":logs:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :log-group:/aws/codebuild/Deploy*Project:*
- Action:
- codebuild:CreateReportGroup
- codebuild:CreateReport
- codebuild:UpdateReport
- codebuild:BatchPutTestCases
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":codebuild:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :report-group/Deploy*Project
- -*
- Action:
- proton:UpdateServiceInstance
- proton:GetServiceInstance
Effect: Allow
Resource: "*"
- Action:
- s3:GetObject*
- s3:GetBucket*
- s3:List*
Effect: Allow
Resource:
- Fn::GetAtt:
- PipelineArtifactsBucket
- Arn
- Fn::Join:
- ""
- - Fn::GetAtt:
- PipelineArtifactsBucket
- Arn
- /*
- Action:
- kms:Decrypt
- kms:DescribeKey
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
- Action:
- kms:Decrypt
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
Version: "2012-10-17"
PolicyName: DeploymentRoleDefaultPolicy
Roles:
- Ref: DeploymentRole
PipelineArtifactsBucketEncryptionKey:
Type: AWS::KMS::Key
Properties:
KeyPolicy:
Statement:
- Action:
- kms:Create*
- kms:Describe*
- kms:Enable*
- kms:List*
- kms:Put*
- kms:Update*
- kms:Revoke*
- kms:Disable*
- kms:Get*
- kms:Delete*
- kms:ScheduleKeyDeletion
- kms:CancelKeyDeletion
- kms:GenerateDataKey
- kms:TagResource
- kms:UntagResource
Effect: Allow
Principal:
AWS:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":iam::"
- Ref: AWS::AccountId
- :root
Resource: "*"
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Principal:
AWS:
Fn::GetAtt:
- PipelineRole
- Arn
Resource: "*"
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Principal:
AWS:
Fn::GetAtt:
- PublishRole
- Arn
Resource: "*"
- Action:
- kms:Decrypt
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Principal:
AWS:
Fn::GetAtt:
- PublishRole
- Arn
Resource: "*"
- Action:
- kms:Decrypt
- kms:DescribeKey
Effect: Allow
Principal:
AWS:
Fn::GetAtt:
- DeploymentRole
- Arn
Resource: "*"
- Action:
- kms:Decrypt
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Principal:
AWS:
Fn::GetAtt:
- DeploymentRole
- Arn
Resource: "*"
Version: "2012-10-17"
UpdateReplacePolicy: Delete
DeletionPolicy: Delete
PipelineArtifactsBucket:
Type: AWS::S3::Bucket
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
KMSMasterKeyID:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
SSEAlgorithm: aws:kms
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
UpdateReplacePolicy: Retain
DeletionPolicy: Retain
PipelineArtifactsBucketEncryptionKeyAlias:
Type: AWS::KMS::Alias
Properties:
AliasName: 'alias/codepipeline-encryption-key-{{ service.name }}' # resource parameter
TargetKeyId:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
UpdateReplacePolicy: Delete
DeletionPolicy: Delete
PipelineRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codepipeline.amazonaws.com
Version: "2012-10-17"
PipelineRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- s3:GetObject*
- s3:GetBucket*
- s3:List*
- s3:DeleteObject*
- s3:PutObject*
- s3:Abort*
Effect: Allow
Resource:
- Fn::GetAtt:
- PipelineArtifactsBucket
- Arn
- Fn::Join:
- ""
- - Fn::GetAtt:
- PipelineArtifactsBucket
- Arn
- /*
- Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
- Action: codestar-connections:*
Effect: Allow
Resource: "*"
- Action: sts:AssumeRole
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineBuildCodePipelineActionRole
- Arn
- Action: sts:AssumeRole
Effect: Allow
Resource:
Fn::GetAtt:
- PipelineDeployCodePipelineActionRole
- Arn
Version: "2012-10-17"
PolicyName: PipelineRoleDefaultPolicy
Roles:
- Ref: PipelineRole
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
RoleArn:
Fn::GetAtt:
- PipelineRole
- Arn
Stages:
- Actions:
- ActionTypeId:
Category: Source
Owner: AWS
Provider: CodeStarSourceConnection
Version: "1"
Configuration:
ConnectionArn: '{{ service.repository_connection_arn }}' # resource parameter
FullRepositoryId: '{{ service.repository_id }}' # resource parameter
BranchName: '{{ service.branch_name }}' # resource parameter
Name: Checkout
OutputArtifacts:
- Name: Artifact_Source_Checkout
RunOrder: 1
Name: Source
- Actions:
- ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: "1"
Configuration:
ProjectName:
Ref: BuildProject
InputArtifacts:
- Name: Artifact_Source_Checkout
Name: Build
OutputArtifacts:
- Name: BuildOutput
RoleArn:
Fn::GetAtt:
- PipelineBuildCodePipelineActionRole
- Arn
RunOrder: 1
Name: Build {%- for service_instance in service_instances %}
- Actions:
- ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: "1"
Configuration:
ProjectName:
Ref: Deploy{{loop.index}}Project
InputArtifacts:
- Name: BuildOutput
Name: Deploy
RoleArn:
Fn::GetAtt:
- PipelineDeployCodePipelineActionRole
- Arn
RunOrder: 1
Name: 'Deploy{{service_instance.name}}' # resource parameter
{%- endfor %}
ArtifactStore:
EncryptionKey:
Id:
Fn::GetAtt:
- PipelineArtifactsBucketEncryptionKey
- Arn
Type: KMS
Location:
Ref: PipelineArtifactsBucket
Type: S3
DependsOn:
- PipelineRoleDefaultPolicy
- PipelineRole
PipelineBuildCodePipelineActionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":iam::"
- Ref: AWS::AccountId
- :root
Version: "2012-10-17"
PipelineBuildCodePipelineActionRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- codebuild:BatchGetBuilds
- codebuild:StartBuild
- codebuild:StopBuild
Effect: Allow
Resource:
Fn::GetAtt:
- BuildProject
- Arn
Version: "2012-10-17"
PolicyName: PipelineBuildCodePipelineActionRoleDefaultPolicy
Roles:
- Ref: PipelineBuildCodePipelineActionRole
PipelineDeployCodePipelineActionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":iam::"
- Ref: AWS::AccountId
- :root
Version: "2012-10-17"
PipelineDeployCodePipelineActionRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- codebuild:BatchGetBuilds
- codebuild:StartBuild
- codebuild:StopBuild
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":codebuild:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- ":project/Deploy*"
Version: "2012-10-17"
PolicyName: PipelineDeployCodePipelineActionRoleDefaultPolicy
Roles:
- Ref: PipelineDeployCodePipelineActionRole
Outputs:
PipelineEndpoint:
Description: The URL to access the pipeline
Value: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}"