Einfache CI / CD-Container in AWS

14

Ich verwende AWS Code Pipeline, Code Build, um einen neuen Docker-Container zu erstellen und an ECR zu senden.

Meine Anwendung basiert auf einem einfachen, einfachen Einzelcontainer. Was wäre ein weniger reibungsloser Ansatz, um den aktuell laufenden Container herunterzufahren und einen neuen Container aus der ECS-Registrierung neu zu starten (Ausgabe von Code Build durch Code Pipeline).

Ich habe CloudFormation mit EC2-Benutzerdaten, benutzerdefinierten Skripten auf der einen Seite und CloudFormation mit ECS mit Aufgabendefinition auf der anderen Seite ausprobiert (noch nicht erfolgreich). Ich bin der festen Überzeugung, dass es einen offensichtlicheren und einfacheren Ansatz geben muss.

Naveen Vijay
quelle

Antworten:

16

Ich würde die ECS-Containerinstanzen (ich spreche von den Docker-Hosts - ich mag die AWS-Terminologie hier nicht) und die Bereitstellung als zwei separate Dinge beibehalten.

Bringen Sie Ihren ECS-Stack zum Laufen. Sie können es über CloudFormation und Auto-Scaling-Gruppen verwalten, das ist in Ordnung. Man denke nur an den Cluster als Plattform , wo Sie bereitstellen werden , um nicht etwas , was Sie brauchen redeploy .

Für CDs ist es bei weitem die einfachste Methode, die Servicedefinition zu aktualisieren, um eine neue Aufgabendefinition zu verwenden, und ECS die Container für Sie aktualisieren zu lassen.

Jedes Mal, wenn eine Aufgabe gestartet wird, führt ECS das Docker-Pull-Image-Tag aus, auch wenn das Image lokal vorhanden ist, um sicherzustellen, dass die neueste Version des Image-Tags vorhanden ist. Das verwendete Image-Tag spielt also keine Rolle (das Tag muss nicht bei jedem Build geändert werden).

Das bedeutet, dass Sie myimage erstellen können: immer und immer wieder, um es einfach bereitzustellen.

Was Sie brauchen, ist eine Aufgabendefinition, bei der image = myimage: latest ist. Erstellen Sie einen Dienst mit dieser Aufgabendefinition, und jedes Mal, wenn ECS eine Aufgabe (eine Instanz Ihres Dienstes) startet, ist dies das aktuellste von Ihnen erstellte "myimage: latest".

Von dort aus fehlt nur ein Teil des Puzzles. In CodeDeploy können Sie eine neue Revision Ihrer Aufgabendefinition erstellen und Ihren Dienst aktualisieren, und ECS erstellt automatisch neue Aufgaben für diese Revision und entferne die alten Aufgaben.

Ein Beispiel:

Angenommen, Sie haben einen Dienst namens MyService erstellt. Sie haben diesen Dienst so konfiguriert, dass 2 Aufgaben für die Aufgabendefinition MyTaskDefinition ausgeführt werden: 1 (Revision 1). In dieser Aufgabendefinition haben Sie eine Containerdefinition, deren Image auf "myimage: latest" festgelegt ist.

  1. Gestern hast du myimage erstellt: spätestens mit der ID (SHA) 365d8f7bf565.
  2. Ihre Containerinstanz ABC führt eine Task mit dem Namen MyTaskDefinition- 1 -containerName-someLongId aus. Wenn Sie diesen Container untersuchen, wird das Bild "sha256: 365d8f7bf565 .........." ausgeführt.
  3. Ihre andere Containerinstanz-DEF führt eine andere Task aus. Es hat einen ähnlichen Namen (nur die ID unterscheidet sich), aber es läuft das gleiche Bild.
  4. Sie drücken eine Änderung an Ihrem Repo.
  5. CodePipeline übernimmt diese Änderung, erstellt und veröffentlicht das Bild in ECR.
  6. Das neue Docker-Image ist auch mein Bild: Neueste, aber seine ID (SHA) ist f7ec5e54ac96
  7. Jetzt müssen Sie Ihrer Pipeline einen Schritt hinzufügen, um Lambda-Funktionen und das AWS NodeJS SDK für einige Aufrufe an Ihren Cluster zu verwenden:
    1. Erstellen Sie eine neue Aufgabendefinition (genau wie zuvor). Das wird MyTaskDefinition sein: 2
    2. Aktualisieren Sie Ihren MyService, um MyTaskDefinition zu verwenden: 2 (anstelle von 1)
  8. ECS wird neue Aufgaben erstellen. Die Containernamen lauten MyTaskDefinition- 2 -containerName-someLongId. Wenn Sie diese Container überprüfen, werden Sie feststellen, dass auf ihnen "sha256: f7ec5e54ac96 ......." ausgeführt wird. Vielleicht haben Sie 2 Aufgaben auf der Container-Instanz ABC, vielleicht werden sie weggesprüht (das hängt von der Konfiguration Ihres Dienstes ab)
  9. Nach einiger Zeit entfernt ECS die alte Aufgabe MyTaskDefinition-1-containerName-someLongId aus ABC und DEF.

Hinweis: Sie müssen tatsächlich keine neue Aufgabendefinition erstellen. Wenn Sie möchten, können Sie stattdessen die Aufgabenliste des Dienstes abrufen und sie einzeln manuell stoppen. Sie sollten warten, bis ECS eine Task neu gestartet hat, bevor Sie eine neue Task stoppen (d. H. Den ersten Container stoppen, warten, bis ECS ihn ersetzt, den zweiten Container stoppen). Wenn ECS den Container neu startet, wird das neueste myimage abgerufen: das zuletzt erstellte, wie zuvor erläutert. Ich denke nur, dass das Erstellen einer neuen Aufgabendefinition einfacher und weniger fehleranfällig ist (es ist keine Logik erforderlich, um zu warten und zu überprüfen, ECS übernimmt das fortlaufende Update für Sie, wenn Sie eine neue Aufgabendefinition haben).

Alexandre
quelle
Erstaunlich - ich würde Ihre Antwort als das fehlende Handbuch für die CI / CD für Docker bezeichnen. Vielen Dank.
Naveen Vijay
3

Für den beschriebenen einfachen Anwendungsfall würde ich vorschlagen, Elastic Beanstalk auf Docker zu überprüfen. Dies ist keine minimale Lösung wie die reine ECS-Nutzung, aber Sie können von automatisch verwalteten und konfigurierten Diensten wie ELB, EC2 AutoScale, Health Monitoring und vielem mehr profitieren.

Zusammenfassung auf hoher Ebene:

  1. Konfigurieren Sie Elastic Beanstalk für die Verwendung eines bestimmten Tags myimage: tested
  2. Verwenden Sie Code Pipeline / Build, um das Tag "testing" zu erstellen, zu testen und zu bewerben.
  3. Triggern Sie die Bereitstellung von Elastic Beanstalk, um das Image zu promoten. Getestet für alle Instanzen stehen verschiedene Bereitstellungsstrategien zur Verfügung.

Dieser Ansatz basiert auf der Wiederverwendung desselben Tags. Ein alternativer Ansatz würde darin bestehen, ein Tag mit Build-ID zu generieren, z. B. myimage: tested-42. Hierfür muss Elastic Beanstalk jedes Mal mit einem neuen Tag aktualisiert werden.

Rombob
quelle
0

Ich zweite elastische Bohnenstange für seine Einfachheit; Es ist sehr einfach einzurichten und bereitzustellen.

Wenn Sie mit docker-compose vertraut sind, können Sie docker-compose.yml auch definieren und mit ecs-cli direkt in ECS bereitstellen.

AnthonyC
quelle