Serverloses CI / CD unter AWS



Es wäre cool, wenn die Copy-Paste-Bereitstellung der Vergangenheit angehören würde, aber leider sind die Dinge anders. Es kommt vor, dass Entwickler eine solche Übermittlungsmethode bevorzugen. Schreibe jetzt zwar einen Artikel darüber, warum das nicht brummt, aber du weißt alles ohne mich. Mit dem Trend zur serverlosen Architektur spielen CI / CD-Pipelines eine wichtige Rolle bei der Anwendungsbereitstellung. Ich habe darüber auch im Artikel " 3 beste Tipps für Ihr nächstes serverloses Projekt " geschrieben.


Ich habe mich vor langer Zeit für das Thema CI und CD interessiert und bin vor einigen Jahren zum ersten Mal darauf gestoßen - dank TeamCity. Derzeit wird TeamCity noch für die meisten unserer CI / CD-Pipelines verwendet. TeamCity funktioniert großartig, ich habe nichts dagegen, aber ich bemühe mich immer, die Arbeit zu verbessern. Zum Beispiel wäre es schön, Pipelines in Form von Code zu sammeln - dies ist einer der Bereiche, in denen TeamCity nicht so gut ist.


Ich habe vor einiger Zeit die Integrations- und Bereitstellungstools in AWS kennengelernt. Obwohl wir CodeDeploy für ein anderes Projekt verwenden, das unter EC2 funktioniert, habe ich noch kein serverloses Projekt mit ihnen bereitgestellt. Nachdem ich die Tools erneut überprüft hatte, bemerkte ich Folgendes: Jetzt gibt es eine integrierte Integrationsfunktion für die Bereitstellung von CloudFormation und Lambda, die vermutlich auf SAM AWS basiert. Wir verwenden das serverlose Framework - es generiert CloudFormation-Vorlagen, funktioniert jedoch mit AWS-Tools nicht sofort.


Vorbereitung


Ich verwende die folgenden AWS-Dienste: EC2, Docker, ECR, S3, IAM, CodeBuild, CodePipeline, CloudWatch, CloudTrail. Um auf dem Laufenden zu bleiben, müssen Sie zumindest auf einer grundlegenden Ebene verstehen, was jeder dieser Dienste tut.


Grundsätzlich schreibe ich den serverseitigen Code in .NET, und dieses Handbuch basiert auch auf dieser Plattform. Keines der vorgefertigten CodeBuild-Images verfügt gleichzeitig über eine .NET- und eine NodeJS-Laufzeit (NodeJS wird für das serverlose Framework benötigt). Wenn Ihre Lambda-Funktionen in NodeJS geschrieben sind, ist die Konfiguration der Bereitstellungspipeline viel einfacher, da dies die einzige Laufzeitumgebung ist, die für die Installation in einem Docker-Image erforderlich ist (in Ihrem Fall können Sie den größten Teil des Handbuchs überspringen). Für eine Sekunde war dies meine erste Erfahrung mit Containern und ich freue mich, etwas Neues zu lernen.


Ich wage anzunehmen, dass sich Ihr Code in einem bestimmten Repository befindet, zum Beispiel git. Zur Orientierung laden wir einfach eine Datei in S3 hoch, die ein Codepaket für die Bereitstellung enthält. Wie Sie es bekommen, liegt bei Ihnen. Auf der Grundlage meiner Arbeit können Sie jederzeit weiter gehen, indem Sie Ihre Pipeline mit Repositorys wie Github oder CodeCommit verbinden.


1. Erstellen Sie eine EC2-Instanz und installieren Sie Docker


Führen Sie eine Standardinstanz von AWS Linux 2 EC2 aus - dies sollte ohne Erklärung klar sein. Melden Sie sich an und installieren Sie Docker mit den folgenden Befehlen:


sudo yum update -y sudo amazon-linux-extras install docker sudo service docker start 

Sie müssen auch den Benutzer ec2 zur Docker-Gruppe hinzufügen, um Docker-Befehle ohne Verwendung von sudo auszuführen:


 sudo usermod -a -G docker ec2-user 

Wenn der Befehl abgeschlossen ist, melden Sie sich ab und wieder bei Ihrer EC2-Instanz an, damit der ec2-Benutzer neue Berechtigungen erhält. Stellen Sie sicher, dass der ec2-Benutzer Docker-Befehle ohne sudo ausführt:


 docker info 


Ausgabe des docker info


2. Erstellen Sie ein Docker-Image und platzieren Sie es in ECR


Angenommen, der vorherige Schritt ist erfolgreich. Der nächste Schritt besteht darin, ein Docker-Image zu erstellen, das in die ECR passt. AWS bietet grundlegende Bilder für CodeBuild auf Github an. Auf diese Weise können Sie ganz einfach Ihr eigenes Bild erstellen.


Ich habe das Bild auch auf github gepostet - falls Sie diese Schritte nicht ausführen möchten, um Ihr eigenes zu erstellen: https://github.com/effectivedigital/serverless-deployment-image


Kopieren Sie die Bilder und wechseln Sie in das Verzeichnis .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/ 

Öffnen Sie Dockerfile in Ihrem bevorzugten Texteditor:


 nano Dockerfile 

Fügen Sie die Befehle zum Installieren von NodeJS und des serverlosen Frameworks am Ende anderer Befehle hinzu, die bereits in der Docker-Datei verfügbar sind. Ich habe die meisten dieser Befehle von einem NodeJS Docker-Image im selben AWS-Repository erhalten:


 # 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 

Jetzt sammeln und markieren wir das Bild:


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

Führen Sie nach Abschluss der Assembly das Image aus. Stellen Sie sicher, dass alles funktioniert und das serverlose Framework korrekt installiert ist:


 docker run -it --entrypoint sh aws/codebuild/dot-net -c bash sls -v 


Ausführen von sls -v in einem brandneuen Container


Erstellen Sie dann das Repository in ECR mithilfe der AWS-CLI. Nach dem Ausführen des Befehls wird das neue Repository in der AWS-Konsole angezeigt:


 aws ecr create-repository --repository-name codebuild-dotnet-node 


AWS CLI-Antwort zum Erstellen eines Repositorys in ECR



Markieren Sie nun das zuvor erstellte aws / codebuild / dot-net- Image mit dem Wert repositoryUri aus dem vorherigen Schritt:


 docker tag aws/codebuild/dot-net <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node 

Führen Sie den Befehl get-login aus, um die Befehlszeile für die Docker-Anmeldeauthentifizierung für die Containerregistrierung abzurufen:


 aws ecr get-login --no-include-email 


Führen Sie den Docker-Anmeldebefehl aus, der im letzten Schritt vom Befehl get-login ausgegeben wurde.


 docker login -u AWS -p eyJwYXlsb2FkIjoiNGZnd0dSaXM1L2svWWRLMmhJT1c0WWpOZEcxamJFeFJOK2VvT0Y5[...] https://<ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com 

Wenn die Anmeldung erfolgreich ist, legen Sie das Docker-Image in dem in ECR erstellten Repository ab. Dies kann einige Minuten dauern (abhängig von der Größe des fertigen Bildes).


 docker push <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node 


Docker auf EC2 erstellt unser Image



Docker-Bild in ECR


Dann können wir jedem den Zugriff auf das Bild von ECR öffnen. Die Berechtigung muss in der Arbeitsumgebung blockiert sein, aber in diesem Beispiel werden wir sie öffnen. Wechseln Sie in der AWS-Konsole zur Registerkarte Berechtigungen, wählen Sie "JSON-Richtlinie ändern" und fügen Sie das folgende Element in die Richtlinie ein:


 { "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. Erstellen Sie eine Pipeline


Es ist Zeit, die Pipeline zu sammeln. Um den Prozess zu vereinfachen, ihn mehrfach bereitstellbar zu machen und mich an die katastrophale Form der Architektur ohne Server zu halten, habe ich eine Pipeline mit dem Framework ohne Server erstellt. Sie können das gleiche Ergebnis erzielen, indem Sie CloudFormation einbauen.


Ich werde nicht die gesamte Quelle aus meiner serverless.yml-Datei kopieren - kopieren Sie sie von github: https://github.com/effectivedigital/serverless-deployment-pipeline


Schauen Sie sich die serverlose Vorlage an, um genau zu sehen, was sie tun wird. Kurz gesagt, sie richtet die folgenden Elemente ein:


  • 3 Segmente S3
  • 1 Segmentpolitik
  • 3 IAM-Rollen
  • 1 CodeBuild-Projekt
  • 1 Pipeline CodePipeline
  • 1 CloudWatch-Ereignis
  • 1 Spur von CloudTrail

Aktualisieren Sie anschließend DockerImageArn für Ihr Image in ECR. Wenn Sie Bereitstellungspakete mit einem anderen Namen als Deployment.zip erstellen möchten, aktualisieren Sie auch DeploymentFilename :


 DockerImageArn: <ACCOUNTID>.dkr.ecr.ap-southeast-2.amazonaws.com/codebuild-dotnet-node:latest DeploymentFilename: Deployment.zip 

Das war's, die Pipeline ist bereit für die Bereitstellung. Führen Sie den Befehl serverlose Bereitstellung aus und warten Sie, bis er konfiguriert ist:


 sls deploy -v 


Serverloser Framework-Stack CloudFormation erstellt



Erstellt von der serverlosen Framework-Pipeline CodePipeline



Erstellt vom serverlosen Framework-Projekt CodeBuild Project


4. Fügen Sie Ihrer Anwendung buildSpec.yml hinzu


Wenn CodePipeline eine Änderung an der Bereitstellungsdatei in S3 feststellt, weist es CodeBuild an, die Anwendung zu starten und zu versuchen, sie zu erstellen und bereitzustellen. CodeBuild muss jedoch auch wissen, welche Befehle zum Erstellen und Bereitstellen der Anwendung ausgeführt werden müssen, und buildSpec.yml enthält Anweisungen, denen CodeBuild folgen wird.


Ich habe eine sehr einfache "Hello World" -Anwendung erstellt, die eine Beispieldatei buildSpec.yml enthält, die Sie verwenden können: https://github.com/effectivedigital/serverless-deployment-app
Oder erstellen Sie die Datei buildSpec.yml in vorhandenen Anwendungen und füllen Sie sie gemäß den folgenden Anweisungen aus:


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

5. Pipeline-Prüfung


Jetzt ist alles bereit für den ersten Start Ihrer Pipeline. Erstellen Sie ein Paket mit dem Namen Deployment.zip . Es sollte alle Dateien für Ihre serverlose Anwendung und die Datei buildSpec.yml enthalten.


Nach einigen Augenblicken sollte CloudTrail ein PutObject-Ereignis registrieren und die CloudWatch-Ereignisregel aktivieren, die dann den CodePipeline-Trigger aktiviert.



Deployment.zip wurde in S3 gestartet



CodePipeline gestartet, Build läuft


Wenn wir zu den Details des AWS CodeBuild-Schritts übergehen, sehen wir den Erstellungs- und Bereitstellungsprozess:



CodeBuild empfängt die Ausgabe des Builds und stellt das Docker-Image bereit



Bereitstellung erfolgreich!


Die neue Anwendung, die von unserer Pipeline bereitgestellt wird, wird auch in CloudFormation angezeigt:



Sie können den in unserer einfachen Anwendung erstellten API-Endpunkt testen (die URL befindet sich in der CodeBuild-Ausgabe oder in der Gateway-API) und sicherstellen, dass die Anwendung erfolgreich funktioniert:



Postbote, um API aufzurufen


Kurze Schlussfolgerungen


Mit CodePipeline können Sie eine skalierbare, flexible und kostengünstige CI / CD-Pipeline erstellen. Sie können damit einige Probleme lösen, die mit herkömmlichen Pipelines verbunden sind, die auf Servern erstellt wurden.
Ich würde gerne weiter gehen und Unit-Tests nach der Bereitstellung zum Mix hinzufügen, aber das Thema verdient einen separaten Artikel - und dies ist eine Gelegenheit, uns in Zukunft zu lesen!

Source: https://habr.com/ru/post/de440756/


All Articles