Contêineres simples de CI / CD na AWS

14

Estou usando o AWS Code Pipeline, Code Build para criar um novo contêiner Docker e enviá-lo para ECR.

Meu aplicativo é baseado em um único contêiner simples e direto. O que seria uma abordagem com menos atrito para reduzir o Container em execução atual e relançar um novo Container a partir do registro do ECS (saída do Code Build através do Code Pipeline).

Tentei o CloudFormation com dados do usuário do EC2, scripts personalizados de um lado e CloudFormation com ECS com definição de tarefa do outro lado (ainda não bem-sucedida). Sinto fortemente que deve haver uma abordagem mais óbvia e mais simples.

Naveen Vijay
fonte

Respostas:

16

Manteria as instâncias do contêiner do ECS (estou falando dos hosts do Docker - não gosto da terminologia da AWS aqui) e da implantação como duas coisas separadas.

Coloque sua pilha do ECS em funcionamento. Você pode gerenciá-lo através dos grupos CloudFormation e Auto-scaling, tudo bem. Basta pensar em seu cluster como uma plataforma onde você vai implantar a , não é algo que você precisa para redeploy .

Então, para CD, o método mais fácil é atualizar a definição de serviço para usar uma nova definição de tarefa e deixar o ECS rolling atualizar os contêineres para você.

Toda vez que uma tarefa é iniciada, o ECS executará a janela docker pull image: mesmo que tenha a imagem localmente para garantir que a versão mais recente dessa imagem: tag seja exibida. Portanto, a tag de imagem que você usa realmente não importa (não há necessidade de alterar a tag em todas as versões).

Isso significa que você pode criar o myimage: mais recente e repetidamente, a fim de implantá-lo facilmente.

O que você precisa é de uma definição de tarefa em que image = myimage: latest. Crie um serviço com essa definição de tarefa e sempre que o ECS iniciar uma tarefa (uma instância do seu serviço) será a mais recente "myimage: latest" que você criou.

A partir daí, você está perdendo apenas uma peça do quebra-cabeça. No CodeDeploy, você pode chamar algo, talvez uma função lambda, para criar uma nova revisão de sua definição de tarefa e atualizar seu serviço, e o ECS criará automaticamente novas tarefas para essa revisão e remova as tarefas antigas.

Um exemplo:

Vamos supor que você criou um serviço chamado MyService. Que você configurou esse serviço para executar 2 tarefas para a definição de tarefa MyTaskDefinition: 1 (revisão 1). Nessa definição de tarefa, você tem uma definição de contêiner cuja imagem está definida como "myimage: latest".

  1. Ontem, você construiu myimage: latest com o ID (SHA) 365d8f7bf565.
  2. Sua instância de contêiner ABC está executando uma tarefa chamada MyTaskDefinition- 1 -containerName-someLongId. quando você inspeciona esse contêiner, ele está executando a imagem "sha256: 365d8f7bf565 .........."
  3. Sua outra instância de contêiner DEF está executando outra tarefa. Ele tem um nome semelhante (apenas o ID é diferente), mas está executando a mesma imagem.
  4. Você faz uma alteração no seu repositório.
  5. O CodePipeline pega essa alteração, cria e publica a imagem no ECR.
  6. Essa nova imagem do Docker também é myimage: mais recente, mas seu ID (SHA) é f7ec5e54ac96
  7. Agora você precisa adicionar uma etapa ao seu pipeline para usar as funções Lambda e o AWS NodeJS SDK para fazer algumas chamadas para o cluster:
    1. Crie uma nova definição de tarefa (que será exatamente a mesma de antes). Isso será MyTaskDefinition: 2
    2. Atualize seu MyService para usar MyTaskDefinition: 2 (em vez de 1)
  8. O ECS criará novas tarefas. Os nomes dos contêineres serão MyTaskDefinition- 2 -containerName-someLongId. Ao inspecionar esses contêineres, você verá que eles estarão executando "sha256: f7ec5e54ac96 .......". Talvez você tenha duas tarefas na instância do contêiner ABC, talvez elas sejam pulverizadas (isso depende da configuração do seu serviço)
  9. Após algum tempo, o ECS removerá a tarefa antiga MyTaskDefinition-1-containerName-someLongId do ABC e DEF.

Nota: você realmente não precisa criar uma nova definição de tarefa. Se desejar, você pode recuperar a lista de tarefas do serviço e pará-las manualmente, uma a uma. Você deve esperar o ECS reiniciar uma tarefa antes de parar uma nova (ou seja: parar o primeiro contêiner, aguardar pelo ECS substituí-lo, parar o segundo contêiner). Quando o ECS reiniciar o contêiner, ele capturará a imagem mais recente: mais recente criada, conforme explicado anteriormente. Apenas acho que criar uma nova definição de tarefa é mais fácil e menos propenso a erros (não é necessária lógica para esperar e verificar, o ECS cuidará da atualização sem interrupção se você tiver uma nova definição de tarefa).

Alexandre
fonte
Incrível - eu chamaria sua resposta como o manual que faltava para o CI / CD do docker. Obrigado.
Naveen Vijay
3

Para um caso de uso simples descrito, sugiro verificar o Elastic Beanstalk for Docker, não é a solução mínima, como o uso simples de ECS, mas você pode se beneficiar de serviços configurados e gerenciados automaticamente, como ELB, EC2 AutoScale, monitoramento de funcionamento e muito mais.

Resumo de alto nível:

  1. Configure o Elastic Beanstalk para usar a tag específica myimage:
  2. Use o Code Pipeline / Build para criar, testar e promover a tag "testing"
  3. Acione a implantação do Elastic Beanstalk, que puxará a imagem promovida myimage: testada para todas as instâncias, diferentes estratégias de implantação disponíveis.

Essa abordagem baseada na reutilização da mesma tag; a abordagem alternativa geraria uma tag com o ID da compilação, por exemplo myimage: testing-42, isso exigirá a atualização do Elastic Beanstalk a cada vez com a nova tag, mas oferece um controle mais granular na revisão implantada.

rombob
fonte
0

Segundo pé de feijão elástico por sua simplicidade; é muito fácil de configurar e implantar.

Se você estiver familiarizado com o docker-compose, outra abordagem seria definir o docker-compose.yml e implantar diretamente no ECS com o ecs-cli.

AnthonyC
fonte