
Ce serait cool si un déploiement de copier-coller appartenait au passé, mais, hélas, les choses sont différentes. Il arrive que les développeurs préfèrent une telle méthode de livraison. Bien que maintenant, écrivez un article sur pourquoi cela ne bourdonne pas, mais vous savez tout sans moi. Avec une tendance vers l'architecture sans serveur, les pipelines CI / CD jouent un rôle important dans la livraison des applications. J'ai également écrit à leur sujet dans l'article " 3 meilleurs conseils pour votre prochain projet sans serveur" .
Je m'intéresse au sujet du CI et du CD il y a longtemps et pour la première fois je l'ai rencontré il y a plusieurs années - grâce à TeamCity. Actuellement, TeamCity est toujours utilisé pour la plupart de nos pipelines CI / CD. TeamCity fonctionne très bien, je n'ai rien contre, mais je m'efforce toujours d'améliorer le travail. Par exemple, ce serait bien de collecter des pipelines sous forme de code - c'est l'un des domaines dans lesquels TeamCity n'est pas si bon.
J'ai appris les outils d'intégration et de livraison sur AWS il y a quelque temps, et bien que nous utilisions CodeDeploy pour un autre projet qui fonctionne sur EC2, je n'ai pas encore déployé de projet sans serveur avec eux. Après avoir revu les outils, j'ai remarqué ceci: il y a maintenant une fonction d'intégration intégrée pour déployer CloudFormation et Lambda, probablement basée sur SAM AWS; nous utilisons le framework sans serveur - il génère des modèles CloudFormation, mais il ne fonctionne pas tout de suite avec les outils AWS.
La préparation
J'utilise les services AWS suivants: EC2, Docker, ECR, S3, IAM, CodeBuild, CodePipeline, CloudWatch, CloudTrail. Afin de suivre, vous devez au moins à un niveau de base comprendre ce que fait chacun de ces services.
Fondamentalement, j'écris le code côté serveur dans .NET, et ce guide s'appuie également sur cette plate-forme. Aucune des images CodeBuild prêtes à l'emploi n'a un runtime .NET et NodeJS en même temps (NodeJS est nécessaire pour le framework sans serveur). Si vos fonctions Lambda sont écrites dans NodeJS, la configuration du pipeline de déploiement est beaucoup plus simple, car il s'agit du seul environnement d'exécution requis pour l'installation dans une image Docker (dans votre cas, n'hésitez pas à ignorer la plupart du manuel). Pendant une seconde, ce fut ma première expérience avec les conteneurs, et je suis heureux d'apprendre quelque chose de nouveau.
J'ose supposer que votre code est dans un certain référentiel, par exemple, git. À titre indicatif, nous téléchargeons simplement sur S3 un fichier contenant un paquet de code pour le déploiement; la façon dont vous l'obtenez dépend de vous. Sur la base de mon travail, vous pouvez toujours aller plus loin en connectant votre pipeline à des référentiels tels que github ou CodeCommit.
1. Créez une instance EC2 et installez Docker
Exécutez une instance standard d'AWS Linux 2 EC2 - cela devrait être clair sans explication. Connectez-vous et installez Docker à l'aide des commandes:
sudo yum update -y sudo amazon-linux-extras install docker sudo service docker start
Vous devez également ajouter l'utilisateur ec2 au groupe docker pour exécuter les commandes Docker sans utiliser sudo:
sudo usermod -a -G docker ec2-user
Une fois la commande terminée, déconnectez-vous et reconnectez-vous à votre instance EC2 pour que l'utilisateur ec2 reçoive de nouvelles autorisations. Assurez-vous que l'utilisateur ec2 exécute les commandes Docker sans sudo:
docker info

Sortie de la docker info
2. Créez une image Docker et placez-la dans ECR
Supposons que l'étape précédente soit réussie; L'étape suivante consiste à créer une image Docker qui tient dans l'ECR. AWS propose des images de base pour CodeBuild sur github , ce qui facilite la création de votre propre image.
J'ai également posté l'image sur github - au cas où vous ne voudriez pas suivre ces étapes pour créer la vôtre: https://github.com/effectivedigital/serverless-deployment-image
Copiez les images et accédez au répertoire .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/
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à disponibles dans le Dockerfile. J'ai obtenu la plupart de ces commandes à partir d'une image Docker NodeJS dans le même référentiel 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
Maintenant, nous collectons et marquons l'image:
docker build -t aws/codebuild/dot-net .
Après avoir terminé l'assemblage, exécutez l'image - assurez-vous que tout fonctionne et que le framework sans serveur est installé correctement:
docker run -it --entrypoint sh aws/codebuild/dot-net -c bash sls -v

Exécution de sls -v
dans un tout nouveau conteneur
Créez ensuite le référentiel dans ECR à l'aide de l'AWS CLI. Après avoir exécuté la commande, le nouveau référentiel sera affiché dans la console AWS:
aws ecr create-repository --repository-name codebuild-dotnet-node

Réponse de l'AWS CLI pour créer un référentiel dans ECR

Marquez maintenant l'image aws / codebuild / dot-net précédemment créée avec la valeur repositoryUri de l'étape précédente:
docker tag aws/codebuild/dot-net <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node
Exécutez la commande get-login pour obtenir la ligne de commande d'authentification de connexion docker pour le registre de conteneurs:
aws ecr get-login --no-include-email

Exécutez la commande docker login émise par la commande get-login lors de la dernière étape.
docker login -u AWS -p eyJwYXlsb2FkIjoiNGZnd0dSaXM1L2svWWRLMmhJT1c0WWpOZEcxamJFeFJOK2VvT0Y5[...] https://<ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com
Si la connexion réussit, placez l'image de docker dans le référentiel créé dans ECR. Cela peut prendre plusieurs minutes (selon la taille de l'image terminée).
docker push <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node

Docker sur EC2 crée notre image

Image Docker dans ECR
Ensuite, nous pouvons ouvrir l'accès à l'image de l'ECR à n'importe qui. L'autorisation doit être bloquée dans l'environnement de travail, mais dans cet exemple, nous allons l'ouvrir. Accédez à l'onglet autorisations dans la console AWS, sélectionnez «Modifier la stratégie JSON» et insérez l'élément suivant dans la stratégie:
{ "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. Créez un pipeline
Il est temps de récupérer le pipeline. Pour simplifier le processus, le rendre multi-déployable et s'en tenir à la forme désastreuse d'architecture sans serveur, j'ai construit un pipeline utilisant le framework sans serveur. Vous pouvez obtenir le même résultat en créant dans CloudFormation.
Je ne copierai pas la source entière de mon fichier serverless.yml - copiez-la depuis github: https://github.com/effectivedigital/serverless-deployment-pipeline
Consultez le modèle sans serveur pour voir exactement ce qu'il fera, mais, en bref, il configure les éléments suivants:
- 3 segments S3
- Politique 1 segment
- 3 rôles IAM
- 1 projet CodeBuild
- 1 pipeline CodePipeline
- 1 événement CloudWatch
- 1 trace de CloudTrail
Mettez ensuite à jour DockerImageArn pour votre image dans ECR. Si vous souhaitez créer des packages de déploiement avec un nom autre que Deployment.zip , mettez également à jour DeploymentFilename :
DockerImageArn: <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node:latest DeploymentFilename: Deployment.zip
Voilà, le pipeline est prêt pour le déploiement. Exécutez la commande de déploiement sans serveur et attendez qu'elle soit configurée:
sls deploy -v

Création d'une pile d'infrastructure sans serveur CloudFormation

Créé par le pipeline de framework sans serveur CodePipeline

Créé par le projet de framework sans serveur Projet CodeBuild
4. Ajoutez buildSpec.yml à votre application
Lorsque CodePipeline détecte une modification du fichier de déploiement dans S3, il indique à CodeBuild de démarrer et d'essayer de générer et de déployer l'application. Cependant, CodeBuild doit également savoir quelles commandes doivent être exécutées pour générer et déployer l'application, et buildSpec.yml contient des instructions que CodeBuild suivra.
J'ai créé une application "Hello world" très simple qui comprend un exemple de fichier buildSpec.yml que vous pouvez utiliser: https://github.com/effectivedigital/serverless-deployment-app
Ou créez le fichier buildSpec.yml dans les applications existantes et remplissez-le selon les instructions ci-dessous:
version: 0.2 phases: pre_build: commands: - chmod a+x * build: commands: - ./build.sh post_build: commands: - sls deploy -v -s $STAGE
5. Vérification du pipeline
Maintenant, tout est prêt pour le premier lancement de votre pipeline. Créez un package appelé Deployment.zip , il doit inclure tous les fichiers de votre application sans serveur et le fichier buildSpec.yml.
Après quelques instants, CloudTrail devrait enregistrer un événement PutObject et activer la règle d'événement CloudWatch, qui active ensuite le déclencheur CodePipeline.

Deployment.zip démarré dans S3

Lancement de CodePipeline, la version est lancée
Si nous passons aux détails de l'étape AWS CodeBuild, nous pouvons voir le processus de génération et de déploiement:

CodeBuild recevra la sortie de l'image Docker de génération et de déploiement

Déploiement réussi!
La nouvelle application déployée par notre pipeline apparaît également dans CloudFormation:

Vous pouvez tester le point de terminaison API créé dans notre application simple (l'URL est dans la sortie CodeBuild ou dans l'API Gateway) et vous assurer que l'application fonctionne correctement:

Postman to call API
Brèves conclusions
CodePipeline vous permet de créer un pipeline CI / CD évolutif, flexible et peu coûteux. Il permet de résoudre certains problèmes associés aux pipelines traditionnels créés sur des serveurs.
Je voudrais aller plus loin et ajouter des tests unitaires après le déploiement au mix, mais le sujet mérite un article séparé - et c'est l'occasion de nous lire à l'avenir!