Comment créer un pipeline CI / CD sans serveur sur AWS

Nous aimerions tous penser que l’époque des déploiements copier / coller est révolue. Malheureusement, ce n’est pas le cas et reste le mode de diffusion préféré de certains développeurs. Je pourrais facilement écrire un article entier pour expliquer pourquoi c'est mauvais, mais je pense que c'est assez explicite. Avec la tendance aux architectures sans serveur, les pipelines CI / CD jouent un rôle majeur dans la livraison de vos applications. Ils figurent également dans mes 3 meilleurs conseils pour votre prochain projet sans serveur.

L’intégration et la livraison continues sont quelque chose qui m’intéresse depuis longtemps et j’ai plongé pour la première fois dans l’eau avec TeamCity il ya plusieurs années. Nous utilisons toujours TeamCity pour la majorité de nos pipelines CI / CD aujourd'hui. TeamCity fonctionne très bien et je n’ai rien contre, mais je cherche toujours à améliorer ce que nous faisons. L’une de ces choses est de pouvoir construire nos pipelines sous forme de code - une des choses pour lesquelles TeamCity n’est pas si bon.

Cela fait longtemps que je n’ai pas examiné en détail les outils d’intégration et de livraison disponibles sur AWS et, bien que nous utilisions CodeDeploy pour un autre projet fonctionnant sur EC2, je ne les utilisais jamais pour déployer un projet sans serveur. Après avoir repris connaissance avec les outils, j'ai constaté qu'il existe désormais une intégration native pour le déploiement de CloudFormation et de Lambda, vraisemblablement avec AWS 'SAM. Nous utilisons le framework sans serveur. Bien qu'il génère des modèles CloudFormation, il ne fonctionne pas immédiatement avec les outils. dans AWS.

Se préparer

Les services AWS que je vais utiliser sont EC2, Docker, ECR, S3, IAM, CodeBuild, CodePipeline, CloudWatch, CloudTrail. Vous devrez au moins comprendre le niveau de base de ce que chacun de ces services doit suivre.

J'écris principalement du code backend dans .NET, sur lequel ce tutoriel est basé. Aucune des images CodeBuild prédéfinies ne comporte à la fois des environnements d'exécution .NET et NodeJS (NodeJS est requis pour la structure sans serveur). Si vos fonctions Lambda sont écrites dans NodeJS, le processus de configuration d'un pipeline de déploiement devient beaucoup plus simple car c'est le seul runtime dont vous avez besoin installé sur votre image Docker (vous pourriez potentiellement ignorer beaucoup de ce tutoriel). Je devrais également mentionner que c’était la première fois que je me familiarisais avec les conteneurs et que j’étais excité d’apprendre quelque chose de nouveau.

Je suppose également que votre code réside dans un référentiel tel que git. Pour ce tutoriel, nous allons simplement télécharger un fichier sur S3 qui contient un paquet du code à déployer - la façon dont vous l'obtenez est à vous. Vous pouvez toujours aller plus loin avec ce que j'ai construit en connectant votre pipeline à des référentiels tels que github ou CodeCommit.

1. Créez une instance EC2 et installez Docker

Commencez par lancer une instance AWS Linux 2 EC2 standard, qui devrait être explicite. Connectez-vous et installez Docker avec ces commandes:

sudo yum update -y
sudo amazon-linux-extras installe le menu fixe
sudo service docker start

Nous devrons également ajouter l'utilisateur ec2 au groupe de docker pour pouvoir exécuter les commandes de Docker sans utiliser sudo:

sudo usermod -a -G docker ec2-user

Après avoir exécuté la commande, déconnectez-vous et reconnectez-vous à votre instance EC2 afin que l'utilisateur ec2 puisse assumer les nouvelles autorisations. Ensuite, vérifiez que ec2-user peut exécuter les commandes Docker sans sudo:

info docker
Sortie de la commande docker info

2. Construisez l'image de Docker et appuyez sur ECR

En supposant que l'étape ci-dessus ait abouti, l'étape suivante consiste à créer l'image Docker et à la transmettre à ECR. AWS fournit les images de base de CodeBuild sur github, ce qui facilite la création de notre propre image.

J’ai également publié mon image sur github si vous ne souhaitez pas suivre les étapes ci-dessous pour créer la vôtre: https://github.com/effectivedigital/serverless-deployment-image

Commencez par cloner les images et naviguez dans le répertoire .NET Core 2.1:

clone de git https://github.com/aws/aws-codebuild-docker-images.git
cd aws-codebuild-docker-images
cd ubuntu / dot-net / core-2.1 /

Ouvrez Dockerfile dans votre éditeur de texte préféré:

nano Dockerfile

Ajoutez les commandes pour installer NodeJS et le framework sans serveur à la fin des autres commandes déjà présentes dans Dockerfile. J'ai pu obtenir la majorité de ces commandes à partir de l'image NodeJS Docker à partir du même référentiel à partir d'AWS:

# Installer les dépendances de nœuds
ENV NODE_VERSION = "10.14.1"
Nombre de clés gpg répertoriées sur https://github.com/nodejs/node#release-team
RUN set -ex \
 && pour la clé \
 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
 B9AE9905FFD7803F25714661B63B535A4C206CA9 \
 77984A986EBC2AA786BC0F66B01FBB92821C587A \
 56730D5401028683275BD23C23EFEFE93C4CFFFE \
 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
 FD3A5288F042B6850C66B31F09FE44734EB7990E \
 8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \
 C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
 DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
 4ED778F539E3634C779C87C6D7062848A1AB005C \
 A48C2BEE680E841632CD4E44F07496B3EB3C1762 \
 ; faire \
 gpg - serveur de clés hkp: //p80.pool.sks-keyservers.net: 80 - recv-keys "$ key" || \
 gpg - serveur de clés hkp: //ipv4.pool.sks-keyservers.net - recv-keys "$ key" || \
 gpg - serveur de clés hkp: //pgp.mit.edu: 80 - recv-keys "$ key"; \
 terminé
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 - décrypter - sortie SHASUMS256.txt SHASUMS256.txt.asc \
 && grep "noeud-v $ NODE_VERSION-linux-x64.tar.gz \ $" SHASUMS256.txt | sha256sum -c - \
 && tar -xzf "noeud-v $ NODE_VERSION-linux-x64.tar.gz" -C / usr / local - strip-components = 1 \
 && rm "noeud-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 ["noeud"]
# Installer Framework sans serveur
RUN set -ex \
 && npm install -g serverless

Maintenant, l'image peut être construite et étiquetée:

docker construire -t aws / codebuild / dot-net.

Une fois la construction terminée, l'image peut être exécutée pour confirmer que tout fonctionne et que le serveur sans serveur est correctement installé:

docker run -it --entrypoint shws / codebuild / dot-net -c bash
sls -v
Exécution de sls -v à l'intérieur du conteneur nouvellement créé

Nous allons ensuite créer un référentiel dans ECR à l'aide de l'AWS CLI. Une fois la commande exécutée, le nouveau référentiel sera visible dans la console AWS:

aws ecr create-repository - nom-référentiel codebuild-dotnet-node
Réponse de l'AWS CLI après la création du référentiel dans ECRLe référentiel nouvellement créé dans ECR

Nous allons maintenant baliser l'image aws / codebuild / dot-net créée précédemment avec la valeur repositoryUri de l'étape précédente:

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

Exécutez la commande get-login pour obtenir la chaîne de commande d'authentification de connexion docker pour votre registre de conteneurs:

aws ecr get-login --no-include-email
La commande de connexion pour s'authentifier dans ECR

Exécutez la commande de connexion de docker qui a été renvoyée en exécutant la commande get-login à la dernière étape.

connexion docker -u AWS -p eyJwYXlsb2FkIjoiNGZnd0dSaXM1L2svWWRLMmhhJT1c0WWpOZEcxamJFeOKJV2VVT0Y5 [...] https: //  .dkr.a

Si la connexion aboutit, nous pouvons maintenant transférer notre image de menu fixe dans le référentiel créé dans ECR. Cela peut prendre quelques minutes en fonction de la taille de l’image terminée:

Appuyez sur Docker  .dkr.ecr.ap-sud-est-2.amazonaws.com / codebuild-dotnet-node
Docker sur EC2 crée notre imageL'image de Docker dans ECR

Une fois l'image créée, nous allons permettre à quiconque d'accéder à l'image à partir d'ECR. L'autorisation doit être verrouillée dans un environnement de production, mais pour cet exemple, nous allons permettre son ouverture. Accédez à l'onglet Autorisations de la console AWS, sélectionnez Modifier la stratégie JSON et collez-la dans cette stratégie:

{
  "Version": "2008-10-17",
  "Déclaration": [
    {
      "Sid": "EnableAccountAccess",
      "Effet": "Autoriser",
      "Principal": "*",
      "Action": [
        "ecr: BatchCheckLayerAvailability",
        "ecr: BatchGetImage",
        "ecr: DescribeImages",
        "ecr: DescribeRepositories",
        "ecr: GetAuthorizationToken",
        "ecr: GetDownloadUrlForLayer",
        "ecr: GetRepositoryPolicy",
        "ecr: ListImages"
      ]
    }
  ]
}

3. Créez votre pipeline

Il est temps de construire le pipeline. Pour rendre cela plus facile et plus facilement déployable, et sous la vraie forme d'architectures sans serveur, j'ai construit le pipeline en utilisant le framework sans serveur. Vous pouvez également obtenir le même résultat en le construisant dans CloudFormation.

Je ne collerai pas l'intégralité du code source à partir de mon fichier serverless.yml, vous pouvez le cloner à partir de github: https://github.com/effectivedigital/serverless-deployment-pipeline

Jetez un coup d'oeil à travers le modèle sans serveur pour comprendre exactement ce qu'il va faire, mais en bref, sa configuration est la suivante:

  • 3x S3 Buckets
  • 1x politique de seau
  • 3x rôles IAM
  • 1x projet CodeBuild
  • 1x Pipeline CodePipeline
  • 1x événement CloudWatch
  • 1x sentier CloudTrail

Une fois cloné, mettez à jour DockerImageArn avec votre image dans ECR. Si vous envisagez de créer des packages de déploiement avec un nom de fichier autre que Deployment.zip, mettez également à jour DeploymentFilename:

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

Le pipeline est maintenant prêt pour le déploiement. Exécutez la commande deployless server et attendez que tout soit configuré pour vous:

sls deploy -v
Notre pile CloudFormation créée par le framework sans serveurLe pipeline CodePipeline créé par la structure sans serveurLe projet CodeBuild créé par le framework sans serveur

4. Ajoutez buildSpec.yml à votre application

Lorsque CodePipeline détecte une modification du fichier de déploiement dans S3, il indique à CodeBuild de s'exécuter et de tenter de créer et de déployer votre application. Cela dit, CodeBuild doit également savoir quelles commandes doivent être exécutées pour générer et déployer votre application. BuildSpec.yml contient les instructions suivies par CodeBuild.

J’ai créé une application très simple, hello world, qui comprend l’exemple de fichier buildSpec.yml que vous pouvez inclure: https://github.com/effectivedigital/serverless-deployment-app

Vous pouvez également créer un fichier buildSpec.yml dans vos applications existantes et le renseigner à l'aide des instructions ci-dessous:

version: 0.2
phases:
  pre_build:
    commandes:
      - chmod a + x *
  construire:
    commandes:
      - ./build.sh
  post_build:
    commandes:
      - sls deploy -v -s $ STAGE

5. Tester votre pipeline

Tout est maintenant en place pour exécuter votre pipeline pour la première fois. Créez un package appelé Deployment.zip qui devrait inclure tous les fichiers de votre application sans serveur et le fichier buildSpec.yml.

Après quelques instants, CloudTrail devrait enregistrer l'événement PutObject, déclencher une règle d'événement CloudWatch qui déclenchera ensuite l'exécution de CodePipeline.

Deployment.zip a été chargé sur S3CodePipeline a commencé et la construction est en cours

Si nous cliquons sur les détails de l'étape AWS CodeBuild, nous pouvons examiner la progression de la construction et du déploiement:

CodeBuild obtiendra la sortie de l'image Docker effectuant la construction et le déploiementNotre déploiement a été réussi!

La nouvelle application déployée par notre pipeline est également visible dans CloudFormation:

Nous pouvons tester le point de terminaison de l'API créé dans notre application simple (l'URL se trouve dans la sortie CodeBuild ou dans la passerelle API) et voir que notre application fonctionne correctement:

Utiliser Postman pour appeler notre API

Sommaire

CodePipeline vous permet de créer un pipeline CI / CD évolutif, flexible et à faible coût et aide à résoudre certains des problèmes associés aux pipelines traditionnels créés sur des serveurs.

J'aimerais aller plus loin et ajouter les tests unitaires dans le mixage une fois le déploiement terminé, même si cela mérite un article à lui tout seul - un objectif à garder à l’esprit à l’avenir!

Rejoignez notre communauté Slack et lisez nos sujets hebdomadaires sur Faun ⬇

Si ce message vous a été utile, veuillez cliquer plusieurs fois sur le bouton clap below ci-dessous pour montrer votre soutien à l'auteur! ⬇