I am trying to deploy a new stack using CloudFormation with an ECS service using the CodeDeploy launch type to enable blue/green deployments.
In the User Guide for performing blue/green deployments via CloudFormation, they state the following:
To enable CloudFormation to perform blue/green deployments on a Stack, include the following information in its stack template:
At least one of the ECS resources that will trigger a blue/green deployment if replaced during a stack update. Currently, those resources are AWS::ECS::TaskDefinition and AWS::ECS::TaskSet.
When I exclude a AWS::ECS::TaskSet
, the Stack creation fails and I receive the following error:
Transform AWS::CodeDeployBlueGreen failed with: Failed to transform template.
ECSAttributes must include TaskSets in AWS::CodeDeploy::BlueGreen Hook
If I add a AWS::ECS::TaskSet
, the stack fails to create with the following error instead:
Resource handler returned message:
"Invalid request provided: Amazon ECS does not support task set management on services where deployments
are controlled by AWS CodeDeploy.
(Service: AmazonECS; Status Code: 400; Error Code: InvalidParameterException;
Request ID: 61b8c146-3ae9-4bc2-ac5c-08a11e194f06; Proxy: null)"
(RequestToken: 86a8a3a5-fe89-9939-15c2-45b08b28c3f3, HandlerErrorCode: InvalidRequest)
These are the relevant parts of my stack template:
Transform:
- AWS::CodeDeployBlueGreen
Hooks:
CodeDeployBlueGreenHook:
Type: AWS::CodeDeploy::BlueGreen
Properties:
ServiceRole: BlueGreenDeploymentRole
Applications:
- Target:
Type: AWS::ECS::Service
LogicalID: EcsService
ECSAttributes:
TaskDefinitions:
- TaskDefinitionBlue
- TaskDefinitionGreen
TaskSets:
- TaskSetBlue
- TaskSetGreen
TrafficRouting:
ProdTrafficRoute:
Type: AWS::ElasticLoadBalancingV2::Listener
LogicalID: LoadBalancerListener
TargetGroups:
- TargetGroupBlue
- TargetGroupGreen
TrafficRoutingConfig:
Type: TimeBasedLinear
TimeBasedLinear:
StepPercentage: 20
BakeTimeMins: 10
AdditionalOptions:
TerminationWaitTimeInMinutes: 60
Resources:
# IAM Role for blue/green deployments
BlueGreenDeploymentRole:
Type: AWS::IAM::Role
Properties:
RoleName: blue-green-deployment-role
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: codedeploy.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: BlueGreenDeploymentPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- codedeploy:Get*
- codedeploy:CreateCloudFormationDeployment
Resource: '*'
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSCodeDeployRoleForECS
#########################
# Load Balancer
#########################
# Application Load Balancer
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
IpAddressType: ipv4
Name: service-alb
Scheme: internal
Subnets:
- !Ref SubnetOne
- !Ref SubnetTwo
SecurityGroups:
- !Ref SecurityGroup
# Load Balancer Listener
LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
ForwardConfig:
TargetGroups:
- TargetGroupArn: !Ref TargetGroupBlue
Weight: 1
- TargetGroupArn: !Ref TargetGroupGreen
Weight: 1
LoadBalancerArn: !Ref LoadBalancer
Port: 8080
Protocol: HTTP
# Load Balancer Target Groups
TargetGroupBlue:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub ${ServiceName}-blue
TargetType: ip
VpcId: !Ref Vpc
Port: 8080
Protocol: HTTP
HealthCheckPort: 8080
HealthCheckPath: /actuator/health
TargetGroupGreen:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub ${ServiceName}-green
TargetType: ip
VpcId: !Ref Vpc
Port: 8080
Protocol: HTTP
HealthCheckPort: 8080
HealthCheckPath: /actuator/health
#########################
# ECS
#########################
# ECS Cluster
Cluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Ref ServiceName
# ECS Service
EcsService:
Type: AWS::ECS::Service
DependsOn: LoadBalancerListener
Properties:
ServiceName: !Ref ServiceName
Cluster: !Ref Cluster
TaskDefinition: !Ref TaskDefinitionBlue
DeploymentController:
Type: CODE_DEPLOY
DesiredCount: 0
LaunchType: FARGATE
LoadBalancers:
- ContainerName: !Sub ${ServiceName}-container
ContainerPort: 8080
TargetGroupArn: !Ref TargetGroupBlue
- ContainerName: !Sub ${ServiceName}-container
ContainerPort: 8080
TargetGroupArn: !Ref TargetGroupGreen
NetworkConfiguration:
AwsvpcConfiguration:
Subnets:
- !Ref SubnetOne
- !Ref SubnetTwo
SecurityGroups:
- !Ref SecurityGroup
SchedulingStrategy: REPLICA
# Task Definitions
TaskDefinitionBlue:
Type: AWS::ECS::TaskDefinition
Properties:
ContainerDefinitions:
- Name: !Sub ${ServiceName}-container
Image: !Sub ${ImageRepository.RepositoryUri}:latest
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref LogGroup
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: payments
PortMappings:
- ContainerPort: 8080
Cpu: 256
Memory: 512
NetworkMode: awsvpc
Family: !Sub ${ServiceName}
ExecutionRoleArn: !Ref TaskExecutionRole
RequiresCompatibilities:
- FARGATE
TaskDefinitionGreen:
Type: AWS::ECS::TaskDefinition
Properties:
ContainerDefinitions:
- Name: !Sub ${ServiceName}-container
Image: !Sub ${ImageRepository.RepositoryUri}:latest
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref LogGroup
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: payments
PortMappings:
- ContainerPort: 8080
Cpu: 256
Memory: 512
NetworkMode: awsvpc
Family: !Sub ${ServiceName}
ExecutionRoleArn: !Ref TaskExecutionRole
RequiresCompatibilities:
- FARGATE
# Image Repository
ImageRepository:
Type: AWS::ECR::Repository
Properties:
RepositoryName: !Sub ${ServiceName}
LifecyclePolicy:
LifecyclePolicyText: |
{
"rules": [
{
"rulePriority": 1,
"description": "Maintain at most 25 images",
"selection": {
"tagStatus": "untagged",
"countType": "imageCountMoreThan",
"countNumber": 25
},
"action": {
"type": "expire"
}
}
]
}
TaskSetBlue:
Type: AWS::ECS::TaskSet
Properties:
Cluster: !Ref Cluster
LaunchType: FARGATE
Service: !Ref EcsService
TaskDefinition: !Ref TaskDefinitionBlue
NetworkConfiguration:
AwsVpcConfiguration:
Subnets:
- !Ref SubnetOne
- !Ref SubnetTwo
SecurityGroups:
- !Ref SecurityGroup
LoadBalancers:
- ContainerName: !Sub ${ServiceName}-container
ContainerPort: 8080
TargetGroupArn: !Ref TargetGroupBlue
How can I update my template to allow for the blue/green deployment strategy via CodeDeploy?
CodePudding user response:
G/B deployment using CFN is EXTERNAL
, not CODE_DEPLOY
. There could be many other issues with your template, but your current error relates to using wrong DeploymentController
. Please study AWS docs and example: