Executar implantações azul/verde do ECS por meio do CodeDeploy usando o AWS CloudFormation - AWS CloudFormation

Executar implantações azul/verde do ECS por meio do CodeDeploy usando o AWS CloudFormation

É possível usar o CloudFormation para executar implantações azul/verde do ECS por meio do AWS CodeDeploy. As implantações azul/verde são uma estratégia de implantação segura fornecida pelo CodeDeploy para minimizar interrupções causadas pela alteração das versões da aplicação. Isso é realizado por meio da criação de seu novo ambiente de aplicativo, chamado de verde, junto com seu aplicativo atual que está veiculando seu tráfego dinâmico, chamado de azul. Isso permite um período para o monitoramento e o teste do ambiente verde antes que o tráfego dinâmico seja roteado de azul para verde e, posteriormente, desative os recursos azuis.

Ao usar o CloudFormation para executar implantações azul/verde do ECS, você começa criando um modelo de pilha que define os recursos para seus ambientes de aplicativo azul e verde, incluindo a especificação das configurações de roteamento de tráfego e de estabilização a serem usadas. Depois, você cria uma pilha a partir desse modelo, o que gera sua aplicação azul (atual). O CloudFormation cria somente os recursos azuis durante a criação da pilha. Os recursos para uma implantação verde não são criados até que sejam necessários.

Depois, se em uma futura atualização de pilha você atualizar os recursos de definição de tarefa ou do conjunto de tarefas no aplicativo azul, o CloudFormation fará o seguinte:

  • Gerará todos os recursos de ambiente do aplicativo verde necessários

  • Deslocará o tráfego com base nos parâmetros de roteamento de tráfego especificados

  • Excluirá os recursos azuis

Se ocorrer um erro em qualquer ponto antes da implantação verde ser finalizada com êxito, o CloudFormation reverterá a pilha para seu estado anterior ao início de toda a implantação verde.

Para permitir que o CloudFormation execute implantações azul/verde em uma pilha, inclua as seguintes informações no modelo de pilha:

  • Uma seção do Transform em seu modelo que invoque a transformação AWS::CodeDeployBlueGreen, e uma seção Hook que invoque o hook AWS::CodeDeploy::BlueGreen.

  • Pelo menos um dos recursos do ECS que acionará uma implantação azul/verde se for substituído durante uma atualização de pilha. Atualmente, esses recursos são AWS::ECS::TaskDefinition e AWS::ECS::TaskSet.

Depois, se você iniciar uma atualização de pilha que atualize qualquer propriedade dos recursos acima que exijam que o CloudFormation substitua o recurso, o CloudFormation executará uma implantação azul/verde conforme descrito acima. Para obter mais informações sobre o comportamento de atualização de recurso, consulte Atualizar comportamentos de recursos da pilha.

Em alguns casos, será melhor configurar seu modelo de pilha para habilitar implantações azul/verde antes de criar a pilha. No entanto, também é possível adicionar a possibilidade de fazer com que o CloudFormation execute implantações azul/verde em uma pilha existente. Para fazer isso, adicione as informações necessárias ao modelo existente da pilha.

Além disso, recomendamos que o CloudFormation gere um conjunto de alterações para a implantação verde, antes de iniciar a atualização da pilha. Isso permite que você revise as alterações que serão feitas na pilha. Para ter mais informações, consulte Atualizar pilhas usando conjuntos de alterações.

Modelar sua implantação azul/verde usando recursos do CloudFormation

Para executar a implantação azul/verde do ECS usando CodeDeploy por meio do CloudFormation, o modelo deve incluir os recursos que modelam sua implantação, como um serviço do Amazon ECS e um balanceador de carga. Para mais detalhes sobre o que esses recursos representam, consulte Antes de iniciar uma implantação do Amazon ECS no AWS CodeDeployGuia do usuário.

Requisito Recurso Obrigatório/opcional Aciona a implantação azul/verde se substituído
Cluster do Amazon ECS AWS::ECS::Cluster Opcional. O cluster padrão pode ser usado. Não
Serviço do Amazon ECS AWS::ECS::Service Obrigatório. Não
Application ou Network Load Balancer AWS::ECS::Service LoadBalancer Obrigatório. Não
Listener de produção AWS::ElasticLoadBalancingV2::Listener Obrigatório. Não
Listener de teste AWS::ElasticLoadBalancingV2::Listener Opcional. Não
Dois grupos de destino AWS::ElasticLoadBalancingV2::TargetGroup Obrigatório. Não
Definição de tarefa do Amazon ECS AWS::ECS::TaskDefinition Obrigatório. Sim
Contêiner para seu aplicativo do Amazon ECS AWS::ECS::TaskDefinition ContainerDefinition Name Obrigatório. Não
Porta para o conjunto de tarefas de substituição AWS::ECS::TaskDefinition PortMapping ContainerPort Obrigatório. Não

Atualizações de recursos que acionam implantações verdes

Se você executar uma atualização de pilha que atualize qualquer propriedade que exija substituição dos seguintes recursos do ECS, o CloudFormation iniciará uma implantação verde:

Atualizar propriedades nesses recursos que não exigem substituição de recursos não aciona uma implantação verde.

Não é possível incluir atualizações para os recursos acima com atualizações para outros recursos na mesma atualização de pilha. Se for necessário atualizar recursos na lista acima, bem como outros recursos na mesma pilha, siga um destes procedimentos:

  • Execute duas operações de atualização de pilha separadas: uma que inclua somente as atualizações para os recursos acima e uma atualização de pilha separada que inclua alterações em quaisquer outros recursos.

  • Remova as seções Hook e Transform do modelo e execute a atualização da pilha. Neste caso, o CloudFormation não executará uma implantação verde.

Considerações ao gerenciar implantações azul/verde do ECS usando o CloudFormation

Considere o seguinte ao definir sua implantação azul/verde usando o CloudFormation:

  • Somente atualizações de determinados recursos acionarão uma implantação verde, conforme discutido em Atualizações de recursos que acionam implantações verdes.

  • Não é possível incluir atualizações de recursos que acionam implantações verdes e atualizações de outros recursos na mesma atualização de pilha, conforme discutido em Atualizações de recursos que acionam implantações verdes.

  • Só é possível especificar um único serviço do ECS como o destino de implantação.

  • Os parâmetros que tenham valores ofuscados pelo CloudFormation não poderão ser atualizados pelo serviço CodeDeploy durante uma implantação verde, e causarão um erro e uma falha na atualização da pilha. Isso inclui:

  • Para cancelar uma implantação verde que ainda está em andamento, cancele a atualização da pilha no CloudFormation, e não no CodeDeploy ou ECS. Para ter mais informações, consulte Cancelar uma atualização de pilha. (Após a conclusão de uma atualização, não será possível cancelá-la. Porém, é possível atualizar uma pilha novamente com as configurações anteriores.)

  • No momento, não há suporte à declaração de Outputs ou ao uso de para importar valores de outras pilhas para modelos que definem implantações azul/verde do ECS.

  • No momento, não há suporte a modelos que definem implantações azul/verde do ECS.

  • Não é possível usar o hook AWS::CodeDeploy::BlueGreen em um modelo que inclua recursos de pilha aninhados.

  • Não é possível usar o hook AWS::CodeDeploy::BlueGreen em uma pilha aninhada.

Para obter informações sobre como o uso do CloudFormation para executar suas implantações do ECS azul/verde por meio de CodeDeploy difere de uma implantação padrão do Amazon ECS usando apenas CodeDeploy, consulte Diferenças entre implantações azul/verde do Amazon ECS por meio do CloudFormation e implantações padrão do Amazon ECS, no Guia do usuário do AWS CodeDeploy.

Preparar seu modelo para executar implantações azul/verde do ECS

Para permitir implantações azul/verde em sua pilha, inclua as seções a seguir no modelo de pilha antes de executar uma atualização dela.

  • Adicione uma referência à transformação AWS::CodeDeployBlueGreen ao modelo:

    "Transform": [ "AWS::CodeDeployBlueGreen" ],
  • Adicione uma seção Hook que invoque o hook AWS::CodeDeploy::BlueGreen e especifique as propriedades para a implantação. Use a referência do modelo abaixo como guia.

  • Na seção Resources, defina os recursos azuis e verdes para a implantação.

É possível adicionar essas seções ao criar o modelo pela primeira vez (ou seja, antes de criar a pilha) ou adicioná-las a um modelo existente antes de executar uma atualização de pilha. Se você especificar a implantação azul/verde para uma nova pilha, o CloudFormation criará somente os recursos azuis durante a criação. Os recursos para a implantação verde não serão criados até que sejam necessários durante uma atualização da pilha.

Revisar os conjuntos de alterações para a implantação azul/verde

É altamente recomendável que você crie um conjunto de alterações antes de executar uma atualização de pilha que iniciará uma implantação verde. Isso permite que você veja as alterações que serão feitas antes de executar a atualização da pilha. Esteja ciente de que as alterações de recursos podem não ser listadas na ordem em que serão executadas durante a atualização da pilha. Para ter mais informações, consulte Atualizar pilhas usando conjuntos de alterações.

Visualizar eventos da pilha para sua implantação azul/verde

É possível visualizar os eventos da pilha gerados em cada etapa da implantação do ECS na guia Events (Eventos) da página Stack (Pilha) e usando a AWS CLI. Para ter mais informações, consulte Monitorar o progresso da atualização de uma pilha.

Referência do modelo

"Hooks": { "Logical ID": { "Properties": { "TrafficRoutingConfig": { "Type": "Traffic routing type", "TimeBasedCanary": { "StepPercentage": Integer, "BakeTimeMins": Integer }, "TimeBasedLinear": { "StepPercentage": Integer, "BakeTimeMins": Integer } }, "AdditionalOptions": {"TerminationWaitTimeInMinutes": Integer}, "LifecycleEventHooks": { "BeforeInstall": "FunctionName", "AfterInstall": "FunctionName", "AfterAllowTestTraffic": "FunctionName", "BeforeAllowTraffic": "FunctionName", "AfterAllowTraffic": "FunctionName" }, "ServiceRole": "CodeDeployServiceRoleName", "Applications": [ { "Target": { "Type": "AWS::ECS::Service", "LogicalID": "Resource Logical ID" }, "ECSAttributes": { "TaskDefinitions": [ "AWS::ECS::TaskDefinition Resource Logical ID (Blue)", "AWS::ECS::TaskDefinition Resource Logical ID (Green)" ], "TaskSets": [ "AWS::ECS::TaskSet Resource Logical ID (Blue)", "AWS::ECS::TaskSet Resource Logical ID (Green)" ], "TrafficRouting": { "ProdTrafficRoute": { "Type": "AWS::ElasticLoadBalancingV2::Listener", "LogicalID": "Resource Logical ID (Production)" }, "TestTrafficRoute": { "Type": "AWS::ElasticLoadBalancingV2::Listener", "LogicalID": "Resource Logical ID (Test)" }, "TargetGroups": [ "AWS::ElasticLoadBalancingV2::TargetGroup Resource Logical ID (Blue)", "AWS::ElasticLoadBalancingV2::TargetGroup Resource Logical ID (Green)" ] } } } ] }, "Type": "AWS::CodeDeploy::BlueGreen" } }

Propriedades

Logical ID

O ID lógico deve ser alfanumérico (A-Z a-z 0-9) e exclusivo no modelo.

Obrigatório: Sim

Properties

Propriedades do hook.

Obrigatório: Sim

TrafficRoutingConfig

Definição das configurações de roteamento de tráfego.

Obrigatório: não

A configuração padrão é o deslocamento de tráfego canário baseado em tempo, com uma porcentagem de 15% de etapa e um tempo de incorporação de cinco minutos.

Type

O tipo de deslocamento de tráfego usado pela configuração de implantação.

Valores válidos: AllAtOnce | TimeBasedCanary | TimeBasedLinear

Obrigatório: Sim

TimeBasedCanary

Especifica uma configuração que desloca o tráfego de uma versão da implantação para outra em incrementos de dois.

Necessário: Condicional: se você especificar TimeBasedCanary como o tipo de roteamento de tráfego, deverá incluir o parâmetro TimeBasedCanary.

StepPercentage

A porcentagem de tráfego a ser deslocado no primeiro incremento de uma implantação TimeBasedCanary. A porcentagem da etapa deve ser 14% ou maior.

Obrigatório: não

BakeTimeMins

O número de minutos entre o primeiro e o segundo deslocamento de tráfego de uma implantação TimeBasedCanary.

Obrigatório: não

TimeBasedLinear

Especifica uma configuração que desloca o tráfego de uma versão da implantação para outra em incrementos iguais, com um número igual de minutos entre cada incremento.

Necessário: Condicional: se você especificar TimeBasedLinear como o tipo de roteamento de tráfego, deverá incluir o parâmetro TimeBasedLinear.

StepPercentage

A porcentagem de tráfego deslocado no início de cada incremento de uma implantação TimeBasedLinear. A porcentagem da etapa deve ser 14% ou maior.

Obrigatório: não

BakeTimeMins

O número de minutos entre cada deslocamento de tráfego incremental de uma implantação TimeBasedLinear.

Obrigatório: não

AdditionalOptions

Opções adicionais para a implantação azul/verde.

Obrigatório: não

TerminationWaitTimeInMinutes

Especifica o tempo de espera, em minutos, antes de encerrar os recursos azuis.

Obrigatório: não

LifecycleEventHooks

Use hooks de eventos de ciclo de vida para especificar uma função do Lambda que o CodeDeploy possa chamar para validar uma implantação. É possível usar a mesma função ou uma diferente para os eventos de ciclo de vida de implantação. Após a conclusão dos testes de validação, a função AfterAllowTraffic do Lambda chama de volta o CodeDeploy e entrega um resultado de Succeeded ou Failed.

Para mais informações, consulte a seção “Hooks” do AppSpec no Guia do usuário do AWS CodeDeploy.

Obrigatório: não

BeforeInstall

Função a ser usada para executar tarefas antes que o conjunto de tarefas de substituição seja criado.

Obrigatório: não

AfterInstall

Função a ser usada para executar tarefas depois que o conjunto de tarefas de substituição for criado e um dos grupos de destino for associado a ele.

Obrigatório: não

AfterAllowTestTraffic

Função a ser usada para executar tarefas depois que o listener de teste distribuir o tráfego para o conjunto de tarefas de substituição.

Obrigatório: não

BeforeAllowTraffic

Função a ser usada para executar tarefas depois que o segundo grupo de destino for associado ao conjunto de tarefas de substituição, mas antes que o tráfego seja deslocado para o conjunto de tarefas de substituição.

Obrigatório: não

AfterAllowTraffic

Função a ser usada para executar tarefas depois que o segundo grupo de destino distribuir o tráfego para o conjunto de tarefas de substituição.

Obrigatório: não

ServiceRole

A função de execução a ser usada pelo CloudFormation para executar as implantações azul/verde. Para obter uma lista das permissões necessárias, consulte Permissões do IAM necessárias para implantações azul/verde.

Obrigatório: Sim

Applications

Especifica as propriedades do aplicativo do Amazon ECS.

Obrigatório: Sim

Target

Obrigatório: Sim

Type

O tipo de recurso.

Obrigatório: Sim

LogicalID

O ID lógico do recurso.

Obrigatório: Sim

ECSAttributes

Os recursos que representam os vários requisitos de sua implantação de aplicativos do Amazon ECS.

Obrigatório: Sim

TaskDefinitions

O ID lógico do AWS::ECS::TaskDefinition recurso para executar o contêiner do Docker que contém seu aplicativo do Amazon ECS.

Obrigatório: Sim

TaskSets

Os IDs lógicos dos recursos AWS::ECS::TaskSet a serem usados como conjuntos de tarefas para o aplicativo.

Obrigatório: Sim

TrafficRouting

Especifica os recursos usados para roteamento de tráfego.

Obrigatório: Sim

ProdTrafficRoute

O listener é usado pelo load balancer para direcionar o tráfego para seus grupos de destino.

Obrigatório: Sim

Type

O tipo do recurso. AWS::ElasticLoadBalancingV2::Listener

Obrigatório: Sim

LogicalID

O ID lógico do recurso.

Obrigatório: Sim

TestTrafficRoute

O listener é usado pelo load balancer para direcionar o tráfego para seus grupos de destino.

Obrigatório: Sim

Type

O tipo do recurso. AWS::ElasticLoadBalancingV2::Listener

Obrigatório: Sim

LogicalID

O ID lógico do recurso.

Obrigatório: não

TargetGroups

ID lógico dos recursos a serem usados como grupos de destino para rotear o tráfego para o destino registrado.

Obrigatório: Sim

Type

O tipo do hook. AWS::ElasticLoadBalancingV2::Listener

Obrigatório: Sim

Permissões do IAM necessárias para implantações azul/verde

Para que o CloudFormation execute com sucesso as implantações azul/verde, você deve ter as seguintes permissões do CodeDeploy:

  • codedeploy:Get*

  • codedeploy:CreateCloudFormationDeployment

Para mais informações, consulte Ações, recursos e chaves de condição para o CodeDeploy, no Guia do usuário do AWS Identity and Access Management.

Exemplo de modelo

O exemplo a seguir configura uma implantação azul/verde do ECS por meio do CodeDeploy, com um progresso de roteamento de tráfego de 15% por etapa, com um período de estabilização de 5 minutos entre cada etapa. Criar uma pilha com o modelo provisiona a configuração inicial da implantação.

Se você fez alguma alteração nas propriedades do recurso "BlueTaskSet" que exija que esse recurso seja substituído, o CloudFormation inicializará uma implantação verde como parte da atualização da pilha.

JSON

{ "Parameters": { "Vpc": { "Type": "AWS::EC2::VPC::Id" }, "Subnet1": { "Type": "AWS::EC2::Subnet::Id" }, "Subnet2": { "Type": "AWS::EC2::Subnet::Id" } }, "Transform": [ "AWS::CodeDeployBlueGreen" ], "Hooks": { "CodeDeployBlueGreenHook": { "Properties": { "TrafficRoutingConfig": { "Type": "TimeBasedCanary", "TimeBasedCanary": { "StepPercentage": 15, "BakeTimeMins": 5 } }, "Applications": [ { "Target": { "Type": "AWS::ECS::Service", "LogicalID": "ECSDemoService" }, "ECSAttributes": { "TaskDefinitions": [ "BlueTaskDefinition", "GreenTaskDefinition" ], "TaskSets": [ "BlueTaskSet", "GreenTaskSet" ], "TrafficRouting": { "ProdTrafficRoute": { "Type": "AWS::ElasticLoadBalancingV2::Listener", "LogicalID": "ALBListenerProdTraffic" }, "TargetGroups": [ "ALBTargetGroupBlue", "ALBTargetGroupGreen" ] } } } ] }, "Type": "AWS::CodeDeploy::BlueGreen" } }, "Resources": { "ExampleSecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "Security group for ec2 access", "VpcId": { "Ref": "Vpc" }, "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "tcp", "FromPort": 8080, "ToPort": 8080, "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "tcp", "FromPort": 22, "ToPort": 22, "CidrIp": "0.0.0.0/0" } ] } }, "ALBTargetGroupBlue": { "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", "Properties": { "HealthCheckIntervalSeconds": 5, "HealthCheckPath": "/", "HealthCheckPort": "80", "HealthCheckProtocol": "HTTP", "HealthCheckTimeoutSeconds": 2, "HealthyThresholdCount": 2, "Matcher": { "HttpCode": "200" }, "Port": 80, "Protocol": "HTTP", "Tags": [ { "Key": "Group", "Value": "Example" } ], "TargetType": "ip", "UnhealthyThresholdCount": 4, "VpcId": { "Ref": "Vpc" } } }, "ALBTargetGroupGreen": { "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", "Properties": { "HealthCheckIntervalSeconds": 5, "HealthCheckPath": "/", "HealthCheckPort": "80", "HealthCheckProtocol": "HTTP", "HealthCheckTimeoutSeconds": 2, "HealthyThresholdCount": 2, "Matcher": { "HttpCode": "200" }, "Port": 80, "Protocol": "HTTP", "Tags": [ { "Key": "Group", "Value": "Example" } ], "TargetType": "ip", "UnhealthyThresholdCount": 4, "VpcId": { "Ref": "Vpc" } } }, "ExampleALB": { "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", "Properties": { "Scheme": "internet-facing", "SecurityGroups": [ { "Ref": "ExampleSecurityGroup" } ], "Subnets": [ { "Ref": "Subnet1" }, { "Ref": "Subnet2" } ], "Tags": [ { "Key": "Group", "Value": "Example" } ], "Type": "application", "IpAddressType": "ipv4" } }, "ALBListenerProdTraffic": { "Type": "AWS::ElasticLoadBalancingV2::Listener", "Properties": { "DefaultActions": [ { "Type": "forward", "ForwardConfig": { "TargetGroups": [ { "TargetGroupArn": { "Ref": "ALBTargetGroupBlue" }, "Weight": 1 } ] } } ], "LoadBalancerArn": { "Ref": "ExampleALB" }, "Port": 80, "Protocol": "HTTP" } }, "ALBListenerProdRule": { "Type": "AWS::ElasticLoadBalancingV2::ListenerRule", "Properties": { "Actions": [ { "Type": "forward", "ForwardConfig": { "TargetGroups": [ { "TargetGroupArn": { "Ref": "ALBTargetGroupBlue" }, "Weight": 1 } ] } } ], "Conditions": [ { "Field": "http-header", "HttpHeaderConfig": { "HttpHeaderName": "User-Agent", "Values": [ "Mozilla" ] } } ], "ListenerArn": { "Ref": "ALBListenerProdTraffic" }, "Priority": 1 } }, "ECSTaskExecutionRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "ecs-tasks.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }, "ManagedPolicyArns": [ "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" ] } }, "BlueTaskDefinition": { "Type": "AWS::ECS::TaskDefinition", "Properties": { "ExecutionRoleArn": { "Fn::GetAtt": [ "ECSTaskExecutionRole", "Arn" ] }, "ContainerDefinitions": [ { "Name": "DemoApp", "Image": "nginxdemos/hello:latest", "Essential": true, "PortMappings": [ { "HostPort": 80, "Protocol": "tcp", "ContainerPort": 80 } ] } ], "RequiresCompatibilities": [ "FARGATE" ], "NetworkMode": "awsvpc", "Cpu": "256", "Memory": "512", "Family": "ecs-demo" } }, "ECSDemoCluster": { "Type": "AWS::ECS::Cluster", "Properties": {} }, "ECSDemoService": { "Type": "AWS::ECS::Service", "Properties": { "Cluster": { "Ref": "ECSDemoCluster" }, "DesiredCount": 1, "DeploymentController": { "Type": "EXTERNAL" } } }, "BlueTaskSet": { "Type": "AWS::ECS::TaskSet", "Properties": { "Cluster": { "Ref": "ECSDemoCluster" }, "LaunchType": "FARGATE", "NetworkConfiguration": { "AwsVpcConfiguration": { "AssignPublicIp": "ENABLED", "SecurityGroups": [ { "Ref": "ExampleSecurityGroup" } ], "Subnets": [ { "Ref": "Subnet1" }, { "Ref": "Subnet2" } ] } }, "PlatformVersion": "1.4.0", "Scale": { "Unit": "PERCENT", "Value": 100 }, "Service": { "Ref": "ECSDemoService" }, "TaskDefinition": { "Ref": "BlueTaskDefinition" }, "LoadBalancers": [ { "ContainerName": "DemoApp", "ContainerPort": 80, "TargetGroupArn": { "Ref": "ALBTargetGroupBlue" } } ] } }, "PrimaryTaskSet": { "Type": "AWS::ECS::PrimaryTaskSet", "Properties": { "Cluster": { "Ref": "ECSDemoCluster" }, "Service": { "Ref": "ECSDemoService" }, "TaskSetId": { "Fn::GetAtt": [ "BlueTaskSet", "Id" ] } } } } }

YAML

Parameters: Vpc: Type: 'AWS::EC2::VPC::Id' Subnet1: Type: 'AWS::EC2::Subnet::Id' Subnet2: Type: 'AWS::EC2::Subnet::Id' Transform: - 'AWS::CodeDeployBlueGreen' Hooks: CodeDeployBlueGreenHook: Properties: TrafficRoutingConfig: Type: TimeBasedCanary TimeBasedCanary: StepPercentage: 15 BakeTimeMins: 5 Applications: - Target: Type: 'AWS::ECS::Service' LogicalID: ECSDemoService ECSAttributes: TaskDefinitions: - BlueTaskDefinition - GreenTaskDefinition TaskSets: - BlueTaskSet - GreenTaskSet TrafficRouting: ProdTrafficRoute: Type: 'AWS::ElasticLoadBalancingV2::Listener' LogicalID: ALBListenerProdTraffic TargetGroups: - ALBTargetGroupBlue - ALBTargetGroupGreen Type: 'AWS::CodeDeploy::BlueGreen' Resources: ExampleSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Security group for ec2 access VpcId: !Ref Vpc SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 8080 ToPort: 8080 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 0.0.0.0/0 ALBTargetGroupBlue: Type: 'AWS::ElasticLoadBalancingV2::TargetGroup' Properties: HealthCheckIntervalSeconds: 5 HealthCheckPath: / HealthCheckPort: '80' HealthCheckProtocol: HTTP HealthCheckTimeoutSeconds: 2 HealthyThresholdCount: 2 Matcher: HttpCode: '200' Port: 80 Protocol: HTTP Tags: - Key: Group Value: Example TargetType: ip UnhealthyThresholdCount: 4 VpcId: !Ref Vpc ALBTargetGroupGreen: Type: 'AWS::ElasticLoadBalancingV2::TargetGroup' Properties: HealthCheckIntervalSeconds: 5 HealthCheckPath: / HealthCheckPort: '80' HealthCheckProtocol: HTTP HealthCheckTimeoutSeconds: 2 HealthyThresholdCount: 2 Matcher: HttpCode: '200' Port: 80 Protocol: HTTP Tags: - Key: Group Value: Example TargetType: ip UnhealthyThresholdCount: 4 VpcId: !Ref Vpc ExampleALB: Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer' Properties: Scheme: internet-facing SecurityGroups: - !Ref ExampleSecurityGroup Subnets: - !Ref Subnet1 - !Ref Subnet2 Tags: - Key: Group Value: Example Type: application IpAddressType: ipv4 ALBListenerProdTraffic: Type: 'AWS::ElasticLoadBalancingV2::Listener' Properties: DefaultActions: - Type: forward ForwardConfig: TargetGroups: - TargetGroupArn: !Ref ALBTargetGroupBlue Weight: 1 LoadBalancerArn: !Ref ExampleALB Port: 80 Protocol: HTTP ALBListenerProdRule: Type: 'AWS::ElasticLoadBalancingV2::ListenerRule' Properties: Actions: - Type: forward ForwardConfig: TargetGroups: - TargetGroupArn: !Ref ALBTargetGroupBlue Weight: 1 Conditions: - Field: http-header HttpHeaderConfig: HttpHeaderName: User-Agent Values: - Mozilla ListenerArn: !Ref ALBListenerProdTraffic Priority: 1 ECSTaskExecutionRole: Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Sid: '' Effect: Allow Principal: Service: ecs-tasks.amazonaws.com Action: 'sts:AssumeRole' ManagedPolicyArns: - 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy' BlueTaskDefinition: Type: 'AWS::ECS::TaskDefinition' Properties: ExecutionRoleArn: !GetAtt - ECSTaskExecutionRole - Arn ContainerDefinitions: - Name: DemoApp Image: 'nginxdemos/hello:latest' Essential: true PortMappings: - HostPort: 80 Protocol: tcp ContainerPort: 80 RequiresCompatibilities: - FARGATE NetworkMode: awsvpc Cpu: '256' Memory: '512' Family: ecs-demo ECSDemoCluster: Type: 'AWS::ECS::Cluster' Properties: {} ECSDemoService: Type: 'AWS::ECS::Service' Properties: Cluster: !Ref ECSDemoCluster DesiredCount: 1 DeploymentController: Type: EXTERNAL BlueTaskSet: Type: 'AWS::ECS::TaskSet' Properties: Cluster: !Ref ECSDemoCluster LaunchType: FARGATE NetworkConfiguration: AwsVpcConfiguration: AssignPublicIp: ENABLED SecurityGroups: - !Ref ExampleSecurityGroup Subnets: - !Ref Subnet1 - !Ref Subnet2 PlatformVersion: 1.4.0 Scale: Unit: PERCENT Value: 100 Service: !Ref ECSDemoService TaskDefinition: !Ref BlueTaskDefinition LoadBalancers: - ContainerName: DemoApp ContainerPort: 80 TargetGroupArn: !Ref ALBTargetGroupBlue PrimaryTaskSet: Type: 'AWS::ECS::PrimaryTaskSet' Properties: Cluster: !Ref ECSDemoCluster Service: !Ref ECSDemoService TaskSetId: !GetAtt - BlueTaskSet - Id