
Seria legal se a implantação de copiar e colar fosse uma coisa do passado, mas, infelizmente, as coisas são diferentes. Acontece que os desenvolvedores preferem esse método de entrega. Embora agora escreva um artigo sobre por que isso não é agitado, mas você sabe tudo sem mim. Com uma tendência para a arquitetura sem servidor, os pipelines de CI / CD desempenham um papel importante na entrega de aplicativos. Também escrevi sobre eles no artigo " 3 melhores dicas para o seu próximo projeto sem servidor ".
Há muito tempo que me interesso pelo tópico da CI e do CD e, pela primeira vez, me deparei com ele há vários anos graças ao TeamCity. Atualmente, o TeamCity ainda é usado para a maioria dos nossos pipelines de CI / CD. O TeamCity funciona muito bem, não tenho nada contra, mas sempre me esforço para melhorar o trabalho. Por exemplo, seria bom coletar pipelines na forma de código - essa é uma das áreas em que o TeamCity não é tão bom.
Aprendi as ferramentas de integração e entrega na AWS há algum tempo e, embora usemos o CodeDeploy para outro projeto que funciona no EC2, ainda não implantei um projeto sem servidor com eles. Depois de revisar as ferramentas novamente, notei o seguinte: agora existe uma função de integração integrada para implantar o CloudFormation e o Lambda, presumivelmente com base no SAM AWS; usamos a estrutura sem servidor - ela gera modelos CloudFormation, mas não funciona imediatamente com as ferramentas da AWS.
Preparação
Uso os seguintes serviços da AWS: EC2, Docker, ECR, S3, IAM, CodeBuild, CodePipeline, CloudWatch, CloudTrail. Para acompanhar, é necessário entender pelo menos em um nível básico o que cada um desses serviços faz.
Basicamente, escrevo o código do lado do servidor no .NET, e este guia também se baseia nessa plataforma. Nenhuma das imagens pré-construídas do CodeBuild possui um tempo de execução .NET e NodeJS ao mesmo tempo (o NodeJS é necessário para a estrutura sem servidor). Se as funções do Lambda estiverem escritas no NodeJS, a configuração do pipeline de implantação será muito mais simples, pois esse é o único ambiente de tempo de execução necessário para a instalação em uma imagem do Docker (se você preferir, pule a maior parte do manual). Por um segundo, essa foi minha primeira experiência com contêineres e estou feliz em aprender algo novo.
Atrevo-me a supor que seu código está em um determinado repositório, por exemplo, git. Para orientação, simplesmente carregamos no S3 um arquivo contendo um pacote de código para implantação; como você recebe depende de você. Tomando meu trabalho como base, você sempre pode ir além, conectando seu pipeline a repositórios como o github ou o CodeCommit.
1. Crie uma instância do EC2 e instale o Docker
Execute uma instância padrão do AWS Linux 2 EC2 - isso deve ficar claro sem explicação. Efetue login e instale o Docker usando os comandos:
sudo yum update -y sudo amazon-linux-extras install docker sudo service docker start
Você também precisa adicionar o usuário ec2 ao grupo docker para executar comandos do Docker sem usar o sudo:
sudo usermod -a -G docker ec2-user
Quando o comando for concluído, efetue logout e logon novamente na instância do EC2 para que o usuário do ec2 receba novas permissões. Verifique se o usuário ec2 executa os comandos do Docker sem o sudo:
docker info

Saída do docker info
2. Crie uma imagem do Docker e coloque-a no ECR
Suponha que a etapa anterior seja bem-sucedida; A próxima etapa é criar uma imagem do Docker que se encaixe no ECR. A AWS oferece imagens básicas para o CodeBuild no github e isso facilita a criação de sua própria imagem.
Também publiquei a imagem no github - caso você não queira seguir estas etapas para criar sua própria: https://github.com/effectivedigital/serverless-deployment-image
Copie as imagens e acesse o diretório .NET Core 2.1:
git clone https://github.com/aws/aws-codebuild-docker-images.git cd aws-codebuild-docker-images cd ubuntu/dot-net/core-2.1/
Abra o Dockerfile no seu editor de texto preferido:
nano Dockerfile
Adicione os comandos para instalar o NodeJS e a estrutura sem servidor no final de outros comandos já disponíveis no Dockerfile. Eu obtive a maioria desses comandos de uma imagem do NodeJS Docker no mesmo repositório da AWS:
# Install Node Dependencies ENV NODE_VERSION="10.14.1" # gpg keys listed at https://github.com/nodejs/node#release-team RUN set -ex \ && for key in \ 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \ B9AE9905FFD7803F25714661B63B535A4C206CA9 \ 77984A986EBC2AA786BC0F66B01FBB92821C587A \ 56730D5401028683275BD23C23EFEFE93C4CFFFE \ 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \ FD3A5288F042B6850C66B31F09FE44734EB7990E \ 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \ C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \ DD8F2338BAE7501E3DD5AC78C273792F7D83545D \ 4ED778F539E3634C779C87C6D7062848A1AB005C \ A48C2BEE680E841632CD4E44F07496B3EB3C1762 \ ; do \ gpg - keyserver hkp://p80.pool.sks-keyservers.net:80 - recv-keys "$key" || \ gpg - keyserver hkp://ipv4.pool.sks-keyservers.net - recv-keys "$key" || \ gpg - keyserver hkp://pgp.mit.edu:80 - recv-keys "$key" ; \ done RUN set -ex \ && wget "https://nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" -O node-v$NODE_VER$ && wget "https://nodejs.org/download/release/v$NODE_VERSION/SHASUMS256.txt.asc" -O SHASUMS256.txt.asc \ && gpg - batch - decrypt - output SHASUMS256.txt SHASUMS256.txt.asc \ && grep " node-v$NODE_VERSION-linux-x64.tar.gz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local - strip-components=1 \ && rm "node-v$NODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ && rm -fr /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN npm set unsafe-perm true CMD [ "node" ] # Install Serverless Framework RUN set -ex \ && npm install -g serverless
Agora, coletamos e marcamos a imagem:
docker build -t aws/codebuild/dot-net .
Depois de concluir a montagem, execute a imagem - verifique se tudo funciona e se a estrutura sem servidor está instalada corretamente:
docker run -it --entrypoint sh aws/codebuild/dot-net -c bash sls -v

Executando sls -v
dentro de um contêiner novo
Em seguida, crie o repositório no ECR usando a CLI da AWS. Após executar o comando, o novo repositório será exibido no console da AWS:
aws ecr create-repository --repository-name codebuild-dotnet-node

Resposta da CLI da AWS para criar repositório na ECR

Agora marque a imagem aws / codebuild / dot-net criada anteriormente com o valor repositoryUri da etapa anterior:
docker tag aws/codebuild/dot-net <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node
Execute o comando get-login para obter a linha de comandos de autenticação de login do docker para o registro de contêiner:
aws ecr get-login --no-include-email

Execute o comando docker login emitido pelo comando get-login durante a última etapa.
docker login -u AWS -p eyJwYXlsb2FkIjoiNGZnd0dSaXM1L2svWWRLMmhJT1c0WWpOZEcxamJFeFJOK2VvT0Y5[...] https://<ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com
Se o login for bem-sucedido, coloque a imagem da janela de encaixe no repositório criado no ECR. Isso pode levar alguns minutos (dependendo do tamanho da imagem concluída).
docker push <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node

O Docker no EC2 cria nossa imagem

Imagem do Docker em ECR
Então, podemos abrir o acesso à imagem do ECR para qualquer pessoa. A permissão deve ser bloqueada no ambiente de trabalho, mas neste exemplo nós a abriremos. Vá para a guia permissões no console da AWS, selecione "Alterar política JSON" e insira o seguinte elemento na política:
{ "Version": "2008-10-17", "Statement": [ { "Sid": "EnableAccountAccess", "Effect": "Allow", "Principal": "*", "Action": [ "ecr:BatchCheckLayerAvailability", "ecr:BatchGetImage", "ecr:DescribeImages", "ecr:DescribeRepositories", "ecr:GetAuthorizationToken", "ecr:GetDownloadUrlForLayer", "ecr:GetRepositoryPolicy", "ecr:ListImages" ] } ] }
3. Crie um pipeline
É hora de coletar o pipeline. Para simplificar o processo, torná-lo multi-implantável e manter a forma desastrosa da arquitetura sem servidor, construí um pipeline usando a estrutura sem servidor. Você pode obter o mesmo resultado criando no CloudFormation.
Não copiarei a fonte inteira do meu arquivo serverless.yml - copie-o do github: https://github.com/effectivedigital/serverless-deployment-pipeline
Confira o modelo sem servidor para ver exatamente o que ele fará, mas, resumidamente, ele configura os seguintes itens:
- 3 segmentos S3
- Política de 1 segmento
- 3 funções do IAM
- 1 projeto CodeBuild
- 1 pipeline CodePipeline
- 1 evento CloudWatch
- 1 rastreamento do CloudTrail
Atualize o DockerImageArn para sua imagem no ECR. Se você deseja criar pacotes de implantação com um nome diferente de Deployment.zip , atualize também DeploymentFilename :
DockerImageArn: <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node:latest DeploymentFilename: Deployment.zip
É isso aí, o pipeline está pronto para implantação. Execute o comando de implantação sem servidor e aguarde até que ele esteja configurado:
sls deploy -v

Pilha de estrutura sem servidor criada CloudFormation

Criado pelo pipeline da estrutura sem servidor CodePipeline

Criado pelo projeto de estrutura sem servidor Projeto CodeBuild
4. Adicione buildSpec.yml ao seu aplicativo
Quando o CodePipeline detecta uma alteração no arquivo de implantação no S3, ele informa ao CodeBuild para iniciar e tentar criar e implantar o aplicativo. No entanto, o CodeBuild também deve saber quais comandos devem ser executados para criar e implantar o aplicativo, e o buildSpec.yml contém instruções que o CodeBuild seguirá.
Criei um aplicativo "Hello world" muito simples, que inclui um arquivo buildSpec.yml de exemplo que você pode usar: https://github.com/effectivedigital/serverless-deployment-app
Ou crie o arquivo buildSpec.yml em aplicativos existentes e preencha-o de acordo com as instruções abaixo:
version: 0.2 phases: pre_build: commands: - chmod a+x * build: commands: - ./build.sh post_build: commands: - sls deploy -v -s $STAGE
5. Verificação de Pipeline
Agora tudo está pronto para o primeiro lançamento do seu pipeline. Crie um pacote chamado Deployment.zip , ele deve incluir todos os arquivos do aplicativo sem servidor e o arquivo buildSpec.yml.
Após alguns instantes, o CloudTrail deve registrar um evento PutObject e ativar a regra de evento CloudWatch, que ativa o gatilho CodePipeline.

Deployment.zip inicializado no S3

CodePipeline lançado, a compilação está ativada
Se passarmos aos detalhes da etapa do AWS CodeBuild, podemos ver o processo de compilação e implantação:

O CodeBuild receberá saída da imagem de compilação e implantação do Docker

Implantação bem-sucedida!
O novo aplicativo implantado pelo nosso pipeline também aparece no CloudFormation:

Você pode testar o ponto de extremidade da API criado em nosso aplicativo simples (a URL está na saída do CodeBuild ou na API do Gateway) e verifique se o aplicativo funciona com êxito:

Carteiro para chamar API
Breves conclusões
O CodePipeline permite criar um pipeline de CI / CD escalável, flexível e barato, ajudando a resolver alguns problemas associados aos pipelines tradicionais criados nos servidores.
Eu gostaria de ir além e adicionar testes de unidade após a implantação à mistura, mas o tópico merece um artigo separado - e esta é uma ocasião para nos ler no futuro!