Come costruire una pipeline CI / CD Serverless su AWS

Tutti vorremmo pensare che i tempi delle distribuzioni copia / incolla sono passati da tempo, purtroppo non è così ed è ancora il metodo di consegna preferito per alcuni sviluppatori. Potrei facilmente scrivere un intero articolo sul perché è negativo, ma penso che sia piuttosto autoesplicativo. Con la tendenza verso architetture senza server, le pipeline CI / CD svolgono un ruolo importante nella consegna delle applicazioni. Sono anche presenti nei miei 3 migliori consigli per il tuo prossimo progetto senza server.

Integrazione e consegna continue sono qualcosa che mi ha interessato per molto tempo e ho immerso le dita dei piedi in acqua con TeamCity diversi anni fa. Oggi utilizziamo TeamCity per la maggior parte delle nostre pipeline CI / CD. TeamCity funziona alla grande e non ho nulla contro di esso, ma cerco sempre come migliorare ciò che facciamo. Una di queste cose è la possibilità di costruire le nostre pipeline come codice, che è una delle cose in cui TeamCity non è così bravo.

È passato un po 'di tempo da quando ho esaminato in dettaglio gli strumenti di integrazione e consegna disponibili da AWS e mentre utilizziamo CodeDeploy per un altro progetto che funziona su EC2, non li avevo mai usati per distribuire un progetto senza server. Dopo essere stato aggiornato con gli strumenti che ho visto, ora c'è l'integrazione nativa per la distribuzione di CloudFormation e Lambda - presumibilmente con SAM di AWS - usiamo il framework serverless e sebbene generi modelli CloudFormation, non funziona con gli strumenti in AWS.

Prepararsi

I servizi AWS che userò sono EC2, Docker, ECR, S3, IAM, CodeBuild, CodePipeline, CloudWatch, CloudTrail. Dovrai comprendere almeno a un livello base ciò che ciascuno di questi servizi fa per seguire.

Scrivo principalmente codice back-end in .NET, su cui si basa questo tutorial. Nessuna delle immagini CodeBuild precompilate presenta sia runtime .NET che NodeJS (NodeJS è richiesto per il framework senza server). Se le tue funzioni Lambda sono scritte in NodeJS, il processo di impostazione di una pipeline di distribuzione diventa molto più semplice in quanto è l'unico runtime che devi installare sull'immagine Docker (potresti potenzialmente saltare molto di questo tutorial). Devo anche menzionare, questa era la mia prima volta a conoscere i contenitori, quindi ero entusiasta di imparare qualcosa di nuovo.

Suppongo anche che il tuo codice risieda in un repository di qualche tipo come git. Per questo tutorial cariceremo solo un file su S3 che contiene un pacchetto del codice da distribuire - come lo ottieni dipende da te. Puoi sempre andare oltre con quello che ho creato collegando la tua pipeline a repository come github o CodeCommit.

1. Creare un'istanza EC2 e installare Docker

Inizia creando un'istanza standard di AWS Linux 2 EC2, che dovrebbe essere autoesplicativa. Accedi e installa Docker con questi comandi:

sudo yum update -y
finestra mobile di installazione sudo amazon-linux-extra
inizio della finestra mobile di servizio sudo

Dovremo anche aggiungere l'utente ec2 al gruppo docker in modo da poter eseguire i comandi Docker senza usare sudo:

sudo usermod -a -G docker ec2-user

Dopo aver eseguito il comando, disconnettersi e riconnettersi all'istanza EC2 in modo che l'utente ec2 possa assumere le nuove autorizzazioni. Quindi verifica che l'utente ec2 possa eseguire i comandi Docker senza sudo:

informazioni sulla finestra mobile
Output del comando info finestra mobile

2. Creare un'immagine Docker e passare a ECR

Supponendo che il passaggio precedente abbia avuto esito positivo, il passaggio successivo consiste nel creare l'immagine Docker e trasferirla in ECR. AWS fornisce le immagini di base per CodeBuild su github, il che semplifica la creazione della nostra immagine.

Ho anche pubblicato la mia immagine su github se non vuoi seguire i passaggi seguenti per crearne una tua: https://github.com/effectivedigital/serverless-deployment-image

Inizia clonando le immagini e navigando nella directory .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 /

Apri Dockerfile nel tuo editor di testo preferito:

nano Dockerfile

Aggiungi i comandi per installare NodeJS e il framework senza server alla fine degli altri comandi già in Dockerfile. Sono stato in grado di ottenere la maggior parte di questi comandi dall'immagine Docker di NodeJS dallo stesso repository di AWS:

# Installa dipendenze nodi
ENV NODE_VERSION = "10.14.1"
# chiavi gpg elencate su https://github.com/nodejs/node#release-team
RUN set -ex \
 && per digitare \
 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
 B9AE9905FFD7803F25714661B63B535A4C206CA9 \
 77984A986EBC2AA786BC0F66B01FBB92821C587A \
 56730D5401028683275BD23C23EFEFE93C4CFFFE \
 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
 FD3A5288F042B6850C66B31F09FE44734EB7990E \
 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \
 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
 DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
 4ED778F539E3634C779C87C6D7062848A1AB005C \
 A48C2BEE680E841632CD4E44F07496B3EB3C1762 \
 ; fare \
 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"; \
 fatto
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 impostato come non sicuro perm
CMD ["nodo"]
# Installa Serverless Framework
RUN set -ex \
 && npm installa -g senza server

Ora l'immagine può essere costruita e taggata:

finestra mobile build -t aws / codebuild / dot-net.

Al termine della costruzione, è possibile eseguire l'immagine per confermare che tutto funziona e che serverless è stato installato correttamente:

docker run -it --entrypoint sh aws / codebuild / dot-net -c bash
sls -v
Esecuzione di sls -v all'interno del contenitore appena creato

Successivamente creeremo un repository in ECR utilizzando l'interfaccia della riga di comando di AWS. Dopo l'esecuzione del comando, il nuovo repository sarà visibile nella Console AWS:

aws ecr create-repository --repository-name codebuild-dotnet-node
Risposta dall'interfaccia della riga di comando di AWS dopo aver creato il repository in ECRIl repository appena creato in ECR

Ora taggeremo l'immagine aws / codebuild / dot-net che abbiamo creato in precedenza con il valore repositoryUri del passaggio precedente:

tag docker aws / codebuild / dot-net  .dkr.ecr.ap-sud-est-2.amazonaws.com / codebuild-dotnet-node

Eseguire il comando get-login per ottenere la stringa di comando di autenticazione di accesso docker per il registro del contenitore:

aws ecr get-login --no-include-email
Il comando di accesso per l'autenticazione in ECR

Eseguire il comando login docker che è stato restituito eseguendo il comando get-login nell'ultimo passaggio.

login docker -u AWS -p eyJwYXlsb2FkIjoiNGZnd0dSaXM1L2svWWRLMmhJT1c0WWpOZEcxamJFeFJOK2VvT0Y5 [...] https: //  .dkr.ecr.-south.com 2.

Se l'accesso ha esito positivo, ora possiamo trasferire la nostra immagine docker nel repository creato in ECR. Potrebbero essere necessari alcuni minuti a seconda delle dimensioni dell'immagine completata:

docker push  .dkr.ecr.ap-sud-est-2.amazonaws.com / codebuild-dotnet-node
Docker su EC2 sta creando la nostra immagineL'immagine Docker in ECR

Una volta creata l'immagine, consentiremo a chiunque di accedere all'immagine da ECR. L'autorizzazione dovrebbe essere bloccata in un ambiente di produzione, ma per questo esempio consentiremo che sia aperta. Vai alla scheda Autorizzazioni nella Console AWS, seleziona Modifica criterio JSON e incolla questo criterio:

{
  "Versione": "2008-10-17",
  "Dichiarazione": [
    {
      "Sid": "EnableAccountAccess",
      "Effetto": "Consenti",
      "Principal": "*",
      "Azione": [
        "ECR: BatchCheckLayerAvailability",
        "ECR: BatchGetImage",
        "ECR: DescribeImages",
        "ECR: DescribeRepositories",
        "ECR: GetAuthorizationToken",
        "ECR: GetDownloadUrlForLayer",
        "ECR: GetRepositoryPolicy",
        "ECR: ListImages"
      ]
    }
  ]
}

3. Crea la tua pipeline

È tempo di costruire la pipeline. Per renderlo più semplice e ripetutamente implementabile, e nella vera forma di architetture senza server, ho costruito la pipeline usando il framework senza server. Puoi anche ottenere lo stesso risultato costruendolo in CloudFormation.

Non incollerò l'intera fonte dal mio file serverless.yml, puoi invece clonarla da github: https://github.com/effectivedigital/serverless-deployment-pipeline

Dai un'occhiata al modello senza server per capire esattamente cosa farà, ma in breve sta andando alla configurazione:

  • 3 secchi S3
  • 1x politica della benna
  • 3 ruoli IAM
  • 1x progetto CodeBuild
  • 1x CodePipeline Pipeline
  • 1x evento CloudWatch
  • 1x CloudTrail Trail

Una volta clonato, aggiorna DockerImageArn alla tua immagine in ECR. Se stai creando pacchetti di distribuzione con un nome file diverso da Deployment.zip, aggiorna anche DeploymentFilename:

DockerImageArn:  .dkr.ecr.ap-sud-est-2.amazonaws.com / codebuild-dotnet-node: ultimo
DeploymentFilename: Deployment.zip

Questo è tutto, la pipeline è ora pronta per l'implementazione. Esegui il comando deploy senza server e attendi che tutto sia configurato per te:

sls deploy -v
Il nostro stack CloudFormation creato dal framework serverlessPipeline CodePipeline creata dal framework serverlessIl progetto CodeBuild creato dal framework serverless

4. Aggiungi buildSpec.yml alla tua applicazione

Quando CodePipeline rileva una modifica al file di distribuzione in S3, indica a CodeBuild di eseguire e tentare di compilare e distribuire l'applicazione. Detto questo, CodeBuild deve anche sapere quali comandi devono essere eseguiti per compilare e distribuire l'applicazione, buildSpec.yml ha le istruzioni che CodeBuild segue.

Ho creato un'applicazione ciao mondo davvero semplice che include il file buildSpec.yml di esempio che puoi includere: https://github.com/effectivedigital/serverless-deployment-app

In alternativa, puoi creare un file buildSpec.yml nelle tue applicazioni esistenti e popolarlo con le istruzioni seguenti:

versione: 0.2
fasi:
  pre_build:
    comandi:
      - chmod a + x *
  costruire:
    comandi:
      - ./build.sh
  post_build:
    comandi:
      - sls deploy -v -s $ STAGE

5. Test della pipeline

Ora è tutto pronto per eseguire la pipeline per la prima volta. Creare un pacchetto chiamato Deployment.zip che dovrebbe includere tutti i file per l'applicazione senza server e il file buildSpec.yml.

Dopo alcuni istanti CloudTrail dovrebbe registrare l'evento PutObject, attivare una regola di eventi CloudWatch che attiverà quindi CodePipeline per iniziare l'esecuzione.

Deployment.zip è stato caricato su S3CodePipeline è iniziata e la compilazione è in corso

Se facciamo clic nei dettagli del passaggio AWS CodeBuild, possiamo esaminare l'avanzamento della creazione e della distribuzione:

CodeBuild otterrà l'output dall'immagine Docker eseguendo la compilazione e la distribuzioneLa nostra distribuzione ha avuto successo!

La nuova app che è stata distribuita dalla nostra pipeline è visibile anche in CloudFormation:

Possiamo testare l'endpoint dell'API creato nella nostra semplice app (l'URL si trova nell'output CodeBuild o nel gateway API) e verificare che la nostra app funzioni correttamente:

Utilizzo di Postman per invocare la nostra API

Sommario

CodePipeline consente di creare una pipeline CI / CD scalabile, flessibile ea basso costo e aiuta a risolvere alcuni dei problemi associati alle pipeline tradizionali create sui server.

Mi piacerebbe fare un ulteriore passo avanti e aggiungere test unitari nel mix una volta completata la distribuzione, anche se garantisce un articolo tutto suo - qualcosa per cui essere sintonizzati in futuro!

Unisciti alla nostra community Slack e leggi i nostri argomenti settimanali su Faun ⬇

Se questo post ti è stato utile, fai clic sul pulsante clap below in basso alcune volte per mostrare il tuo supporto per l'autore! ⬇