Projekt: Ephemere Review-Umgebungen pro Merge Request. Evaluationsgegenstand: Art der Bereitstellung aus der GitLab-Pipeline. Evaluationsdatum: 06.11.2026 Durchführende Stelle: Projektleitung
Ausgangslage
Die Pipeline muss pro Merge Request eine Umgebung anlegen, aktualisieren und abbauen. Schwierig ist dabei nicht der einzelne Aufruf von run-instances, sondern das Drumherum: Mehrere Pipelines desselben MR können gleichzeitig laufen, Jobs werden abgebrochen, und der Abbau muss auch dann greifen, wenn die Bereitstellung noch läuft. Genau an diesen Stellen unterscheiden sich die beiden Varianten.
Varianten
| Variante | Beschreibung |
|---|---|
| A: Direkt aus der Pipeline | Der CI-Job stellt die Umgebung selbst bereit (AWS CLI oder Terraform), die Reihenfolge pro MR regelt resource_group. |
| B: Pipeline + SQS + Lambda | Die Pipeline legt nur einen Auftrag in eine SQS-FIFO-Queue, eine Lambda-Funktion (Python) setzt ihn um. |
Weitere Ansätze wurden vorab verworfen, weil sie das Kernproblem nicht besser lösen als B, aber zusätzlichen Aufwand bringen:
| Ansatz | Grund für den Ausschluss |
|---|---|
| Lambda direkt über API Gateway aufrufen (ohne Queue) | Keine Reihenfolge pro MR, keine Deduplizierung und keine Dead-Letter-Queue. Die Lambda müsste Nebenläufigkeit selbst lösen. |
| AWS Step Functions als Orchestrierung | Löst Wiederholungen ebenfalls, bringt aber eine weitere Zustandsmaschine ins Projekt. Für zwei Abläufe (Deploy, Destroy) überdimensioniert. |
Theoretischer Hintergrund
Variante B setzt zwei Konzepte aus dem Modul FAAS um:
- Entkopplung über eine Nachrichtenwarteschlange: Der Auftraggeber (Pipeline) und der Ausführende (Lambda) kennen sich nicht und laufen nicht gleichzeitig. Bricht die Pipeline ab, liegt der Auftrag trotzdem in der Queue und wird verarbeitet.
- Ereignisgesteuerte, idempotente Verarbeitung: SQS stellt Nachrichten mindestens einmal zu, eine Nachricht kann also doppelt ankommen. Die Verarbeitung muss deshalb idempotent sein: Ein zweiter «deploy» für denselben MR darf keine zweite Instanz erzeugen. Das sichern drei Ebenen ab, die FIFO-Deduplizierung über die Pipeline-ID, die Message-Group pro MR (höchstens ein Auftrag pro MR gleichzeitig) und das EC2-ClientToken.
Beispiel: Ein Entwickler pusht zwei Commits kurz hintereinander. In Variante B landen zwei Aufträge in derselben Message-Group und werden strikt nacheinander verarbeitet, der zweite aktualisiert die Instanz des ersten. In Variante A sorgt resource_group zwar ebenfalls für die Reihenfolge, wird der erste Job aber während run-instances abgebrochen, weiss der zweite nichts von der halb gestarteten Instanz.
Methode: Nutzwertanalyse
Die Varianten werden mit einer Nutzwertanalyse verglichen:
- Kriterien festlegen und gewichten (Summe 100 %).
- Jede Variante pro Kriterium auf einer Skala von 1 (ungenügend) bis 5 (hervorragend) bewerten und die Bewertung begründen.
- Bewertung mal Gewicht ergibt den Teilnutzen, die Summe den Nutzwert.
- Das Ergebnis mit einer Sensitivitätsanalyse prüfen: Hält der Entscheid, wenn die unsichersten Gewichte verschoben werden?
Die vier Kriterien aus dem Einreichungsformular (Rechte, Nebenläufigkeit, Fehler, Komplexität) tragen je 20 %, zwei ergänzende Kriterien je 10 %. Die Ergebnisse der Berechtigungsprüfung (US.1) fliessen in die Bewertung ein.
Vergleichstabelle
| Bewertungskriterium | Gewicht | A: Direkt aus der Pipeline | B: Pipeline + SQS + Lambda |
|---|---|---|---|
| 1. Rechte im CI (Least Privilege des Runners) | 20 % | 2: Runner braucht ec2:RunInstances, ec2:TerminateInstances, iam:PassRole und SSM-Rechte | 4: Runner braucht nur sqs:SendMessage. Im Schulaccount nicht durchsetzbar, weil der Runner mit den Lab-Sitzungsdaten läuft (E1, E2), darum keine 5 |
| 2. Nebenläufigkeit (parallele Pipelines pro MR) | 20 % | 3: resource_group reiht Jobs pro Environment ein, ein abgebrochener Job kann aber eine halb erstellte Umgebung hinterlassen | 5: FIFO-Message-Group pro MR, Deduplizierung über die Pipeline-ID, EC2-ClientToken gegen Doppelanlage (in US.1 geprüft) |
| 3. Fehlerbehandlung (Wiederholung, Nachvollziehbarkeit) | 20 % | 2: Job schlägt fehl, Neustart von Hand, Fehler nur im Job-Log | 5: Automatische Wiederholung, fehlerhafte Aufträge landen in der Dead-Letter-Queue, unabhängig vom Runner |
| 4. Komplexität (Aufbau, Betrieb, Testbarkeit) | 20 % | 5: Wenige Komponenten, alles in .gitlab-ci.yml | 2: Queue, DLQ, Lambda und Rückmeldung über die GitLab-API müssen gebaut und getestet werden |
| 5. Rückmeldung im MR (URL, Status) | 10 % | 5: Job kennt die URL am Ende selbst, Status entspricht dem Job | 3: Job endet vor der Bereitstellung, die Lambda trägt die URL nachträglich über die GitLab-API ein |
| 6. Bezug zu den Modulzielen (FAAS, IaC) | 10 % | 2: Kein FAAS-Anteil | 5: Lambda, Queue und IaC greifen ineinander |
Gewichtete Gesamtbewertung
| Lösung | Nutzwert | Ranking |
|---|---|---|
| B: Pipeline + SQS + Lambda | 4,00 | 1. Platz |
| A: Direkt aus der Pipeline | 3,10 | 2. Platz |
(Berechnung B: 0,2×4 + 0,2×5 + 0,2×5 + 0,2×2 + 0,1×3 + 0,1×5 = 4,00) (Berechnung A: 0,2×2 + 0,2×3 + 0,2×2 + 0,2×5 + 0,1×5 + 0,1×2 = 3,10)
Sensitivitätsanalyse
| Annahme | A | B | Entscheid hält? |
|---|---|---|---|
| Gewichtung wie oben | 3,10 | 4,00 | Ja |
| Ohne Kriterium 6 (Modulbezug, das subjektivste Kriterium) | 3,22 | 3,89 | Ja |
| Komplexität mit 30 % statt 20 % (übrige anteilig gekürzt) | 3,34 | 3,75 | Ja |
| Komplexität mit 40 % statt 20 % | 3,58 | 3,50 | Nein |
Der Gleichstand liegt bei rund 38 % Gewicht für die Komplexität. B ist also nur dann die bessere Wahl, wenn Robustheit wichtiger ist als ein möglichst einfacher Aufbau. Für ephemere Umgebungen trifft das zu: Eine vergessene oder doppelt gestartete Instanz kostet laufend Geld, ein komplexerer Aufbau nur einmalig Zeit.
Vorbehalte gegen Variante B
| Vorbehalt | Einschätzung |
|---|---|
| Mehr Komponenten, mehr Fehlerquellen | Berechtigt. Wird durch definierte Robustheitstests (doppelte Nachricht, parallele Pipelines, MR geschlossen während Bereitstellung) in US.10 abgesichert. |
| Der Rechtevorteil gilt im Schulaccount nicht | Berechtigt. Der Runner läuft mit den Lab-Sitzungsdaten (E1, E2). Der Vorteil ist architektonisch vorhanden und wird wirksam, sobald die Lösung in einem regulären Account läuft. Für den Entscheid hält B auch ohne diesen Vorteil (Kriterium 1 für beide mit 2 bewertet: A 3,10, B 3,60). |
| Asynchrone Rückmeldung, der Job ist grün, bevor die Umgebung läuft | Teilweise entkräftet. Die URL erscheint über die GitLab-API im Environment. Fehler sind in der Dead-Letter-Queue und in CloudWatch nachvollziehbar statt im Job-Log. |
| Fehlersuche über mehrere Dienste | Teilweise entkräftet. Jeder Auftrag trägt MR-ID und Pipeline-ID, damit lassen sich Pipeline, Nachricht, Lambda-Log und Instanz-Tags zuordnen. |
| Zusätzliche Kosten für SQS und Lambda | Entkräftet. Pro MR fallen nur wenige Nachrichten und Aufrufe an, die Kosten sind gegenüber der EC2-Instanz vernachlässigbar. Budget-Alarm folgt mit US.12. |
Erkenntnisse
- In Semesterarbeit 1 wurde die Bereitstellung als interaktives Bash-Skript umgesetzt, das eine Person von Hand startet. Parallele Ausführbarkeit war dort mit 5 % gewichtet, der gewählte Monolith erhielt dafür nur eine 2. Hier sind parallele Pipelines der Kern des Problems, darum fällt der Entscheid anders aus.
- Die Berechtigungsprüfung (US.1) hat die Bewertung direkt verändert: Ohne sie wäre Kriterium 1 für B mit 5 statt 4 bewertet worden.
- Die Sensitivitätsanalyse zeigt, dass der Entscheid nicht eindeutig ist, sondern an der Gewichtung von Robustheit gegenüber Einfachheit hängt. Das wird so offen begründet.
Handlungsempfehlung
Variante B: Pipeline + SQS + Lambda wird umgesetzt. Sie ist bei Nebenläufigkeit und Fehlerbehandlung klar überlegen, also genau dort, wo ephemere Umgebungen in der Praxis scheitern (Doppelanlagen, vergessene Instanzen nach abgebrochenen Jobs). Für das weitere Vorgehen heisst das:
- Architektur und Abläufe (Deploy, Update, Destroy) mit US.2 festlegen, inklusive Nachrichtenformat mit MR-ID und Pipeline-ID.
- Die höhere Komplexität früh mit einem Durchstich (Pipeline bis Lambda) in US.4 entschärfen.
- Die Vorbehalte mit den Robustheitstests in US.10 überprüfen.
ADR-001: Bereitstellung über SQS und Lambda
| Feld | Inhalt |
|---|---|
| Status | Angenommen |
| Datum | 06.11.2026 |
| Kontext | Pro Merge Request soll eine Review-Umgebung auf AWS entstehen, aktualisiert und abgebaut werden. Parallele Pipelines für denselben MR und abgebrochene Jobs dürfen keine doppelten oder verwaisten Instanzen erzeugen. |
| Entscheid | Die Pipeline reiht nur Aufträge (deploy, destroy) in eine SQS-FIFO-Queue ein, Message-Group ist die MR-ID. Eine Lambda (Python) setzt die Aufträge um, startet Instanzen aus dem Launch Template und meldet die URL über die GitLab-API zurück. Der Entscheid ist mit der Freigabe der Semesterarbeit durch die Expert/innen bestätigt. |
| Alternativen | Bereitstellung direkt aus dem CI-Job mit resource_group (Variante A, 3,10 Punkte). Lambda über API Gateway und Step Functions wurden vorab verworfen. |
| Konsequenzen | Positiv: Reihenfolge und Deduplizierung pro MR durch SQS, automatische Wiederholung und Dead-Letter-Queue, Runner braucht im Zielbild nur sqs:SendMessage. Negativ: Mehr Komponenten, die Rückmeldung an den MR ist asynchron. Im Schulaccount läuft der Runner trotzdem mit weitreichenden Lab-Rechten (E1, E2), der Rechtevorteil gilt dort nur architektonisch. |