本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
通过学习如何使用 AWS CloudFormation 基础架构作为代码文件 AWS Proton。 AWS CloudFormation 是一项基础设施即代码 (IaC) 服务,可帮助您对 AWS 资源进行建模和设置。您可以在模板中定义基础架构资源,在 CloudFormation 模板文件格式之上使用 Jinja 进行参数化。 AWS Proton 展开参数并呈现完整 CloudFormation 模板。 CloudFormation 将定义的资源配置为 CloudFormation 堆栈。有关更多信息,请参阅《 AWS CloudFormation 用户指南》中的什么是 AWS CloudFormation?
AWS Proton 支持 AWS CloudFormation IaC 的托管配置。
从您自己的现有基础设施即代码文件开始
您可以调整自己现有的基础设施即代码 (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 用作用于部署环境的环境模板包的基础架构即 AWS Proton 代码 (IaC) 文件(如示例 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}"