amazon-web-services - 使用图像参数更改触发 Cloudformation Blue/Green
问题描述
在我的 Cloudformation 模板中,我使用的是蓝绿色部署触发器并具有以下 TaskDefinition
TaskDefinition:
Type: AWS::ECS::TaskDefinition
DependsOn: LogGroup
Properties:
Family: "task-family-name"
NetworkMode: awsvpc
RequiresCompatibilities: [FARGATE]
Cpu: 512
Memory: 1024
ExecutionRoleArn: arn:aws:iam::579072907853:role/ecsTaskExecutionRole
TaskRoleArn: !Ref ServiceRole
ContainerDefinitions:
- Name: !Ref ServiceName
Essential: true
Image: !Ref ImageARN
PortMappings:
- ContainerPort: !Ref ContainerPort
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-region: !Ref AWS::Region
awslogs-group: !Ref LogGroup
awslogs-stream-prefix: ecs
Environment:
- Name: RACK_ENV
Value: !Ref EnvironmentName
如果我用参数的新值更新堆栈ImageARN
,我会收到以下错误
'CodeDeployBlueGreenHook' of type AWS::CodeDeploy::BlueGreen failed with message: The submitted template's primary task definition 'TaskDefinition' was never updated. The template's 'AWS::CodeDeployBlueGreen' Transform might be missing or removed
如果我不使用参数而是使用硬编码Image
然后更新模板它工作正常。
有没有办法使用参数?
例子
以下是存在此问题的模板的完整示例。我在这两个图像之间更改 ImageARN 参数
nginx:1.18.0@sha256:001487e0a8c6abf91351ab45fdb308c0c2b95e8a67260b7ca5cf064462689a9e
nginx:1.19.4@sha256:aec3f367f48745b280ee2fd8d8469c0c0ec6b9b2fca3cd3e6cff03e1b69ae054
AWSTemplateFormatVersion: 2010-09-09
Parameters:
Image:
Type: String
CIDRBlock:
Type: String
Default: 192.168.5.0/24
Description: CIDR block for VPC
ExecutionRoleARN:
Type: String
Transform:
- AWS::CodeDeployBlueGreen
Hooks:
CodeDeployBlueGreenHook:
Type: AWS::CodeDeploy::BlueGreen
Properties:
TrafficRoutingConfig:
Type: AllAtOnce
Applications:
- Target:
Type: AWS::ECS::Service
LogicalID: ECSService
ECSAttributes:
TaskDefinitions:
- TaskDefinition
- GreenTaskDefinition
TaskSets:
- TaskSet
- GreenTaskSet
TrafficRouting:
ProdTrafficRoute:
Type: AWS::ElasticLoadBalancingV2::Listener
LogicalID: HTTPListener
TargetGroups:
- TargetGroup
- TargetGroupGreen
Resources:
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTP to load balancer
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
FargateSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow port 80 to service
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref ALBSecurityGroup
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: load-balancer
Type: application
IpAddressType: ipv4
Scheme: internet-facing
SecurityGroups: [!Ref ALBSecurityGroup]
Subnets: [!Ref Subnet1, !Ref Subnet2]
HTTPListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- TargetGroupArn: !Ref TargetGroup
Type: forward
LoadBalancerArn: !Ref LoadBalancer
Port: 80
Protocol: HTTP
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
HealthCheckTimeoutSeconds: 10
HealthyThresholdCount: 5
Name: targetgroup-blue
Port: 80
Protocol: HTTP
TargetType: ip
UnhealthyThresholdCount: 10
VpcId: !Ref Vpc
TargetGroupGreen:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
HealthCheckTimeoutSeconds: 10
HealthyThresholdCount: 5
Name: targetgroup-green
Port: 80
Protocol: HTTP
TargetType: ip
UnhealthyThresholdCount: 10
VpcId: !Ref Vpc
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: "task-family-name"
NetworkMode: awsvpc
RequiresCompatibilities: [FARGATE]
Cpu: 512
Memory: 1024
ExecutionRoleArn: !Ref ExecutionRoleARN
ContainerDefinitions:
- Name: Container
Essential: true
Image: !Ref Image
PortMappings:
- ContainerPort: 80
TaskSet:
Type: AWS::ECS::TaskSet
Properties:
Cluster: !Ref ECSCluster
LaunchType: FARGATE
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups: [!Ref FargateSecurityGroup]
Subnets: [!Ref Subnet1, !Ref Subnet2]
Scale:
Unit: PERCENT
Value: 100
Service: !Ref ECSService
TaskDefinition: !Ref TaskDefinition
PlatformVersion: LATEST
LoadBalancers:
- ContainerName: Container
ContainerPort: 80
TargetGroupArn: !Ref TargetGroup
ECSService:
Type: AWS::ECS::Service
DependsOn: HTTPListener
Properties:
ServiceName: service
Cluster: !Ref ECSCluster
DeploymentController:
Type: EXTERNAL
DesiredCount: 4
EnableECSManagedTags: true
PrimaryTaskSet:
Type: 'AWS::ECS::PrimaryTaskSet'
Properties:
Cluster: !Ref ECSCluster
Service: !Ref ECSService
TaskSetId: !GetAtt 'TaskSet.Id'
Vpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref CIDRBlock
EnableDnsHostnames: true
EnableDnsSupport: true
Subnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
CidrBlock: !Select [0, !Cidr [!Ref CIDRBlock, 2, 6 ]]
AvailabilityZone: !Select [0, Fn::GetAZs: !Ref 'AWS::Region']
Subnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
CidrBlock: !Select [1, !Cidr [!Ref CIDRBlock, 2, 6 ]]
AvailabilityZone: !Select [1, Fn::GetAZs: !Ref 'AWS::Region']
InternetGateway:
Type: AWS::EC2::InternetGateway
InternetGatewayVPCAssoc:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref Vpc
InternetGatewayId: !Ref InternetGateway
RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref Vpc
RouteTableSub1Assoc:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable
SubnetId: !Ref Subnet1
RouteTableSub2Assoc:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTable
SubnetId: !Ref Subnet2
InternetGatewayRoute:
Type: AWS::EC2::Route
DependsOn: InternetGateway
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: Cluster
CapacityProviders:
- FARGATE
DefaultCapacityProviderStrategy:
- CapacityProvider: FARGATE
Weight: 1
解决方案
我查看了您的示例,以及我自己的项目中的内容。我可以确认您的示例没有按预期工作。
我进行了更多调查并确定该问题可能是由于在您的模板中创建了整个网络堆栈。在我自己的项目中,我的 ecs 模板中没有 VPC 或子网,因此一切正常。
因此,一旦我从您的模板中删除了与 VPC 相关的内容,它就开始按要求工作。还有一些其他较小的更改,但它们可能不是必需的。我认为 VPC 的东西是主要原因。
此外,请使用Replace current template选项更新模板,而不是Use current template
. 如果您使用第二个选项,它仍然无法正常工作。我认为这是由于宏在 CFN 中的工作方式,应该替换模板,而不是就地更新。如果替换它,CodeDeploy 中的 B/G是成功触发,您可以在 CodeDeploy 控制台中查看它。
这是修改后的模板:
AWSTemplateFormatVersion: 2010-09-09
Parameters:
ImageUrl:
Type: String
VpcId:
Type: 'AWS::EC2::VPC::Id'
Subnet1:
Type: 'AWS::EC2::Subnet::Id'
Subnet2:
Type: 'AWS::EC2::Subnet::Id'
ExecutionRoleARN:
Type: String
DesiredCount:
Type: Number
Default: 2
Transform:
- 'AWS::CodeDeployBlueGreen'
Hooks:
CodeDeployBlueGreenHook:
Type: 'AWS::CodeDeploy::BlueGreen'
Properties:
TrafficRoutingConfig:
Type: AllAtOnce
Applications:
- Target:nginx:1.19.4@sha256:aec3f367f48745b280ee2fd8d8469c0c0ec6b9b2fca3cd3e6cff03e1b69ae054
Type: 'AWS::ECS::Service'
LogicalID: ECSService
ECSAttributes:
TaskDefinitions:
- TaskDefinition
- GreenTaskDefinition
TaskSets:
- TaskSet
- GreenTaskSet
TrafficRouting:
ProdTrafficRoute:
Type: 'AWS::ElasticLoadBalancingV2::Listener'
LogicalID: HTTPListener
TargetGroups:
- TargetGroupnginx:1.19.4@sha256:aec3f367f48745b280ee2fd8d8469c0c0ec6b9b2fca3cd3e6cff03e1b69ae054
- TargetGroupGreen
Resources:
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTP to load balancer
VpcId: !Ref VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
FargateSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow port 80 to service
VpcId: !Ref VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref ALBSecurityGroup
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
#Name: load-balancer
Type: application
IpAddressType: ipv4
Scheme: internet-facing
SecurityGroups:
- !Ref ALBSecurityGroup
Subnets:
- !Ref Subnet1
- !Ref Subnet2
HTTPListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- TargetGroupArn: !Ref TargetGroup
Type: forward
LoadBalancerArn: !Ref LoadBalannginx:1.19.4@sha256:aec3f367f48745b280ee2fd8d8469c0c0ec6b9b2fca3cd3e6cff03e1b69ae054cer
Port: 80
Protocol: HTTP
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
HealthCheckTimeoutSeconds: 10
HealthyThresholdCount: 5
#Name: targetgroup-blue
Port: 80
Protocol: HTTP
TargetType: ip
UnhealthyThresholdCount: 10
VpcId: !Ref VpcId
TargetGroupGreen:
Type: nginx:1.19.4@sha256:aec3f367f48745b280ee2fd8d8469c0c0ec6b9b2fca3cd3e6cff03e1b69ae054AWS::ElasticLoadBalancingV2nginx:1.19.4@sha256:aec3f367f48745b280ee2fd8d8469c0c0ec6b9b2fca3cd3e6cff03e1b69ae054::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
HealthCheckTimeoutSeconds: 10
HealthyThresholdCount: 5
#Name: targetgroup-green
Port: 80
Protocol: HTTP
TargetType: ip
UnhealthyThresholdCount: 10
VpcId: !Ref VpcId
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: "task-family-name"
NetworkMode: awsvpc
RequiresCompatibilities: [FARGATE]
Cpu: 256
Memory: 512
ExecutionRoleArn: !Ref ExecutionRoleARN
ContainerDefinitions:
- Name: Container
Essential: true
Image: !Ref ImageUrl
PortMappings:
- ContainerPort: 80
Protocol: tcp
TaskSet:
Type: AWS::ECS::TaskSet
Properties:
Cluster: !Ref ECSCluster
LaunchType: FARGATE
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- !Ref FargateSecurityGroup
Subnets:
- !Ref Subnet1
- !Ref Subnet2
Scale:
Unit: PERCENT
Value: 100
Service: !Ref ECSService
TaskDefinition: !Ref TaskDefinition
PlatformVersion: LATEST
LoadBalancers:
- ContainerName: Container
ContainerPort: 80
TargetGroupArn: !Ref TargetGroup
ECSService:
Type: AWS::ECS::Service
DependsOn: HTTPListener
Properties:
#ServiceName: service
Cluster: !Ref ECSCluster
DeploymentController:
Type: EXTERNAL
DesiredCount: !Ref DesiredCount
EnableECSManagedTags: true
PrimaryTaskSet:
Type: 'AWS::ECS::PrimaryTaskSet'
Properties:
Cluster: !Ref ECSCluster
Service: !Ref ECSService
TaskSetId: !GetAtt TaskSet.Id
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
#ClusterName: Cluster
CapacityProviders:
- FARGATE
DefaultCapacityProviderStrategy:
- CapacityProvider: FARGATE
Weight: 1
Outputs:
ALBDNSName:
Value: !GetAtt LoadBalancer.DNSName
推荐阅读
- flutter - Dart/Flutter 错误:“AuthSession”类型的值不能分配给“CognitoAuthSession”类型的变量
- ldap - 防止用户多次更改密码 - openldap
- node.js - R3InjectorError(AppServerModule) 没有 InjectionToken compilerOptions 的提供者
- python - 获取 Radiobutton Python tkinter 的值
- powershell - DirectorySearcher 查找具有特定经理的所有条目
- pandas - 在有条件的情况下重新启动 Pandas 中的 cumsum
- swift - 组合:Just 和 first() 之间的区别来完成一个流
- sql - 跳过 Postgres 中的 WHERE 子句,具体取决于参数
- python - Python 中的 VLOOKUP 与 JSON 或 CSV
- reactjs - 在步进器中保持先前选择的项目状态