Semesterarbeit HF
| Titel der Semesterarbeit | Ephemere Review-Umgebungen: Automatisierte Bereitstellung von AWS-Testumgebungen pro Merge Request mit GitLab CI/CD, SQS und Lambda |
| Name des Studenten | Ramon Schmocker |
| Name des Studiengangs | Dipl. HF Cloud-native Engineer |
| Semester / AbgabeDatum | Semester 2 / 27.01.2027 |
Inhaltsverzeichnis
[TOC]
Management Summary
Abstract
Die vorliegende Semesterarbeit befasst sich mit der automatisierten Bereitstellung von kurzlebigen (ephemeren) Testumgebungen in der Amazon Web Services (AWS) Cloud. Für jeden Merge Request (MR) in GitLab soll automatisch eine eigene, isolierte Umgebung entstehen, die bei jedem neuen Commit aktualisiert und beim Merge oder Schliessen des MR wieder abgebaut wird.
Problematik
Änderungen an einer Webanwendung werden heute meist erst nach dem Merge auf einer gemeinsamen Testumgebung sichtbar. Laufen mehrere Merge Requests parallel, überschreiben sie sich dort gegenseitig, Reviewer können eine Änderung nicht isoliert ausprobieren und Fehler fallen zu spät auf. Von Hand erstellte Test-VMs werden zudem gerne vergessen und verursachen laufende Kosten.
Zielsetzung und Methodik
Ziel dieser Arbeit ist eine Lösung, welche pro Merge Request vollautomatisch eine eigene Review-Umgebung auf AWS bereitstellt, aktualisiert und wieder abbaut. Methodisch wird hierbei bewusst eine entkoppelte Architektur umgesetzt: Die GitLab-Pipeline legt nur einen Auftrag in eine SQS-FIFO-Queue, eine Lambda-Funktion (Python) setzt diesen um. Die langlebige Basis-Infrastruktur wird vollständig in Terraform beschrieben und über die Pipeline ausgerollt. Als Oberfläche dienen die bestehenden GitLab «Review Apps» (Environment, URL, Stop-Auslöser).
Ergebnisse
Durch die technische Umsetzung erhält jeder Reviewer eine eigene, isolierte Umgebung, deren URL direkt im Merge Request sichtbar ist. Parallele Merge Requests stören sich nicht mehr gegenseitig, und da jede Umgebung beim Merge oder Schliessen automatisch abgebaut wird, entstehen keine vergessenen Instanzen und damit keine unnötigen Kosten. Die Arbeit zeigt, wie FAAS und Infrastructure as Code ineinandergreifen, um einen robusten, asynchronen Bereitstellungsprozess umzusetzen.
Ist-Situation
In der aktuellen Praxis existiert genau eine gemeinsame Testumgebung. Änderungen landen dort erst, nachdem sie in den Hauptzweig gemerged wurden. Wer eine Änderung vorher ausprobieren möchte, muss sie entweder lokal starten oder sich von Hand eine Test-VM in der AWS Management Console zusammenklicken.
GitLab bietet mit «Review Apps» zwar bereits dynamische Umgebungen pro MR an, inklusive URL-Anzeige im MR und automatischem Stoppen. Review Apps steuern aber nur den Lebenszyklus in GitLab, die eigentliche Bereitstellung auf AWS fehlt.
Problemanalyse der aktuellen Situation
Die gemeinsame Testumgebung und die manuellen Test-VMs bringen folgende Probleme mit sich:
- Gegenseitiges Überschreiben: Laufen mehrere Merge Requests parallel, überschreibt die zuletzt deployte Änderung alle anderen. Ein isoliertes Testen ist nicht möglich.
- Späte Fehlererkennung: Da Änderungen erst nach dem Merge sichtbar werden, fallen Fehler erst auf, wenn sie bereits im Hauptzweig sind.
- Vergessene Ressourcen: Von Hand erstellte Test-VMs werden nach dem Review gerne vergessen und verursachen laufende Kosten.
- Fehlende Reproduzierbarkeit: Manuell erstellte Test-VMs sind «Snowflake-Server», die sich nicht identisch wiederherstellen lassen.
- Zu weitreichende Rechte: Würde direkt aus dem CI-Job bereitgestellt, bräuchte der Runner weitreichende EC2-Rechte.
Methodik
Die Umsetzung erfolgt nach agilen Prinzipien in Anlehnung an das SCRUM-Framework mit drei Sprints. Der Product Backlog wird als GitLab Issues geführt und nach MoSCoW priorisiert. Zur Visualisierung des Arbeitsfortschritts wird das Issue Board von GitLab als Kanban-Board eingesetzt. Jeder Sprint wird mit einem Review und einer kurzen Retrospektive abgeschlossen.
Relevanz / Motivation
Relevanz Die Entwicklungsteams der Ronova arbeiten parallel an mehreren Merge Requests, teilen sich aber eine einzige Testumgebung. Damit Reviewer Änderungen isoliert und frühzeitig prüfen können, ohne dass dabei vergessene Test-VMs Kosten verursachen, ist es erforderlich, die Bereitstellung von Review-Umgebungen vollständig zu automatisieren.
Motivation Ich arbeite privat mit GitLab CI, Terraform und AWS und möchte genau diesen Workflow auch für meine eigenen Projekte nutzen. Zudem greifen hier FAAS und IaC ineinander, und asynchrone Verarbeitung, Nebenläufigkeit und Aufräumlogik sind keine Trivialität. Genau diese Herausforderung reizt mich.
Out-of-Scope
Für dieses Projekt sind folgende Punkte out of Scope:
- Die Entwicklung einer produktiven Webanwendung (es wird nur eine kleine Demo-Anwendung als Testobjekt verwendet)
- Produktive Umgebungen sowie Deployments in Produktion
- Datenbanken oder persistente Daten innerhalb der Review-Umgebungen
- Eigene Domains und TLS-Zertifikate pro Review-Umgebung
- Andere CI/CD-Systeme als GitLab CI/CD
Projektorganisation
| Name | Rolle | Kontaktinformationen | GitLab User | GitHub User |
|---|---|---|---|---|
| Ramon Schmocker | Projektleiter | [email protected] | @4G0NYY | @4G0NYY |
| Corrado ??? | Fachdozent PRJ | ??? | @??? | @??? |
| Armin Dörzbach | Fachdozent IaC & FAAS | [email protected] | @armindoerzbachtbz | @armindoerzbachtbz |
| Thanam Pangri | Lehrgangsleiter | [email protected] | @pat-teacher | @pat-teacher |
Technologie-Evaluierung
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. |
AWS-Berechtigungen
Projekt: Ephemere Review-Umgebungen pro Merge Request. Gegenstand: Berechtigungen im AWS-Schulaccount (AWS Academy Learner Lab), US.1. Prüfdatum: 06.11.2026 Durchführende Stelle: Projektleitung
Fazit
Der Schulaccount reicht für die Umsetzung, ein Wechsel auf den privaten Account (Fallback) ist nicht nötig. Alle benötigten Dienste lassen sich anlegen, ansteuern und wieder entfernen. Es gibt aber vier Einschränkungen, die Architektur und Planung beeinflussen:
| # | Einschränkung | Auswirkung | Massnahme |
|---|---|---|---|
| E1 | Keine eigenen IAM-Rollen oder -Benutzer (iam:CreateRole, iam:CreateUser verweigert) | Lambda, EC2 und Scheduler können keine eigene Least-Privilege-Rolle erhalten. Es gibt keinen eigenen IAM-Benutzer für den Runner, der nur sqs:SendMessage darf. | Alle Dienste nutzen die vorhandene LabRole bzw. das LabInstanceProfile. Terraform liest diese per data-Quelle statt sie anzulegen. Falls die Zeit reicht, kann eine Least-Privilege-Policy im privaten Account nachgewiesen werden. |
| E2 | Zugangsdaten sind temporäre Learner-Lab-Sitzungsdaten (Rolle voclabs) | Die CI/CD-Variablen laufen mit jeder Sitzung ab und müssen von Hand erneuert werden. Der Runner hat dieselben weitreichenden Rechte wie die Projektleitung. | Vor Pipeline-Läufen die Variablen AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY und AWS_SESSION_TOKEN erneuern. Im Testprotokoll und in der Betriebsdokumentation festhalten. |
| E3 | Nur die Regionen us-east-1 und us-west-2 sind freigegeben | Keine Bereitstellung in der Schweiz oder der EU. | Alles läuft in us-east-1. |
| E4 | Die Zone us-east-1e bietet keine t3-Instanzen an | Ein Subnetz ohne feste Zone landet zufällig dort, run-instances schlägt dann mit Unsupported fehl. Im ersten Prüflauf ist genau das passiert. | Subnetze in Terraform immer mit fester availability_zone (z.B. us-east-1a) anlegen. |
Damit ist das Akzeptanzkriterium «Eine Lambda-Funktion mit eigener Rolle kann erstellt werden» nicht erfüllbar. Die Lambda läuft mit der LabRole, was für die Funktion genügt, aber das Sicherheitsziel «Least Privilege» im Schulaccount nicht durchgesetzt werden kann.
Vorgehen
Die Rechte wurden nicht aus den Policies abgelesen, sondern mit echten Aufrufen geprüft: Jede benötigte Ressource wird angelegt, benutzt und wieder gelöscht. So fallen auch Einschränkungen auf, die nicht in einer IAM-Policy stehen (z.B. E4). Das Skript ist wiederholbar und räumt auch bei einem Abbruch alles auf:
./source/permission-check/check_permissions.sh
Ein Lauf dauert rund 7 Minuten, den grössten Teil davon wartet das Skript auf die Registrierung der Instanz bei SSM und die Docker-Installation per Run Command.
Vorhandene Lab-Rolle
| Eigenschaft | Wert |
|---|---|
| Angemeldet als | assumed-role/voclabs/<user> |
| Rolle für Dienste | LabRole |
| Instanzprofil für EC2 | LabInstanceProfile (enthält LabRole) |
Für das Projekt relevante Vertrauensstellungen der LabRole | lambda, ec2, ssm, sqs, events, scheduler, logs |
| Relevante verwaltete Policy | AmazonSSMManagedInstanceCore, damit sich Instanzen bei SSM melden |
Resultate
Stand des Prüflaufs vom 06.11.2026 in us-east-1.
| Prüfung | Ergebnis | Aufruf / Fehler |
|---|---|---|
| IAM: eigene Rolle erstellen | verweigert | not authorized to perform: iam:CreateRole |
| IAM: LabRole lesen | erlaubt | iam get-role |
| IAM: LabInstanceProfile lesen | erlaubt | iam get-instance-profile |
| Region eu-central-1 nutzbar | verweigert | not authorized to perform: ec2:DescribeVpcs |
| Region us-west-2 nutzbar | erlaubt | ec2 describe-vpcs |
| S3: Bucket erstellen | erlaubt | s3api create-bucket |
| S3: Versionierung aktivieren | erlaubt | s3api put-bucket-versioning |
| S3: Verschlüsselung setzen | erlaubt | s3api put-bucket-encryption |
| S3: Public Access Block setzen | erlaubt | s3api put-public-access-block |
| S3: Objekt schreiben | erlaubt | s3api put-object |
| S3: bedingtes Schreiben (If-None-Match) | erlaubt | s3api put-object |
| S3: Versionen auflisten | erlaubt | s3api list-object-versions |
| DynamoDB: Tabelle erstellen | erlaubt | dynamodb create-table |
| SQS: FIFO Dead-Letter-Queue erstellen | erlaubt | sqs create-queue |
| SQS: FIFO-Queue mit Redrive Policy erstellen | erlaubt | sqs create-queue |
| SQS: Nachricht mit Message-Group und Dedup-ID senden | erlaubt | sqs send-message |
| SSM: SecureString schreiben | erlaubt | ssm put-parameter |
| SSM: SecureString entschlüsselt lesen | erlaubt | ssm get-parameter |
| Lambda: Funktion mit LabRole erstellen | erlaubt | lambda create-function |
| Lambda: Funktion aufrufen | erlaubt | lambda invoke |
| Lambda: Reserved Concurrency setzen | erlaubt | lambda put-function-concurrency |
| Lambda: SQS-Trigger (Event Source Mapping) erstellen | erlaubt | lambda create-event-source-mapping |
| CloudWatch Logs: Lambda-Logs lesen | erlaubt | logs filter-log-events |
| EventBridge: Schedule-Regel erstellen | erlaubt | events put-rule |
| EventBridge: Lambda als Ziel setzen | erlaubt | events put-targets |
| Lambda: Aufrufrecht für EventBridge vergeben | erlaubt | lambda add-permission |
| EventBridge Scheduler: Schedule mit LabRole erstellen | erlaubt | scheduler create-schedule |
| EC2: VPC erstellen | erlaubt | ec2 create-vpc |
| EC2: Subnetz erstellen | erlaubt | ec2 create-subnet |
| EC2: Internet Gateway erstellen | erlaubt | ec2 create-internet-gateway |
| EC2: Internet Gateway anhängen | erlaubt | ec2 attach-internet-gateway |
| EC2: Routing-Tabelle erstellen | erlaubt | ec2 create-route-table |
| EC2: Default-Route setzen | erlaubt | ec2 create-route |
| EC2: Routing-Tabelle zuordnen | erlaubt | ec2 associate-route-table |
| EC2: Public IP im Subnetz aktivieren | erlaubt | ec2 modify-subnet-attribute |
| EC2: Security Group erstellen | erlaubt | ec2 create-security-group |
| EC2: Ingress HTTP freigeben | erlaubt | ec2 authorize-security-group-ingress |
| EC2: Launch Template erstellen | erlaubt | ec2 create-launch-template |
| EC2: Instanz aus Launch Template mit ClientToken und Tags starten | erlaubt | ec2 run-instances |
| EC2: ClientToken verhindert Doppelanlage | erlaubt | ec2 run-instances --client-token |
| EC2: Instanzen per MR-Tag finden | erlaubt | ec2 describe-instances |
| SSM: Instanz meldet sich beim Agent (LabInstanceProfile) | erlaubt | ssm describe-instance-information |
| SSM: Run Command senden | erlaubt | ssm send-command |
| SSM: Run Command installiert Docker und startet Container | erlaubt | ssm get-command-invocation |
| Budgets: Budget erstellen | erlaubt | budgets create-budget |
| Cost Explorer: Kosten abfragen | erlaubt | ce get-cost-and-usage |
| CloudWatch: Billing-Alarm erstellen | erlaubt | cloudwatch put-metric-alarm |
Bedeutung für die User Stories
| User Story | Benötigt | Ergebnis |
|---|---|---|
| US.3: Terraform Remote State | S3 mit Versionierung, State Locking | Möglich. S3 unterstützt bedingtes Schreiben, damit reicht use_lockfile = true ohne DynamoDB. DynamoDB wäre als Alternative ebenfalls erlaubt. |
| US.4: Basis-Infrastruktur | VPC, Subnetz, IGW, Security Group, SQS FIFO + DLQ, Lambda, Launch Template | Möglich, mit LabRole statt eigenen Rollen (E1) und fester Zone (E4). |
| US.6: Deploy | run-instances aus Launch Template, ClientToken, Tags | Möglich. Ein wiederholter Aufruf mit gleichem ClientToken liefert dieselbe Instanz, es entsteht keine zweite. |
| US.8: Update | SSM Run Command auf der Instanz | Möglich. Docker installieren und einen Container starten funktioniert über AWS-RunShellScript. |
| US.9: Destroy | Instanzen per Tag finden und terminieren | Möglich. |
| US.10: Robustheit | Dead-Letter-Queue, Reserved Concurrency | Möglich. |
| US.11: Aufräumen | EventBridge-Regel oder Scheduler mit Lambda als Ziel | Möglich, der Scheduler nutzt die LabRole. |
| US.12: Kosten | AWS Budgets, Cost Explorer | Möglich. Budget, Billing-Alarm und Kostenabfrage sind erlaubt. |
Architektur
Entwurf aus dem Einreichungsformular. Wird in Sprint 1 mit US.2 finalisiert.
Übersicht
graph LR
A[GitLab MR-Pipeline] -->|sqs:SendMessage| B[SQS FIFO Queue]
B -->|Trigger| C[Lambda Python]
B -.->|nach Wiederholungen| D[Dead-Letter-Queue]
C -->|RunInstances / Terminate| E[EC2 Review-Instanz]
C -->|SSM Run Command| E
C -->|Environment-URL| F[GitLab API]
E -->|docker pull| G[GitLab Container Registry]
Jede Umgebung ist eine EC2-Instanz mit der Demo-Anwendung als Container, identifiziert über die Tags Projekt und MR-ID.
Lebenszyklus
| Ereignis | Auslöser | Ablauf |
|---|---|---|
| MR eröffnet | MR-Pipeline, Job «deploy» mit Environment review/<MR-ID> | Image bauen und in die GitLab Registry pushen, Auftrag «deploy» einreihen. Die Lambda findet keine Instanz mit dem MR-Tag und startet eine neue aus dem Launch Template. Danach trägt sie die URL über die GitLab-API im Environment ein, so erscheint sie im MR. |
| Neuer Commit | Gleiche Pipeline erneut | Auftrag «deploy» mit neuem Image-Tag. Die Lambda findet die bestehende Instanz und aktualisiert sie über SSM Run Command (neues Image ziehen, Container neu starten). Instanz und URL bleiben gleich. |
| MR gemerged oder geschlossen | Bei MR-Pipelines startet GitLab automatisch den on_stop-Job | Auftrag «destroy» einreihen. Die Lambda terminiert alle Instanzen mit dem MR-Tag, auch solche, die noch starten. |
| Vergessen oder Fehler (Kann) | auto_stop_in und zeitgesteuerte Aufräum-Lambda | Entfernt Instanzen ohne aktives Environment oder älter als die TTL. |
Abgrenzung Terraform
Terraform verwaltet die langlebige Basis-Infrastruktur: VPC, Subnetze, Security Groups, Queue mit Dead-Letter-Queue, IAM-Rollen, Lambdas und das Launch Template der Review-Instanzen. Die Review-Instanzen selbst sind bewusst nicht im Terraform-State. Sie leben nur Stunden bis Tage und entstehen ausschliesslich aus dem versionierten Launch Template. Ihre Konfiguration bleibt so im Code definiert, ohne dass jede Umgebung einen eigenen State braucht.
Nebenläufigkeit
Ein Tag allein verhindert keine Doppelanlage, wenn zwei Aufträge gleichzeitig laufen. Deshalb hat jeder MR eine eigene FIFO-Message-Group, die Lambda verarbeitet also pro MR höchstens einen Auftrag gleichzeitig. Doppelte Nachrichten filtert die FIFO-Deduplizierung (Pipeline-ID), zusätzlich bekommt jeder Start ein EC2-ClientToken, mit dem EC2 bei einer Wiederholung keine zweite Instanz anlegt.
Sicherheit
- Least Privilege für IAM-Rollen, der Runner darf nur
sqs:SendMessage. - Keine Secrets im Repository: geschützte CI/CD-Variablen, GitLab-Token im SSM Parameter Store.
- Kein SSH, Zugriff auf die Instanzen nur über SSM. Security Groups nur HTTP/HTTPS.
Projektplanung
Backlog
Der priorisierte Backlog kann hier gefunden werden: GitLab.com | Backlog Der Backlog ist “Top-Down”, somit sind die obersten Userstories die am meisten priorisierten.
Zielsetzung
Folgende Ziele sollen im Rahmen dieses Projekts erfüllt werden:
| Nr. | Ziel | Messkriterium | Prio |
|---|---|---|---|
| Z1 | Die Basis-Infrastruktur ist vollständig in Terraform beschrieben und wird über die GitLab-Pipeline ausgerollt. | terraform apply auf leerem Account läuft fehlerfrei durch, terraform plan danach zeigt keine Änderungen. | Muss |
| Z2 | Ein neuer MR erhält automatisch eine eigene Umgebung. | Umgebung innert 5 Minuten erreichbar, URL als Environment im MR sichtbar. | Muss |
| Z3 | Ein neuer Commit aktualisiert die bestehende Umgebung. | Nach drei Commits genau eine Instanz pro MR, die neuste Version ist ausgeliefert. | Muss |
| Z4 | Merge oder Schliessen baut die Umgebung ab. | Nach Merge und nach Schliessen ist jeweils keine Instanz mit dem MR-Tag mehr vorhanden. | Muss |
| Z5 | Die Verarbeitung ist robust bei Nebenläufigkeit und Fehlern. | Testfälle bestanden: doppelte Nachricht, zwei gleichzeitige Pipelines für denselben MR, MR geschlossen während die Bereitstellung läuft. Fehlerhafte Aufträge landen in der Dead-Letter-Queue. | Muss |
| Z6 | Vergessene Umgebungen werden automatisch entfernt. | auto_stop_in gesetzt, Aufräum-Lambda entfernt Instanzen nach max. 24 h. | Kann |
| Z7 | Die Kosten sind transparent. | Kostenabschätzung pro Umgebung und Monat, AWS-Budget-Alarm aktiv. | Kann |
Mindestumfang: Ein vollständiger Durchlauf mit der Demo-Anwendung: MR eröffnen, Umgebung entsteht und die URL ist im MR sichtbar, ein neuer Commit aktualisiert sie, Merge oder Schliessen baut sie ab.
Story Points
Zur Schätzung des Aufwands wird die relative Schätzung mittels Story Points (Fibonacci-Folge) gewählt. Dies ermöglicht es, Komplexität, Unwägbarkeiten und den reinen Arbeitsaufwand entkoppelt von Zeitdruck zu bewerten. Eine Story mit 5 Punkten wird dabei als etwa doppelt so aufwendig/komplex wie eine Story mit 2 oder 3 Punkten eingestuft. Als Beispiel:
| Story Points | Komplexität | Beschreibung | Beispiel im Projekt |
|---|---|---|---|
| 1 | Trivial | Minimale Änderung, kein Risiko, sofort umsetzbar. | Tippfehler in der README korrigieren oder Label anpassen. |
| 2 | Einfach | Standardaufgabe ohne nennenswerte logische Hürden. | Berechtigungen im Schulaccount mit der AWS CLI prüfen. |
| 3 | Moderat | Erfordert Recherche oder einfache Logik/Verknüpfungen. | URL der Umgebung über die GitLab-API im Environment eintragen. |
| 5 | Komplex | Mehrere Abhängigkeiten, Fehlerbehandlung nötig, API-Interaktion. | Bestehende Instanz über SSM Run Command aktualisieren. |
| 8 | Gross | Hohe Unsicherheit, umfasst mehrere Systembereiche. | Erstmaliger Deploy-Ablauf (Pipeline -> SQS -> Lambda -> EC2). |
| 13 | Epic | Zu umfangreich für eine einzelne User Story. | “Den gesamten Lebenszyklus inkl. aller Testfälle entwickeln” -> Muss gesplittet werden! |
Priorisierung mit MoSCoW
Die Userstories sowie Tasks werden anhand von MoSCoW (Must have, Should have, Could have, Won’t have) priorisiert. Dies sorgt dafür, dass die Priorisierung auf den wirklich wichtigen Aufgaben liegt und nicht für “nice-to-have”-Dinge zu viel Zeit verbraucht wird. Must entspricht dabei dem Mindestumfang (Z1 bis Z5), die Kann-Ziele (Z6, Z7) sind Could.
Releases
Es wird gleich viele Releases wie auch Sprints geben. Somit: Pro Sprint ein Release. Dies sieht ungefähr wie folgt aus:
| Sprint | Release | genauere Bezeichnung | Nutzen |
|---|---|---|---|
| 1 | MVP | Minimal Viable Product | Die Basis-Infrastruktur steht in Terraform und ein Auftrag aus der Pipeline erreicht die Lambda (Durchstich). |
| 2 | MMP | Minimum Marketable Product | Der Mindestumfang läuft: Ein MR erhält eine Umgebung, ein Commit aktualisiert sie, Merge oder Schliessen baut sie ab. |
| 3 | MLP | Minimal Loveable Product | Die Lösung ist robust bei Nebenläufigkeit und Fehlern, räumt selbst auf und die Kosten sind transparent. |
Risikomanagement
| Risiko | W | S | Risikowert (W x S) | Mitigationsstrategie (Vermeidung/Lösung) |
|---|---|---|---|---|
| Einschränkungen des Schul-AWS-Accounts (IAM-Rollen, SQS FIFO, SSM) | 3 | 4 | 12 | Prüfung in Woche 1 vor jeder Umsetzung. Fallback: vorhandene Rollen nutzen oder privater Account im Free Tier. |
| Aufwand unterschätzt (50 h neben Arbeit und Schule) | 3 | 4 | 12 | Mindestumfang klar abgegrenzt, Kann-Ziele erst nach lauffähigem Mindestumfang. Zeiterfassung pro Sprint. |
| Doppelanlage bei gleichzeitigen Aufträgen | 3 | 3 | 9 | FIFO-Message-Group pro MR, Deduplizierung, EC2-ClientToken, eigener Testfall. |
| MR geschlossen während Bereitstellung, Instanz bleibt liegen | 3 | 3 | 9 | FIFO-Reihenfolge, Destroy terminiert auch startende Instanzen, eigener Testfall. |
| Kosten durch vergessene Instanzen | 3 | 3 | 9 | Kleine Instanztypen, Abbau über on_stop, Aufräum-Lambda und Budget-Alarm als Kann-Ziele. |
| Sicherheitslücken (offene Ports, Zugangsdaten im Repo) | 2 | 4 | 8 | Security Groups nur HTTP/HTTPS, kein SSH, Secrets nur in geschützten Variablen bzw. Parameter Store. |
| Datenverlust (Lokal) | 2 | 4 | 8 | Tägliche Commits und Pushes in das GitLab-Repository (Versionierung als Backup). |
| Ausfall der Hardware (Laptop) | 1 | 5 | 5 | Regelmässige Sicherung der wichtigsten Konfigurationen; Nutzung von Cloud-IDE-Alternativen im Notfall. |
Legende
W: Wahrscheinlichkeit (1 = unwahrscheinlich, 5 = sehr wahrscheinlich) S: Schadensausmass (1 = vernachlässigbar, 5 = kritisch für den Projektabschluss)
Risikowert: Priorisierung der Massnahmen (Hoch > 12, Mittel 6-12, Niedrig < 6)
Die Risiken werden bei jedem Sprint-Abschluss überprüft.
Kommunikation
Die Kommunikation mit den Stakeholdern findet grundsätzlich nur über MS Teams statt. Das Gitlab-Repo ist öffentlich einsehbar und kann unter diesem Link gefunden werden: Gitlab.com Die aus dem Gitlab-Repo automatisch generierte Website kann hier eingesehen werden: docs.sa2.ronova.to
Stakeholder-Analyse
| Name | Rolle | Einstellung | Einfluss | Interesse |
|---|---|---|---|---|
| Ramon Schmocker | Projektleiter / Developer | Hoch | Kritisch | Projekt so professionell, effizient und zielstrebig wie möglich abschliessen. |
| Corrado ??? | Fachexperte Projektmanagement | Mittel | Unterstützend | Hilfestellung für Projektmanagement-Anliegen / Challenges. |
| Armin Dörzbach | Fachexperte IaC & FAAS | Mittel | Unterstützend | Hilfestellung für technische Anliegen / Challenges. |
| Thanam Pangri | Lehrgangsleiter / Verantwortlich bei Eskalationen | Niedrig | Neutral | Professionelle Semesterarbeit, die bezeugt dass ich befähigt bin. |
Ramon Schmocker:
Kategorie: Schlüsselfigur
Strategie: Wichtig: Regeln: Kommunikation über Teams-Kanal. Projekt so ausführlich wie möglich dokumentieren und planen. Dies ist entscheidend für den Erfolg.
Corrado ???:
Kategorie: Fachexperte
Strategie: Starke Einbindung im Projektmanagement, bei Challenges nach Rat fragen. Bei Entscheidungsunsicherheit die Stakeholder miteinbeziehen.
Armin Dörzbach:
Kategorie: Fachexperte
Strategie: Sicherstellen, dass das Produkt fachgerecht programmiert ist und dass ich jede Zeile Code erklären kann. Den Architekturentscheid (ADR) frühzeitig besprechen.
Thanam Pangri:
Kategorie: Lehrgangsleiter
Strategie: Regelmässige Updates über Teams-Kanal bereitstellen. Bei Eskalationen in Absprache bleiben.
Projektzeitplanung
Projektzeitplan (Gantt)
Hier ist die Zeitliche Abfolge der Sprints und Meilensteine dargestellt:
gantt
title Semesterarbeit: Ephemere Review-Umgebungen
dateFormat YYYY-MM-DD
axisFormat %d.%m.
section Planung
Initialisierung (Einreichungsformular) :done, i0, 2026-10-16, 14d
Sprint 0 (Setup & Doku-Struktur) :active, s0, 2026-10-30, 7d
section Entwicklung
Sprint 1 (MVP - Basis-Infrastruktur) :s1, 2026-10-30, 28d
Einzelbesprechung 1 :milestone, e1, 2026-11-27, 0d
Sprint 2 (MMP - Mindestumfang) :s2, 2026-11-28, 42d
Einzelbesprechung 2 :milestone, e2, 2027-01-08, 0d
Sprint 3 (MLP - Robustheit & Kann-Ziele) :s3, 2027-01-09, 17d
Einzelbesprechung 3 :milestone, e3, 2027-01-25, 0d
section Abschluss
Abgabe der Arbeit :milestone, m1, 2027-01-27, 0d
Sprint 1
graph TD
%% Definition der Spalten (Subgraphs)
subgraph "To Do"
T1[US.0: Evaluierung der Lösungsmöglichkeiten]
T2[US.1: Berechtigungen im AWS-Schulaccount prüfen]
T3[US.2: Systemdesign & Architektur]
T4[US.3: Terraform Remote State & Pipeline]
T5[US.4: Basis-Infrastruktur in Terraform]
end
subgraph "In Progress"
P1[Aktuell keine Tasks]
end
subgraph "Done"
D1[Projektstruktur aufsetzen]
D2[GitLab CI/CD für Doku]
end
%% Styling für die Optik
style D1 fill:#dfd,stroke:#333
style D2 fill:#dfd,stroke:#333
Link zum Live Issue Board auf GitLab ↗
Sprint 2
graph TD
subgraph "To Do"
T1[US.5: Demo-Anwendung containerisieren]
T2[US.6: Deploy-Ablauf pro Merge Request]
T3[US.7: URL der Umgebung im Merge Request]
T4[US.8: Update-Ablauf bei neuem Commit]
T5[US.9: Destroy-Ablauf bei Merge oder Schliessen]
end
subgraph "In Progress"
P1[Aktuell keine Tasks]
end
subgraph "Done"
D1[Noch keine Tasks]
end
Link zum Live Issue Board auf GitLab ↗
Sprint 3
graph TD
subgraph "To Do"
T1[US.10: Robustheit bei Nebenläufigkeit & Fehlern]
T2[US.11: Automatisches Aufräumen vergessener Umgebungen]
T3[US.12: Kostentransparenz & Budget-Alarm]
T4[US.13: Betriebsdokumentation & Übergabe]
end
subgraph "In Progress"
P1[Aktuell keine Tasks]
end
subgraph "Done"
D1[Noch keine Tasks]
end
Link zum Live Issue Board auf GitLab ↗
Projektdurchführung
Zeiterfassung
Hier sind jegliche Arbeitsaufwände dieses Projekts dokumentiert.
FTE-Budget
Für diese Semesterarbeit ist ein Gesamtbudget von rund 50 Stunden (~6.25 FTE-Tage à 8 Stunden) eingeplant. Die nachfolgend dokumentierten Aufwände werden laufend gegen dieses Budget verrechnet, um den Verbrauch über die Sprints hinweg im Blick zu behalten.
| Phase | Zeitraum | Geplanter Aufwand |
|---|---|---|
| Initialisierung | 16.10. bis 30.10.26 | 3 h |
| Sprint 1 | 30.10. bis 27.11.26 | 16 h |
| Sprint 2 | 28.11.26 bis 08.01.27 | 18 h |
| Sprint 3 | 09.01. bis 25.01.27 | 13 h |
| Total | 50 h |
Genehmigungsverfahren (Sprint 0)
Das initiale ausfüllen, revidieren und Re-Orientieren des PKA (Semesterarbeits-Einreichungsformulars)
- Ausfüllen des Einreichungsformulars (V1.0) ~? Stunden
- Überarbeitung nach Feedback (V1.1) ~? Stunden
Initiales Aufsetzen des Projekts (Sprint 0)
In diesem Abschnitt ist das initiale Aufsetzen des GitLab-Repo’s sowie der Toolselektion
- GitLab Issue Boards aufsetzen ~? Stunden
- GitLab Repo Struktur definieren ~? Stunden
- GitLab CI/CD Pipeline für Webpage-Docs aufsetzen ~? Stunden
- Domainconnect für GitLab Pages ~? Stunden
Initiale Projektplanung (Sprint 0)
- Userstories in GitLab erfassen ~? Stunden
- Meilensteine definieren ~? Stunden
- Grobe Roadmap erstellen ~? Stunden
Subtotal Sprint 0
Total Sprint 0: ~? Stunden
Sprint 0
- Einreichungsformular überarbeitet anhand Feedback der Stakeholder
- Berechtigungen im AWS-Schulaccount prüfen (Lambda-Rolle, EC2, SQS FIFO, SSM), siehe AWS-Berechtigungen
- Userstories erstellen & priorisieren
- Just the Docs für Dokumentation implementieren
- GitLab Repo strukturieren
- Backlog Priorisierung definieren
- Template für Userstories definieren
- Template für Tasks definieren
- Story Points definieren
- Stakeholder definiert
- Ersten Sprint planen & Stakeholder informieren
- Besprechungen vereinbaren
Retrospektive
Folgt nach Abschluss von Sprint 0.
Room for Improvement Folgt nach Abschluss von Sprint 0.
Sprint 1
Plan des ersten Sprints
Ziele dieses Sprints:
- MVP-Release fertiggestellt zu haben
- Alle Tasks & Userstories, welche diesem Sprint zugewiesen sind, abzuschliessen.
Für die aktuellsten Informationen:
Link zum Live Issue Board auf GitLab ↗
Aufgaben für diesen Sprint
- US.0: Evaluierung der Lösungsmöglichkeiten
- US.1: Berechtigungen im AWS-Schulaccount prüfen
- US.2: Systemdesign & Architektur
- US.3: Terraform Remote State & Pipeline
- US.4: Basis-Infrastruktur in Terraform
Implementierung des ersten Sprints
Folgt während Sprint 1.
Review des ersten Sprints
Folgt nach Abschluss von Sprint 1.
Sprint 2
Plan des zweiten Sprints
Ziele dieses Sprints:
- MMP-Release fertiggestellt zu haben
- Alle Tasks & Userstories, welche diesem Sprint zugewiesen sind, abzuschliessen.
Für die aktuellsten Informationen:
Link zum Live Issue Board auf GitLab ↗
Aufgaben für diesen Sprint
- US.5: Demo-Anwendung containerisieren
- US.6: Deploy-Ablauf pro Merge Request
- US.7: URL der Umgebung im Merge Request
- US.8: Update-Ablauf bei neuem Commit
- US.9: Destroy-Ablauf bei Merge oder Schliessen
Implementierung des zweiten Sprints
Folgt während Sprint 2.
Review des zweiten Sprints
Folgt nach Abschluss von Sprint 2.
Sprint 3
Plan des dritten Sprints
Ziele dieses Sprints:
- MLP-Release fertiggestellt zu haben
- Alle Tasks & Userstories, welche diesem Sprint zugewiesen sind, abzuschliessen.
Für die aktuellsten Informationen:
Link zum Live Issue Board auf GitLab ↗
Aufgaben für diesen Sprint
- US.10: Robustheit bei Nebenläufigkeit & Fehlern
- US.11: Automatisches Aufräumen vergessener Umgebungen
- US.12: Kostentransparenz & Budget-Alarm
- US.13: Betriebsdokumentation & Übergabe
Implementierung des dritten Sprints
Folgt während Sprint 3.
Review des dritten Sprints
Folgt nach Abschluss von Sprint 3.
Betriebsdokumentation
Diese Betriebsdokumentation richtet sich an das Betriebsteam der Ronova, welches die Review-Umgebungen betreibt.
Folgt in Sprint 3 (US.13).
Ergebnisse & Analyse
Folgt nach Abschluss von Sprint 3: Soll/Ist-Vergleich der Ziele Z1 bis Z7, Lieferumfang und Aufwand.
Fazit & Ausblick
Folgt nach Abschluss von Sprint 3.