O blog da AWS

Implantações azul/verde no Amazon ECS usando o AWS CloudFormation e o AWS CodeDeploy

Por Ajay Mehta e Santosh Kale

Introdução

Muitos clientes usam o Amazon Elastic Container Service (ECS) para executar seus aplicativos de missão crítica baseados em containers na AWS. Esses clientes estão procurando uma implantação de mudanças segura nos aplicativos e na infraestrutura com o mínimo de tempo de inatividade, utilizando o AWS CodeDeploy e o AWS CloudFormation. O AWS CloudFormation oferece suporte nativo à execução de implantações azul/verde no ECS usando um hook do CodeDeploy, mas esse recurso vem com algumas considerações adicionais que são descritas aqui; uma delas é a incapacidade de usar pilhas aninhadas do CloudFormation e a outra é a incapacidade de atualizar as alterações nos aplicativos e na infraestrutura em uma única implantação. Por esses motivos, alguns clientes talvez não consigam usar o recurso de implantação azul/verde baseado em CloudFormation para o ECS. Além disso, precisam de mais controle sobre seu processo de implantação azul/verde e, portanto, gostariam que as implantações baseadas em CodeDeploy fossem realizadas fora do CloudFormation.

Neste blog, mostraremos como superar esses desafios utilizando o AWS CodeBuild e o AWS CodePipeline para automatizar a configuração do CodeDeploy para realizar implantações azul/verde no ECS. Também mostraremos como você pode implantar mudanças na infraestrutura e nos aplicativos por meio de um único CodePipeline para seus aplicativos executados no ECS.

A solução apresentada nesta postagem é apropriada se você estiver usando o CloudFormation para a implantação de sua infraestrutura de aplicativos. Para aplicativos CDK da AWS, consulte esta postagem que mostra como você pode habilitar implantações azul/verde no ECS usando pipelines de CDK.

Arquitetura de referência

O diagrama abaixo mostra um pipeline de referência do CICD para orquestrar uma implantação azul/verde para um aplicativo ECS. Nessa arquitetura de referência, presumimos que você esteja implantando mudanças na infraestrutura e no aplicativo por meio do mesmo pipeline.

Figura 1: pipeline do CICD para realizar a implantação azul/verde em um aplicativo executado no Cluster ECS Fargate

O pipeline consiste nas seguintes etapas:

1. Origem: No estágio de origem, o CodePipeline extrai o código do repositório de origem, como o AWS CodeCommit ou o GitHub, e organiza as alterações no S3.
2. Compilação: no estágio de construção, você usa o CodeBuild para empacotar os modelos do CloudFormation, realizar análises estáticas para o código do aplicativo, bem como para os modelos de infraestrutura do aplicativo, executar testes unitários, criar o código do aplicativo, gerar e publicar a imagem do container do aplicativo no ECR. Essas etapas podem ser executadas usando uma série de etapas do CodeBuild, conforme descrito no pipeline de referência acima.
3. Implantar infraestrutura: no estágio de implantação, você aproveita a ação de implantação com o CloudFormation via CodePipeline para implantar ou atualizar a infraestrutura do aplicativo. Nesse estágio, toda a infraestrutura do aplicativo é configurada usando pilhas aninhadas do CloudFormation. Isso inclui os componentes necessários para realizar implantações azul/verde no ECS usando o CodeDeploy, como o cluster ECS, o serviço ECS, a definição de tarefas, os listeners do Application Load Balancer (ALB), os grupos de destino, o aplicativo CodeDeploy, o grupo de implantação e outros.
4. Implantar aplicativo: no estágio de implantação do aplicativo, você usa a ação ECS-to-CodeDeploy do CodePipeline para implantar as alterações do seu aplicativo usando o recurso de implantação azul/verde do CodeDeploy. Ao aproveitar o CodeDeploy, você pode automatizar o fluxo de trabalho de implantação azul/verde para seus aplicativos executados no ECS, incluindo testes de seu aplicativo após a implantação e reversões automatizadas em caso de falhas nas implantações. O CodeDeploy também oferece maneiras diferentes de alternar o tráfego para seu aplicativo durante uma implantação azul/verde, oferecendo suporte às opções de mudança de tráfego Linear, Canary e All-at-Once. Mais informações sobre o fluxo de trabalho de implantação azul/verde do CodeDeploy para ECS podem ser encontradas aqui.

Considerações

Algumas considerações que talvez você precise avaliar ao implementar o pipeline de referência acima

1. Criação do grupo de implantação do CodeDeploy usando o CloudFormation
O CloudFormation atualmente não oferece suporte à criação direta dos componentes do CodeDeploy, pois esses componentes são criados e gerenciados pelo CloudFormation por meio do hook AWS::CodeDeploy::BlueGreen. Para contornar isso, você pode aproveitar um recurso personalizado do CloudFormation implementado por meio de uma função do AWS Lambda para criar o grupo de implantação do CodeDeploy com a configuração necessária. Uma implementação de referência de um recurso personalizado Lambda do CloudFormation pode ser encontrada na implementação de referência da nossa solução aqui.

2. Gerando os artefatos necessários de implantação do código (appspec.yml e taskdef.json)
Para aproveitar a ação CodeDeployToECS no CodePipeline, são necessários dois arquivos de entrada (appspec.yml e taskdef.json). Esses arquivos/artefatos são usados pelo CodePipeline para criar uma implantação do CodeDeploy que executa a implantação azul/verde em seu cluster ECS. O arquivo AppSpec especifica uma definição de tarefa do Amazon ECS para a implantação, um nome de container e mapeamento de portas usados para rotear o tráfego e as funções do Lambda que são executadas após os hooks do ciclo de vida da implantação. O nome do container deve ser um container na sua definição de tarefa do Amazon ECS. Para obter mais informações sobre isso, consulte trabalhando com revisões de aplicativos para o CodeDeploy. O taskdef.json é usado pelo CodePipeline para gerar dinamicamente uma nova revisão de definição da tarefa com a imagem atualizada do container do aplicativo no ECR. Esse é um recurso opcional suportado pela ação CodeDeployToECS, em que ele pode substituir automaticamente um valor de campo reservado (por exemplo, IMAGE1_NAME) para ImageUri no taskdef.json pelo Uri da imagem do container atualizada. Na solução de referência, não usamos esse recurso, pois nosso taskdef.json contém o ImageUri mais recente que planejamos implantar. Você pode aproveitar o CodeBuild para criar dinamicamente o taskdef.json a partir do ARN de definição de tarefa mais recente. Abaixo estão exemplos de comandos buildspec do CodeBuild que criam o taskdef.json a partir da definição de tarefa do ECS

build:
    commands:
        # Create appspec.yml for CodeDeploy deployment
        - python iac/code-deploy/scripts/update-appspec.py --taskArn ${TASKDEF_ARN} --hooksLambdaArn ${HOOKS_LAMBDA_ARN} --inputAppSpecFile 'iac/code-deploy/appspec.yml' --outputAppSpecFile '/tmp/appspec.yml'
        # Create taskdefinition for CodeDeploy deployment
        - aws ecs describe-task-definition --task-definition ${TASKDEF_ARN} --region ${AWS_REGION} --query taskDefinition >> taskdef.json
    artifacts:
        files:
            - /tmp/appspec.yml
            - /tmp/taskdef.json
        discard-paths: yes

Para gerar o appspec.yml, você pode aproveitar um python ou shell script e um campo reservado appspec.yml no seu repositório de origem para gerar dinamicamente o arquivo appspec.yml atualizado. Por exemplo, o trecho de código abaixo atualiza os valores do campo reservado appspec.yml para gerar um appspec.yml atualizado que é usado no estágio de implantação. Neste exemplo, definimos os valores do hook AfterAllowTestTraffic, o nome do container, os valores da porta do container da definição da tarefa e o ARN do Hooks do Lambda que é passado como entrada para o script.

contents = yaml.safe_load(file)
print(contents)
response = ecs.describe_task_definition(taskDefinition=taskArn)
contents['Hooks'][0]['AfterAllowTestTraffic'] = hooksLambdaArn
contents['Resources'][0]['TargetService']['Properties']['LoadBalancerInfo']['ContainerName'] = response['taskDefinition']['containerDefinitions'][0]['name']
contents['Resources'][0]['TargetService']['Properties']['LoadBalancerInfo']['ContainerPort'] = response['taskDefinition']['containerDefinitions'][0]['portMappings'][0]['containerPort']
contents['Resources'][0]['TargetService']['Properties']['TaskDefinition'] = taskArn

print('Updated appspec.yaml contents')
yaml.dump(contents, outputFile)

No cenário acima, a definição de tarefa existente é usada para criar o appspec.yml. Você também pode especificar um ou mais hooks baseados em lambda do CodeDeploy no appspec.yml para realizar vários testes automatizados como parte da sua implantação.

3. Atualizações na definição de tarefas do ECS
Para realizar implantações azul/verde em seu cluster ECS usando o CodeDeploy, o controlador de implantação no serviço ECS precisa ser configurado para CodeDeploy. Com essa configuração, sempre que houver uma atualização na definição da tarefa no serviço ECS (como ao criar uma nova imagem do aplicativo), a atualização resultará em uma falha. Basicamente, isso faz com que as atualizações do CloudFormation na infraestrutura do aplicativo falhem quando novas alterações no aplicativo são implantadas. Para evitar isso, você pode implementar um recurso personalizado baseado no CloudFormation que obtenha a versão anterior da definição da tarefa. Isso impede que o CloudFormation atualize o serviço ECS com a nova definição de tarefa quando a imagem do container do aplicativo é atualizada e, por fim, falhe na atualização da pilha. As atualizações nos serviços do ECS para novas revisões de tarefas são realizadas usando a implantação do CodeDeploy, conforme descrito em #2 acima. Usando esse mecanismo, você pode atualizar a infraestrutura do aplicativo junto com as alterações no código do aplicativo usando um único pipeline e, ao mesmo tempo, aproveitar a implantação do CodeDeploy azul/verde.

4. Passando a configuração entre diferentes estágios do pipeline
Para criar um pipeline automatizado que construa sua infraestrutura e execute uma implantação azul/verde para seu aplicativo, você precisará passar a configuração entre os diferentes estágios do seu pipeline. Por exemplo, quando você quiser criar o taskdef.json e o appspec.yml conforme mencionado na etapa #2, você precisa do ARN da definição de tarefa existente e do ARN do hook Lambda do CodeDeploy. Esses componentes são criados em diferentes estágios em seu pipeline. Para facilitar isso, você pode aproveitar as variáveis e namespaces do CodePipeline. Por exemplo, no estágio CodePipeline abaixo, definimos o valor das variáveis de ambiente TASKDEF_ARN e HOOKS_LAMBDA_ARN ao buscar esses valores em um estágio diferente no mesmo pipeline em que criamos esses componentes. Uma opção alternativa é usar o AWS System Manager Parameter Store para armazenar e recuperar essas informações. Informações adicionais sobre as variáveis do CodePipeline e como usá-las podem ser encontradas em nossa documentação aqui.

- Name: BuildCodeDeployArtifacts
  Actions:
	- Name: BuildCodeDeployArtifacts
	  ActionTypeId:
		Category: Build
		Owner: AWS
		Provider: CodeBuild
		Version: "1"
	  Configuration:
		ProjectName: !Sub "${pApplicationName}-CodeDeployConfigBuild"
		EnvironmentVariables: '[{"name": "TASKDEF_ARN", "value": "#{DeployInfraVariables.oTaskDefinitionArn}", "type": "PLAINTEXT"},{"name": "HOOKS_LAMBDA_ARN", "value": "#{DeployInfraVariables.oAfterInstallHookLambdaArn}", "type": "PLAINTEXT"}]'
	  InputArtifacts:
		- Name: Source
	  OutputArtifacts:
		- Name: CodeDeployConfig
	  RunOrder: 1

Solução de referência:

Como parte desta postagem, fornecemos uma solução de referência que executa uma implantação azul/verde para um exemplo de aplicativo baseado em Java executado no ECS Fargate usando CodePipeline e CodeDeploy. A implementação de referência fornece modelos do CloudFormation para criar os componentes necessários do CodeDeploy, incluindo recursos personalizados para implantação azul/verde no Amazon ECS, bem como a infraestrutura de aplicativos usando pilhas aninhadas. A solução também fornece uma implementação de referência do CodePipeline que orquestra totalmente a criação, o teste e a implantação azul/verde do aplicativo. Na solução, também demonstramos como você pode orquestrar a implantação azul/verde usando padrões de mudança de tráfego Linear, Canary e All-at-Once. Você pode baixar a implementação de referência aqui. Você pode personalizar ainda mais essa solução criando seus próprios hooks de ciclo de vida do CodeDeploy e executando tarefas adicionais de configuração e validação de acordo com as necessidades do seu aplicativo. Também recomendamos que você analise nossa Arquitetura de Referência de Implantação do pipeline (DPRA) e aprimore seus canais de entrega incluindo etapas e ações adicionais que atendam às suas necessidades.

Conclusão:

Neste blog post, explicamos como você pode automatizar a implantação azul/verde de seu aplicativo baseado em ECS usando pilhas aninhadas do AWS CodePipeline, do AWS CodeDeploy e do AWS CloudFormation. Analisamos o que você precisa considerar para automatizar a implantação azul/verde para seu aplicativo executado em seu cluster ECS usando o CodePipeline e o CodeDeploy e como você pode enfrentar esses desafios com alguns scripts e recursos CloudFormation personalizados baseados em Lambda. Esperamos que isso ajude você a configurar implantações azul/verde em seu aplicativo baseado em ECS usando o CodePipeline e o CodeDeploy.

Este blog é uma tradução do blog original em inglês (link aqui).

Autores

Ajay Mehta é arquiteto principal de infraestrutura de nuvem para serviços profissionais da AWS. Ele trabalha com clientes corporativos para acelerar a adoção da nuvem por meio da criação de landing zones e da transformação das organizações de TI para que adotem práticas operacionais em nuvem e operações ágeis. Quando não está trabalhando, ele gosta de passar tempo com a família, viajar e explorar novos lugares.

 

Santosh Kale é arquiteto sênior de DevOps na AWS Professional Services, apaixonado por Kubernetes e GenAI-AI/ML. Como SME de DevOps e MLOps, ele é membro ativo da equipe de Containers na AWS, profundidade em MLOps e ajuda clientes corporativos de alta tecnologia em suas jornadas transformadoras por meio da adoção de DevOps/MLOps e tecnologias de modernização de containers. Além de Cloud, ele é um amante da natureza e gosta de passar bons momentos visitando espaços cênicos ao redor do mundo.

Tradutores

Marcelo Moras é Arquiteto de Soluções na AWS atendendo clientes Enterprise com foco em mercado financeiro. Com mais de 15 anos de experiência atuando com infraestrutura, administração de sistemas, redes, containers e segurança.

Daniel Abib é Senior Solution Architect na AWS, com mais de 25 anos trabalhando com gerenciamento de projetos, arquiteturas de soluções escaláveis, desenvolvimento de sistemas e CI/CD, microsserviços, arquitetura Serverless & Containers e segurança. Ele trabalha apoiando clientes corporativos, ajudando-os em sua jornada para a nuvem.

https://www.linkedin.com/in/danielabib/