Semesterarbeit: End-to-End CI/CD-Pipeline mit Terraform, Helm und GH Actions für Nextcloud auf Kubernetes (AWS EKS)
Student: Nenad Stevic TBZ Lehrgang dipl. Informatiker/in HF - 3. Semester Abgabedatum: 09.07.2025
- 1. Einleitung
- 2. Projektmanagement
- 2.1 Scrum
- 2.2 Projektplanung
- 2.3 Sprint-Durchführung und Dokumentation
- 2.3.1 Sprint Overview Dashboard
- 2.3.2 Sprint 0: Bootstrap & Initialplanung
- 2.3.3 Sprint 1: AWS Account, Lokale Umgebung & Terraform Basis-Netzwerk (VPC)
- 2.3.4 Sprint 2: Terraform für EKS Cluster & ECR
- 2.3.5 Sprint 3: Terraform für RDS/IAM & Manuelles Nextcloud Deployment
- 2.3.6 Sprint 4: Nextcloud Helm Chart Entwicklung
- 2.3.7 Sprint 5: CI/CD Pipeline (GitHub Actions) & Tests
- 2.3.8 Sprint 6: Finalisierung & Vollständiges Lifecycle-Management
- 2.4 Risikomanagement
- 2.5 Stakeholder & Kommunikation
- 3. Evaluation
- 4. Implementierung und Technische Umsetzung
- 4.1 Infrastruktur-Provisionierung mit Terraform
- 4.1.1 Terraform State Backend - Foundation für Kollaboration
- 4.1.2 Netzwerk-Architektur - Defense in Depth
- 4.1.3 EKS Cluster - Managed Kubernetes mit Custom Tuning
- 4.1.4 IAM Roles for Service Accounts (IRSA) - Sichere Pod-Authentifizierung
- 4.1.5 Persistenter Speicher - EBS CSI Driver
- 4.1.6 RDS Datenbank - Managed PostgreSQL
- 4.2 Nextcloud Helm Chart - Anwendungs-Paketierung
- 4.3 CI/CD Pipeline - Automatisierte Deployments
- 4.4 Kritische Konfigurationsanpassungen
- 4.5 Deployment und Validierung
- 4.1 Infrastruktur-Provisionierung mit Terraform
- 5. Testing und Qualitätssicherung
- 6. Projektdokumentation (Zusammenfassung)
- 7. Reflexion und Erkenntnisse
- 8. Anhänge
In diesem Kapitel wird das Projekt, die Kriterien und die Vorgehensweise genauer unter die Lupe genommen. Damit wird ein Überblick über die geplante Arbeit geschaffen, was die Auswertung der Ergebnisse am Schluss vereinfachen soll.
Das Hosten von Webanwendungen mit High-Availability Infrastrukturen bringt komplexe Herausforderungen mit sich: Wie laufen mehrere Instanzen einer Applikation parallel, ohne die Datenintegrität auf der DB zu gefährden? Wie konfiguriert man die verschiedenen Komponenten fehlerfrei?
Diese Probleme begegnen uns täglich beim Hosting von Kundenanwendungen, auch im aktuellen Betrieb. Da ich schon Erfahrungen in diesem Bereich sammeln konnte, aber bisher nie von Grund auf so eine Architektur beim Aufbau begleitet habe, schien mir dies eine Packende und interessante Aufgabe.
Die Ziele folgen dem SMART-Prinzip (Spezifisch, Messbar, Attraktiv, Relevant, Terminiert):
-
Automatisierte Infrastruktur via Terraform
AWS-Infrastruktur (EKS, RDS, ECR) vollständig als Code erstellen. -
Funktionales Nextcloud Helm Chart
Eigenständiges Chart für Kubernetes-Deployments, Services, PVCs und Datenbankverbindungen. -
CI/CD-Pipeline mit GitHub Actions
Automatisierte Pipeline für kompletten Deployment-Prozess bei Code-Änderungen. -
Funktionale Nextcloud Instanz
Extern erreichbare, datenbankverbundene Instanz mit Datenpersistenz. -
Vollständige Dokumentation
Systemarchitektur, Code und Setup-Prozess dokumentiert.
Warum SMART? Jedes Ziel ist spezifisch definiert, hat messbare Erfolgskriterien, ist attraktiv für DevOps-Entwicklung, relevant für die Berufspraxis und terminiert.
Die Lösung basiert vollständig auf "Infrastructure as Code" (IaC):
- Infrastruktur-Provisionierung: Cloud-Infrastruktur via Terraform
- Anwendungs-Deployment: Nextcloud via eigenem Helm Chart auf Kubernetes
- Automatisierung: Kompletter Lifecycle via GitHub Actions CI/CD-Pipeline
- Methodisches Vorgehen: Agile Entwicklung nach Scrum-Framework mit iterativer Entwicklung und begleitender Dokumentation
Dabei wird bei der Entwicklung des Projekts auf Scrum basiertes, Agiles Entwickeln gesetzt.
Diese Semesterarbeit implementiert eine durchgängig automatisierte Pipeline zur Bereitstellung von Nextcloud auf AWS EKS. Die Lösung nutzt Terraform für Cloud-Infrastruktur, Helm für Kubernetes-Paketierung und GitHub Actions für CI/CD-Automatisierung. Ziel ist eine robuste, wiederholbare Deployment-Methode und die Vertiefung von DevOps- und Cloud-native-Kompetenzen.
Zur Sicherstellung der Realisierbarkeit innerhalb des vorgegebenen Zeitrahmens werden folgende Aspekte klar definiert und abgegrenzt:
Im Projektumfang (In Scope):
- Automatisierte Kern-Infrastruktur (EKS, RDS, ECR) via Terraform
- Funktionales Nextcloud Helm Chart mit Persistenz und Datenbankanbindung
- CI/CD-Pipeline mit GitHub Actions für EKS-Deployment
- Sichere Secret-Handhabung für Datenbank und Pipeline-Authentifizierung
- Extern erreichbare Nextcloud-Instanz mit Datenpersistenz
- Architektur- und Setup-Dokumentation
Nicht im Projektumfang (Out of Scope):
- Erstellung einer eigenen Applikation/Eigener Fork von Nextcloud
- Komplexe Nextcloud-Konfigurationen oder externe Authentifizierungssysteme
- Automatisierte Backup/Restore-Strategien
- Advanced Monitoring/Logging über Kubernetes/AWS-Standards hinaus
- Performance-Optimierung und Lasttests
- Multi-Cloud-Support oder andere Kubernetes-Distributionen
- Custom Nextcloud Docker-Images
- Compliance-Anforderungen über IT-Security Best Practices hinaus
Dieses Projekt folgt dem Scrum-Framework, um eine iterative Entwicklung und transparente Nachvollziehbarkeit zu gewährleisten. Alle Rollen werden durch mich, den Studierenden, wahrgenommen, die Prinzipien aber konsequent eingehalten.
Product Goal: Bis zum 09.07.2025 eine vollautomatisierte CI/CD-Pipeline mit Terraform, Helm und GitHub Actions implementieren, die eine funktionale Nextcloud-Instanz auf AWS EKS bereitstellt und verwaltet.
Alle Scrum-Rollen werden durch mich, Nenad Stevic, wahrgenommen:
- Product Owner: Definition der Produktvision und Priorisierung des Backlogs
- Scrum Master: Prozesseinhaltung und Beseitigung von Hindernissen
- Developer: Technische Umsetzung der Sprint-Ziele
- Product Backlog: Dynamische Liste aller Anforderungen, geführt als GitHub Project Board
- Sprint Backlog: Ausgewählte Items für den aktuellen Sprint mit konkretem Umsetzungsplan
- Increment: Lauffähiger Code und aktualisierte Dokumentation nach jedem Sprint
Um Scrum auch als Einzelperson konsequent zu leben, werden alle Zeremonien mehr oder weniger durchgeführt - wenn auch in angepasster Form:
Sprint Planning findet zu Beginn jedes Sprints statt. Als Product Owner präsentiere ich mir die priorisierten Backlog Items, wechsle dann in die Developer-Rolle und wähle realistisch umsetzbare Items aus. Das Sprint-Ziel wird klar definiert und die konkreten Aufgaben geplant.
Daily Scrum wird als tägliche 5-10 Minuten Reflexion durchgeführt. Die drei klassischen Fragen - Was wurde gestern erreicht? Was wird heute getan? Gibt es Hindernisse? - werden beantwortet. Diese Routine sollte helfen, den Fokus zu behalten und nicht in Rabbit Holes zu verschwinden.
Sprint Review erfolgt am Sprint-Ende durch Demonstration des Inkrements. Auch wenn keine externen Stakeholder anwesend sind, wird das Erreichte kritisch begutachtet und das Product Backlog entsprechend angepasst.
Sprint Retrospective ist besonders wertvoll für kontinuierliche Verbesserung. Was lief gut? Was kann optimiert werden? Konkrete Massnahmen für den nächsten Sprint werden abgeleitet.
Backlog Refinement passiert kontinuierlich während des Sprints. User Stories werden detailliert, geschätzt und bei Bedarf aufgeteilt, um das Product Backlog stets in einem "ready" Zustand zu halten.
Was bedeutet "fertig" in diesem Projekt? Ein Backlog Item durchläuft mehrere Qualitätsstufen: Der Code wird direkt auf
dem main-Branch entwickelt und committet (trunk-based development). Automatisierte Prüfungen wie terraform validate
und helm lint müssen grün sein. Die Infrastruktur wird erfolgreich deployed und die Funktionalität verifiziert. Alle
Akzeptanzkriterien sind erfüllt, die Dokumentation aktualisiert und das Item wandert im Project Board in die "Done"
-Spalte. Erst dann gilt ein Feature als wirklich abgeschlossen und bereit für den produktiven Einsatz.
Eine gute Planung ist das A und O, auch wenn man agil unterwegs ist. In diesem Kapitel wird behandelt, wie die Roadmap zur fertigen Nextcloud-Pipeline auszusehen hat.
Der zeitliche Rahmen orientiert sich an den offiziellen TBZ-Terminen, insbesondere den Einzelbesprechungen und dem finalen Abgabetermin am 09.07.2025. Basierend auf ersten Aufwandsschätzungen für die Hauptkomponenten wurde ein visueller Zeitplan erstellt, der die übergeordneten Projektphasen und geplanten Sprints im Überblick zeigt:
Dieser Plan dient als Orientierung und wird iterativ verfeinert. Die sechs geplanten Sprints à zwei Wochen (plus/minus) ermöglichen eine strukturierte Herangehensweise, während genügend Flexibilität für Anpassungen bleibt.
Das Projekt gliedert sich in acht thematische Arbeitspakete (Epics), die den Weg von der Projektinitialisierung bis zur fertigen CI/CD-Pipeline strukturieren. Diese Epics bauen logisch aufeinander auf und können sich über mehrere Sprints erstrecken:
| Epic | Fokus | Beschreibung | Abhängigkeiten |
|---|---|---|---|
PROJMGMT |
Setup | Schaffung der organisatorischen Grundlagen: Repository-Setup, initiale Dokumentation und GitHub Project Board | - |
TF-NET |
Infrastruktur | Aufbau des Cloud-Fundaments mit VPC, Subnetze, Internet Gateway, Routing-Tabellen und Security Groups | PROJMGMT |
TF-K8S |
Platform | Automatisierte Bereitstellung eines managed EKS-Clusters und einer privaten ECR-Registry | TF-NET |
TF-DB-IAM |
Services | Provisionierung einer managed RDS-Datenbank und aller notwendigen IAM-Rollen für sichere Service-Kommunikation | TF-NET |
NC-DEPLOY |
Application | Manuelle Installation und Konfiguration von Nextcloud zur Validierung der Datenbankanbindung und Persistenz | TF-K8S, TF-DB-IAM |
HELM |
Automation | Entwicklung eines robusten, konfigurierbaren Helm Charts für konsistente, reproduzierbare Nextcloud-Deployments | NC-DEPLOY |
CICD |
Pipeline | Implementierung der vollautomatisierten CI/CD-Pipeline mit GitHub Actions für kontinuierliche Deployments | HELM |
ABSCHLUSS |
Delivery | Umfassendes End-to-End-Testing der Gesamtlösung und Finalisierung der Projektdokumentation | CICD |
| Tabelle: Epic Issues |
Die Detailplanung erfolgt Sprint für Sprint. Jeder Sprint hat ein klares Ziel, aus dem konkrete User Stories mit Akzeptanzkriterien abgeleitet werden. Das Product Backlog wird kontinuierlich gepflegt und priorisiert, ohne das gesamte Projekt vorab bis ins Detail zu planen.
Diese Flexibilität ermöglicht es, auf Erkenntnisse aus vorherigen Sprints zu reagieren und die Planung entsprechend anzupassen.
Dieser Abschnitt dokumentiert die Durchführung aller sechs Sprints mit ihren wichtigsten Ergebnissen, Herausforderungen und Lernerfahrungen. Jeder Sprint folgt dem definierten Scrum-Zyklus mit Planning, Daily Scrums, Review und Retrospektive.
| Sprint | Ziel | Status | Stories | Impediments | Schlüsselelement |
|---|---|---|---|---|---|
| 0 | Bootstrap & Setup | ✅ Complete | 6/6 | 1 | Project foundation |
| 1 | AWS Foundation | ✅ Complete | 5/5 | 2 | VPC + Tools setup |
| 2 | EKS & ECR | ✅ Complete | 4/4 | 1 | K8s platform ready |
| 3 | RDS & Manual Deploy | ✅ Complete | 5/5 | 2 | Proof-of-concept |
| 4 | Helm Chart | ✅ Complete | 5/5 | 1 | Standardized deployment |
| 5 | CI/CD Pipeline | ✅ Complete | 3/3 | 1 | Full automation |
| 6 | Lifecycle & Polish | ✅ Complete | 6/6 | 1 | Complete solution |
| Tabelle: Sprint-Übersicht |
Dauer: 05. Mai - 09. Mai 2025 (Erledigt 9. Mai 2025)
Zugehöriges Epic: EPIC-PROJMGMT
Sprint Planning: 05.05.2025 (simuliert)
Basierend auf den Projektanforderungen und den TBZ-Vorgaben wurde dieser Sprint darauf ausgerichtet, die Projektbasis zu schaffen (D.h. Setup de Repo, Grundgerüst des Dokuments usw.).
"Die grundlegende Projektinfrastruktur (Repository, Scrum-Board, initiale Dokumentation) ist etabliert, das Scrum-Rahmenwerk für das Projekt ist definiert und dokumentiert, und eine erste Grobplanung (Epics, Roadmap) sowie die Detailplanung für Sprint 1 sind vorhanden, um eine solide Basis für die erfolgreiche Durchführung der Semesterarbeit zu schaffen."
| User Story | Was wurde umgesetzt | Interessante Erkenntnisse/Herausforderungen | Abgeschlossen |
|---|---|---|---|
Nextcloud#33 |
Repository-Initialisierung mit Grundstruktur (src/, charts/, docs/) |
Entscheidung für monorepo-Ansatz statt separate Repos für Terraform/Helm | 05.05.2025 |
Nextcloud#34 |
Scrum-Framework Definition: DoD, DoR, Product Goal, Epic-Struktur | Anpassung der Standard-Scrum-Rollen für Einzelperson erwies sich als knifflig | 06.05.2025 |
Nextcloud#35 |
6-Sprint-Roadmap mit Gantt-Diagramm und Sprint 1 Detailplanung | Aufwandsschätzung ohne Referenzwerte sehr schwierig - erste Schätzungen erwiesen sich später als zu optimistisch | 07.05.2025 |
Nextcloud#36 |
Risikomatrix für AWS-Kosten, Technologie-Komplexität, Zeitrisiken | AWS Free Tier Limits als kritisches Risiko identifiziert - führte zu kostenoptimierten Architekturentscheidungen | 08.05.2025 |
Nextcloud#1 |
GitHub Project Board mit Kanban-Workflow, Epic-Labels, Automation | Board-Automation (Auto-move to "In Progress") funktionierte nicht wie erwartet - manueller Workflow notwendig | 08.05.2025 |
Nextcloud#3 |
Issue-Templates für User Stories, Bugs, Epics mit Akzeptanzkriterien | Template-Syntax anfangs verwirrend - mehrere Iterationen bis zufriedenstellende Form erreicht | 09.05.2025 |
| Tabelle: Sprint 0 - User Stories |
| Komponente | Deliverable | Wichtigste Features | Nachweis |
|---|---|---|---|
| Repository | GitHub Repo initialisiert | Verzeichnisstruktur (src/, charts/, docs/), README-Template, MIT-Lizenz |
github.com/Stevic-Nenad/Nextcloud |
| Scrum-Framework | Vollständige Prozessdefinition | Product Goal, 8-Punkte DoD, Epic-Struktur, User Story Format | Kapitel 2.1 |
| Project Board | Funktionales Kanban-Board | 4 Spalten, Epic-Labels, Issue-Templates, Workflow-Automation | GitHub Project Board |
| Sprint 1 Planung | Detailliertes Backlog | 5 User Stories mit Akzeptanzkriterien, Abhängigkeiten identifiziert | Issues #37, #38, #6, #5, #7 |
| Risikoanalyse | Risikomatrix erstellt | 12 Risiken bewertet, AWS-Kosten als kritisch identifiziert | Kapitel 2.4 |
| Roadmap | 6-Sprint-Zeitplan | Gantt-Diagramm, Meilensteine, Epic-zu-Sprint-Zuordnung | Kapitel 2.2.1 |
| Tabelle: Sprint 0 - Inkremente |

Bild: Sprint 0 - GitHub Project Board nach Sprint Planning - 6 User Stories committet mit Epic-Labels

Bild: Sprint 0 - Detailansicht User Story mit vollständigen Akzeptanzkriterien

Bild: Sprint 0 - Alle 6 User Stories erfolgreich in "Done" Spalte - Sprint-Ziel erreicht

Bild: Sprint 0 - Finale Repository-Struktur mit professioneller Verzeichnisorganisation
Hauptimpediment: Krankheitsbedingter Ausfall (06.–07. 05. 2025)
Auswirkung: Reduzierte verfügbare Arbeitszeit
Ergebnis: Sprint-Ziel trotzdem erreicht
Lösungsschritte
- 🚀 Mehr Freizeit investiert
- 🎯 Kernaufgaben priorisiert
Demo-Highlights: Funktionales GitHub Project Board mit automatisierten Workflows präsentiert
Stakeholder-Feedback: Solide Projektbasis geschaffen, bereit für technische Sprints
Sprint-Ziel Status: ✅ Vollständig erreicht (6/6 User Stories abgeschlossen)
Nächste Schritte: Sprint 1 kann planmässig starten mit AWS-Account-Setup
| 😊 Was lief gut | 😕 Was lief schlecht | 💡 Lessons Learned | ⚡ Action Items |
|---|---|---|---|
| Priorisierung half bei Zeitdruck | GitHub Automation komplexer als erwartet | Scrum für 1 Person braucht Anpassungen | Zeitpuffer in zukünftige Sprints einplanen |
| Akzeptanzkriterien als Checklisten | Aufwandsschätzung ohne Referenz schwierig | Detailplanung reduziert Stress | Risikobewertung kontinuierlich machen |
| Klare Epic-Struktur etabliert | Issue-Template-Syntax verwirrend | GitHub Features haben Lernkurve | Template-Dokumentation erstellen |
| Tabelle: Sprint 0 - Retro |
Dauer: 10. Mai - 24. Mai 2025 (Erledigt 24. Mai 2025)
Zugehöriges Epic: EPIC-PROJEKT, EPIC-NETZ
Sprint Planning: 09.05.2025 (simuliert)
Nach erfolgreichem Abschluss von Sprint 0 zielte dieser erste operative Sprint darauf ab, die fundamentalen technischen Grundlagen für alle weiteren Infrastrukturarbeiten zu schaffen. Ohne sicheren AWS-Zugang, lokale Entwicklungsumgebung und grundlegende Netzwerkstruktur wären keine weiteren Komponenten sinnvoll umsetzbar.
"Ein sicherer AWS Account und eine lokale Entwicklungsumgebung sind eingerichtet, das Terraform Remote Backend ist konfiguriert, und ein grundlegendes, korrekt getaggtes AWS VPC-Netzwerk ist mittels Terraform Code definiert, versioniert und erfolgreich provisioniert."
| User Story | Was wurde umgesetzt | Interessante Erkenntnisse/Herausforderungen | Abgeschlossen |
|---|---|---|---|
Nextcloud#37 |
AWS Root Account mit MFA, IAM User "terraform-admin", AWS CLI Profile "nextcloud-project", Budget $20/Monat | AWS Free Tier Limits mussten genau geprüft werden - AdministratorAccess pragmatisch aber nicht Least Privilege | 24.05.2025 |
Nextcloud#38 |
Lokale Tools: AWS CLI v2.x, Terraform v1.9.x, kubectl v1.30.x, Helm v3.15.x, IntelliJ Ultimate | Unterschiedliche Installationsmethoden je nach OS erforderten flexible Dokumentation | 24.05.2025 |
Nextcloud#7 |
Globale Tagging-Strategie implementiert, AWS Provider mit default_tags konfiguriert | Standard-Tags automatisch auf alle Ressourcen propagiert - wichtige Basis für Kostenkontrolle | 24.05.2025 |
Nextcloud#6 |
S3 Backend und DynamoDB State Locking für Terraform Remote Backend konfiguriert | Backend-Konfiguration extern verwaltet, keine AWS Keys im Code hardcodiert | 24.05.2025 |
Nextcloud#5 |
VPC mit öffentlichen/privaten Subnetzen, NAT Gateway pro AZ für Hochverfügbarkeit | NAT-Gateway-pro-AZ-Architektur komplexer als initial geschätzt aber bessere HA-Lösung | 24.05.2025 |
| Tabelle: Sprint 1 - User Stories |
| Komponente | Deliverable | Wichtigste Features | Nachweis |
|---|---|---|---|
| AWS Account | Sichere Produktionsreife Konfiguration | MFA aktiviert, IAM User, Budget Alerts, eu-central-1 als Standard-Region | AWS Console, ~/.aws/credentials |
| Lokale Umgebung | Vollständig eingerichtetes Development Setup | AWS CLI, Terraform, kubectl, Helm, IntelliJ - alle Tools getestet und verifiziert | Terminal-Ausgaben der Versionsprüfungen |
| Terraform Basis | Modulare Provider-Konfiguration | Globale Tags, AWS Provider v5.x, Standardregion konfiguriert | src/terraform/provider.tf, locals.tf |
| Remote Backend | Zentrale State-Verwaltung | S3 Bucket mit Versionierung, DynamoDB Locking, Verschlüsselung | src/terraform/backend.tf, terraform init Erfolg |
| VPC Netzwerk | Hochverfügbare Netzwerkarchitektur | 2 AZ, öffentliche/private Subnetze, NAT Gateway pro AZ, IGW, Route Tables | AWS VPC Console, terraform plan/apply |
| Kostenmanagement | Automatisches Tagging & Budget | Alle Ressourcen mit Projekt-Tags, $20 Budget mit 80%/100% Alerts | AWS Billing Dashboard, Resource Tags |
| Tabelle: Sprint 01 - Inkremente |
Bild: Sprint 1 - Sicherer AWS Account mit aktiviertem MFA und konfiguriertem IAM User "terraform-admin"
Bild: Sprint 1 - Vollständig eingerichtete lokale Entwicklungsumgebung mit allen erforderlichen Tools
Bild: Sprint 1 - Provisionierte VPC-Netzwerkarchitektur mit NAT Gateway pro Availability Zone
Bild: Sprint 1 - Konfiguriertes S3 Remote Backend mit DynamoDB State Locking
Hauptimpediment: AWS Free Tier Limits und Kostenoptimierung
Auswirkung: Architekturentscheidungen mussten kostenbewusst getroffen werden
Ergebnis: NAT Gateway pro AZ als Kompromiss zwischen HA und Kosten
Lösungsschritte
- 💰 AWS Budget mit Alerts eingerichtet
- 🏷️ Globale Tagging-Strategie für Kostentransparenz
- ⚖️ NAT Gateway pro AZ statt single NAT für bessere Verfügbarkeit
Demo-Highlights: Vollständige AWS-Infrastruktur via Terraform Code demonstriert - von Account-Setup bis
VPC-Provisionierung
Stakeholder-Feedback: Solide technische Basis geschaffen, NAT-Gateway-pro-AZ-Strategie als gute Designentscheidung
bewertet
Sprint-Ziel Status: ✅ Vollständig erreicht (5/5 User Stories abgeschlossen)
Nächste Schritte: Sprint 2 kann mit EKS Cluster Aufbau starten
| 😊 Was lief gut | 😕 Was lief schlecht | 💡 Lessons Learned | ⚡ Action Items |
|---|---|---|---|
| Klare Zielsetzung half bei Fokussierung | Aufwandsschätzung VPC zu optimistisch | Remote Backend früh etablieren zahlt sich aus | Detailliertere Recherche bei komplexen Tasks |
| Best Practices von Anfang an implementiert | AdministratorAccess nicht Least Privilege | AWS Free Tier Limits beeinflussen Architektur | IAM Policies für Sprint 2 spezifischer gestalten |
| Strukturierte User Story Aufteilung | Kleine Impediments nicht immer dokumentiert | Parallele Dokumentation bewährt sich | Konsequentere Impediment-Erfassung |
| NAT Gateway pro AZ für echte HA | Tool-Kompatibilitäten unterschätzt | Kostenmanagement ist kritischer Erfolgsfaktor | Terraform Provider Versionen genauer prüfen |
| Tabelle: Sprint 1 - Retro |
Dauer: 25. Mai - 01. Juni 2025 (Erledigt 01. Juni 2025)
Zugehöriges Epic: EPIC-TF-K8S
Sprint Planning: 24.05.2025 (simuliert)
Aufbauend auf der soliden VPC-Infrastruktur aus Sprint 1 zielte dieser Sprint darauf ab, das Herzstück der Container-Plattform zu schaffen: einen vollwertigen Kubernetes-Cluster mit persistenter Speicherunterstützung und sicherer Container-Registry-Integration.
"Ein funktionsfähiger AWS EKS Kubernetes-Cluster mit konfigurierten Node Groups und einem IAM OIDC Provider ist mittels Terraform automatisiert provisioniert. Zusätzlich ist ein AWS ECR Repository für Docker-Images via Terraform erstellt und der AWS EBS CSI Driver im EKS Cluster für persistente Volumes installiert und konfiguriert."
| User Story | Was wurde umgesetzt | Interessante Erkenntnisse/Herausforderungen | Abgeschlossen |
|---|---|---|---|
Nextcloud#8 |
EKS Control Plane K8s v1.29, Managed Node Group t3.medium (2 Nodes), IAM Rollen für Cluster & Nodes | assume_role_policy Syntax anfangs problematisch - Worker Nodes erfolgreich in private Subnetze platziert |
01.06.2025 |
Nextcloud#10 |
IAM OIDC Provider mit dynamischem Root-CA-Thumbprint, IRSA-Rolle für EBS CSI Driver | IRSA Trust Policy Komplexität unterschätzt - Condition-Klausel für Service Account Binding war der Schlüssel |
01.06.2025 |
Nextcloud#9 |
Privates ECR Repository mit Image Scanning, Lifecycle Policy für ungetaggte Images (30 Tage) | JSON-Syntax für ECR Lifecycle Policy erforderte AWS-Dokumentation-Recherche | 01.06.2025 |
Nextcloud#11 |
AWS EBS CSI Driver als EKS Add-on via IRSA, Test PVC erfolgreich an dynamisches EBS Volume gebunden | EKS Add-on Ansatz stabiler als Helm - Live-Test mit PVC/PV-Binding bestätigte Funktionalität | 01.06.2025 |
| Tabelle: Sprint 2 - User Stories |
| Komponente | Deliverable | Wichtigste Features | Nachweis |
|---|---|---|---|
| EKS Cluster | Produktionsreifer Kubernetes Cluster | K8s v1.29, HA mit 2 Worker Nodes in privaten Subnetzen, Auto-Scaling bereit | kubectl get nodes -o wide, EKS Console |
| IAM OIDC Provider | Sichere Pod-zu-AWS-Service Integration | IRSA aktiviert, dynamischer Thumbprint, Service Account basierte Rollen | AWS IAM Console, Trust Policy Verification |
| ECR Repository | Private Container Registry | Image Scanning aktiviert, Lifecycle Policy, Repository URL als Terraform Output | AWS ECR Console, terraform output |
| EBS CSI Driver | Persistente Speicherlösung | EKS-verwaltetes Add-on, IRSA-konfiguriert, dynamische Volume-Provisionierung | kubectl get pvc, AWS EC2 Volumes |
| Terraform Config | Modulare IaC-Struktur | Getrennte Dateien (eks.tf, ecr.tf, iam_oidc.tf), saubere Resource-Organisation | src/terraform/ Verzeichnisstruktur |
| kubectl Integration | Lokaler Cluster-Zugriff | kubeconfig automatisch konfiguriert, Ready-Status aller Nodes verifiziert | aws eks update-kubeconfig Erfolg |
| Tabelle: Sprint 2 - Inkremente |
Bild: Sprint 2 - Vollständig provisionierter EKS Cluster mit 2 Worker Nodes im Ready-Status
Bild: Sprint 2 - Privates ECR Repository mit aktiviertem Image Scanning und Lifecycle Policy
Bild: Sprint 2 - IAM OIDC Provider und IRSA-Rolle für sicheren Pod-zu-AWS-Service Zugriff
Bild: Sprint 2 - Erfolgreicher PVC-Test mit dynamisch provisioniertem EBS Volume
Hauptimpediment: IRSA (IAM Roles for Service Accounts) Komplexität
Auswirkung: Trust Policy Syntax und Condition-Klauseln zeitaufwändiger als erwartet
Ergebnis: Sichere, anmeldeinformationsfreie AWS-API-Integration erreicht
Lösungsschritte
- 📚 Intensive AWS IRSA Dokumentation studiert
- 🔍 Trust Policy Condition-Syntax für Service Account Binding verstanden
- ✅ Live-Test mit PVC-Binding bestätigte erfolgreiche Implementierung
Demo-Highlights: Live-Demonstration der kompletten Container-Plattform - von terraform apply über
kubectl get nodes bis hin zum dynamischen PVC-Binding
Stakeholder-Feedback: Robuste und sichere Basis für Anwendungs-Deployments geschaffen, EKS Add-on Ansatz als stabile
Entscheidung gewürdigt
Sprint-Ziel Status: ✅ Vollständig erreicht (4/4 User Stories abgeschlossen)
Nächste Schritte: Sprint 3 kann mit RDS-Datenbank-Setup beginnen
| 😊 Was lief gut | 😕 Was lief schlecht | 💡 Lessons Learned | ⚡ Action Items |
|---|---|---|---|
| Logische Story-Aufteilung sehr effektiv | IRSA Komplexität unterschätzt | EKS Add-on stabiler als Helm-Installation | Spike-Tickets für unbekannte AWS Services |
| Proaktive kubeconfig Problemlösung | Terraform plan/apply dauert länger | VPC aus Sprint 1 war perfekte Basis | Modulare Terraform-Struktur beibehalten |
| Dokumentation von Architekturentscheidungen | ECR Lifecycle Policy JSON-Syntax | Isolierte Verifikation jeder Komponente | Komplexitätsbewertung vor Implementierung |
| Stabile Integration aller Komponenten | Trust Policy Syntax Learning Curve | Live-Tests bestätigen echte Funktionalität | Terraform-Performance in Zeitplanung berücksichtigen |
| Tabelle: Sprint 2 - Retro |
Dauer: 03. Juni - 14. Juni 2025 (Erledigt 11. Juni 2025)
Zugehöriges Epic: EPIC-TF-DB-IAM, EPIC-NC-DEPLOY
Sprint Planning: 02.06.2025 (simuliert)
Dieser entscheidende Sprint sollte die letzte grosse Infrastruktur-Abhängigkeit schaffen und die Funktionsfähigkeit der Gesamtplattform validieren. Das Ziel: absolute Sicherheit durch ein manuelles Proof-of-Concept-Deployment, bevor die Automatisierung beginnt.
"Eine ausfallsichere AWS RDS PostgreSQL-Instanz ist via Terraform provisioniert und sicher konfiguriert, sodass nur der EKS-Cluster darauf zugreifen kann. Die erfolgreiche Integration der gesamten Infrastruktur wird durch ein manuelles Deployment einer funktionalen, datenbank-angebundenen und persistenten Nextcloud-Instanz nachgewiesen."
| User Story | Was wurde umgesetzt | Interessante Erkenntnisse/Herausforderungen | Abgeschlossen |
|---|---|---|---|
Nextcloud#12 |
RDS PostgreSQL 16.2 (db.t3.micro) in privaten Subnetzen, Master-Passwort via AWS Secrets Manager | Sichere Credential-Verwaltung ohne Hardcoding im Terraform-Code implementiert | 11.06.2025 |
Nextcloud#13 |
Dedizierte RDS Security Group, Zugriff nur von EKS-Cluster auf Port 5432 | Netzwerk-Segmentierung zwischen EKS und RDS erfolgreich isoliert | 11.06.2025 |
Nextcloud#39 |
Kubernetes Secret mit base64-codierten DB-Credentials manuell erstellt | Bridge zwischen AWS Secrets Manager und K8s Secrets - manuelle Synchronisation nötig | 11.06.2025 |
| Ungeplant | EKS Worker Node Launch Template mit IMDS Hop Limit 2, gehärtete IRSA Trust Policy | 🔥 PVC Pending-Status führte zu tiefgreifender Infrastruktur-Debugging-Session | 11.06.2025 |
Nextcloud#14 |
Funktionale Nextcloud via manuelle YAML-Manifeste, AWS Load Balancer Integration | Pod-Neustart-Test bestätigte Datenpersistenz und DB-Anbindung - kritischer Meilenstein! | 11.06.2025 |
Nextcloud#15 |
Vollständige Spezifikation des manuellen Deployments in README dokumentiert | Detaillierte Blaupause für Sprint 4 Helm-Automatisierung geschaffen | 11.06.2025 |
| Tabelle: Sprint 3 - User Stories |
| Komponente | Deliverable | Wichtigste Features | Nachweis |
|---|---|---|---|
| RDS Database | Produktionsreife PostgreSQL-Instanz | v16.2, private Subnetze, Secrets Manager Integration, Backup-Retention | AWS RDS Console, Terraform State |
| Database Security | Isolierte Netzwerk-Architektur | Dedizierte Security Group, nur EKS-Zugriff, Port 5432 exklusiv | VPC Security Groups, Connection Test |
| K8s Credentials | Sichere Secret-Verwaltung | base64-codierte DB-Credentials in Kubernetes Secret | kubectl get secret nextcloud-db-secret -o yaml |
| EKS Hardening | Robuste Worker Node Config | Launch Template mit IMDS Hop Limit 2, gehärtete IRSA Trust Policy | Erfolgreiche PVC-Provisionierung |
| Nextcloud PoC | Funktionale Anwendung | Manuelle YAML-Manifeste, Load Balancer, persistente Datenbankanbindung | Live-Demo mit Pod-Neustart-Test |
| Deployment Spec | Automatisierungs-Blaupause | Vollständige Dokumentation aller Schritte, Konfigurationen und Manifeste | README Kapitel 4.1.8 |
| Tabelle: Sprint 3 - Inkremente |
Bild: Sprint 3 - Provisionierte RDS PostgreSQL-Instanz in privaten Subnetzen mit Secrets Manager Integration
Bild: Sprint 3 - Funktionale Nextcloud-Instanz über AWS Load Balancer mit persistenter Datenbankanbindung
Bild: Sprint 3 - Systematische Fehleranalyse: Von Pending PVC über CSI-Logs bis IMDS-Konfiguration
Bild: Sprint 3 - Live-Demo: Pod-Neustart mit bestätigter Datenpersistenz und Datenbankintegrität
Hauptimpediment: PVC bleibt im Pending-Status - komplexe Fehlersuche erforderlich
Auswirkung: Zweitägiger Debugging-Marathon durch alle Infrastruktur-Ebenen
Ergebnis: Robuste EKS-Konfiguration und systematische Problemlösungskompetenz
Lösungsschritte
- 🔍 Problem 1: IMDS Hop Limit zu niedrig für Container → Launch Template mit Hop Limit 2
- 🛡️ Problem 2: IRSA Trust Policy zu schwach → Gehärtete Policy mit
audundsubValidierung - 📋 Methodik: Schichtweise Analyse (Pod → PVC → CSI → IAM → EC2) als Best Practice etabliert
Demo-Highlights: Spektakuläre Live-Demo der kompletten End-to-End-Funktionalität - vom Terraform Apply über
Nextcloud-Login bis zum Pod-Neustart-Persistenz-Test
Stakeholder-Feedback: Beeindruckt von Stabilität und Resilienz, gesamte Infrastruktur als validiert betrachtet,
technische Tiefe gewürdigt
Sprint-Ziel Status: ✅ Vollständig erreicht (5/5 geplante + 1 ungeplante User Story abgeschlossen)
Nächste Schritte: Sprint 4 Helm-Automatisierung kann auf validierter Spezifikation aufbauen
| 😊 Was lief gut | 😕 Was lief schlecht | 💡 Lessons Learned | ⚡ Action Items |
|---|---|---|---|
| Systematische Fehlersuche methodisch durchgeführt | Komplexität von Cloud-Integrationen unterschätzt | IMDS Hop Limits sind kritisch für Container | Validierte Spezifikation als Helm-Basis nutzen |
| Resilienz bei komplexen Problemen bewiesen | Subtile Abhängigkeiten nicht in Standard-Docs | Proof-of-Concept deckt Infrastruktur-Fehler auf | Best-Practice-Guides vor Implementation studieren |
| Inkrementeller Wert durch PoC-Ansatz | Dokumentation der Impediments verzögert | Schichtweise Debugging ist der Schlüssel | GitHub Issues für bekannte Probleme recherchieren |
| Sprint-Ziel trotz Herausforderungen erreicht | IRSA Trust Policy Komplexität übersehen | Manuelle Validierung vor Automatisierung essentiell | Impediments sofort nach Lösung dokumentieren |
| Tabelle: Sprint 3 - Retro |
Dauer: 15. Juni - 20. Juni 2025 (Erledigt 22. Juni 2025)
Zugehöriges Epic: EPIC-HELM
Sprint Planning: 14.06.2025 (simuliert)
Nach der erfolgreichen Validierung der Infrastruktur in Sprint 3 war es Zeit, den manuellen, fehleranfälligen Deployment-Prozess zu industrialisieren. Dieser Sprint transformierte die validierten YAML-Manifeste in ein standardisiertes, wiederverwendbares Helm Chart - den ersten Schritt zur vollständigen Automatisierung.
"Ein eigenständiges und funktionales Helm Chart für Nextcloud ist entwickelt, das die manuelle Bereitstellung
vollständig ersetzt. Das Chart ist über eine values.yaml-Datei konfigurierbar, löst das localhost-Redirect-Problem
durch eine dedizierte ConfigMap und enthält einen einfachen Helm-Test zur Überprüfung der Erreichbarkeit des
Deployments. Die Benutzerfreundlichkeit wird durch eine informative NOTES.txt-Datei nach der Installation
sichergestellt."
| User Story | Was wurde umgesetzt | Interessante Erkenntnisse/Herausforderungen | Abgeschlossen |
|---|---|---|---|
Nextcloud#16 |
Helm Chart Grundgerüst mit helm create, Chart.yaml Metadaten, saubere Template-Basis |
Redundante Ressourcennamen (nextcloud-nextcloud-chart) durch suboptimale _helpers.tpl - schnell behoben |
22.06.2025 |
Nextcloud#40 |
Validierte Manifeste aus Sprint 3 in parametrisierte Helm-Templates überführt | Implizit durch #16 erledigt - Ticket-Überlappung im Sprint Planning übersehen | 22.06.2025 |
Nextcloud#17 |
Secret & ConfigMap Templates, dynamische trusted_domains für localhost-Fix | ConfigMap mit autoconfig.php löst kritisches Redirect-Problem elegant | 22.06.2025 |
Nextcloud#19 |
Helm-Test mit wget-basierter /status.php Connectivity-Prüfung | Test-Pod mit helm.sh/hook: test Annotation erfolgreich implementiert |
22.06.2025 |
Nextcloud#18 |
Dynamische NOTES.txt mit service-type-spezifischen Anweisungen | UX-Fokus: Benutzer bekommen sofort nächste Schritte nach Installation | 22.06.2025 |
| Tabelle: Sprint 4 - User Stories |
| Komponente | Deliverable | Wichtigste Features | Nachweis |
|---|---|---|---|
| Helm Chart Struktur | Vollständiges Chart-Package | charts/nextcloud-chart/, Chart.yaml, values.yaml, _helpers.tpl | helm lint & helm template erfolgreich |
| Template System | Parametrisierte K8s-Manifeste | Deployment, Service, PVC als konfigurierbare Templates | helm template . --set image.tag=28 |
| Configuration Management | Secret & ConfigMap Automation | Optional Secret generation, autoconfig.php für trusted_domains | LoadBalancer hostname dynamisch konfigurierbar |
| User Experience | Post-Installation Guidance | Service-type-spezifische NOTES.txt, Admin-Credential Anweisungen | helm install --dry-run Demo |
| Quality Assurance | Automatisierte Tests | Helm-Test für /status.php Connectivity-Check | helm test nextcloud → Succeeded |
| Documentation | Chart-Dokumentation | README Kapitel 4.2.x, values.yaml Kommentare, Sicherheitshinweise | Vollständige Nutzungsanleitung |
| Tabelle: Sprint 4 - Inkremente |
Bild: Sprint 4 - Vollständige Helm Chart Verzeichnisstruktur mit Templates, Tests und Konfiguration
Bild: Sprint 4 - Live-Demo der parametrisierten Manifest-Generierung mit verschiedenen values.yaml Konfigurationen
Bild: Sprint 4 - Benutzerfreundliche Post-Installation Anweisungen je nach Service-Type Konfiguration
Bild: Sprint 4 - Erfolgreicher Helm-Test mit /status.php Connectivity-Prüfung im EKS-Cluster
Hauptimpediment: Chicken-and-Egg-Problem mit LoadBalancer Hostname
Auswirkung: Chart muss installiert werden um Hostname zu erhalten, dann Upgrade für Konfiguration
Ergebnis: Zweistufiger Prozess als Standard etabliert, Automation für Sprint 5 geplant
Lösungsschritte
- 🔧 Naming-Fix: _helpers.tpl Template durch Standard-Helm-Logik ersetzt
- 📋 Validationskreislauf:
helm lint→helm template→ Fix als Best Practice etabliert - 🎯 UX-Optimierung: NOTES.txt mit klaren upgrade-Anweisungen für Benutzer
Demo-Highlights: Kompletter Helm Chart Lebenszyklus live demonstriert - von helm install --dry-run über
ConfigMap-Rendering bis hin zum erfolgreichen Test-Execution
Stakeholder-Feedback: Massive Verbesserung gegenüber manuellen Manifesten, proaktive localhost-Lösung und
Test-Implementation als Qualitätszeichen gelobt
Sprint-Ziel Status: ✅ Vollständig erreicht (5/5 User Stories abgeschlossen)
Nächste Schritte: CI/CD-Pipeline in Sprint 5 kann auf robustes Chart aufbauen
| 😊 Was lief gut | 😕 Was lief schlecht | 💡 Lessons Learned | ⚡ Action Items |
|---|---|---|---|
| Validationskreislauf extrem effizient | Chicken-and-Egg LoadBalancer Problem | Sprint 3 Blaupause zahlt sich aus | Automatisierung des Upgrade-Schritts für CI/CD |
| UX-Fokus mit NOTES.txt und Kommentaren | Ticket-Überlappung im Sprint Planning | helm lint/template als Standard-Workflow | Wiederverwendung der Parameterlogik |
| Blaupause aus Sprint 3 beschleunigte Entwicklung | Implizite Abhängigkeiten zwischen Tickets | User Experience ist kein Nice-to-Have | Bessere Ticket-Granularität in Zukunft |
| Sofortige Fehlererkennung verhinderte Tech Debt | Zweistufiger Install-Prozess unvermeidbar | Helm Charts sind der Industriestandard | CI/CD Pipeline für automatisches Upgrade |
| Tabelle: Sprint 4 - Retro |
Dauer: 21. Juni - 03. Juli 2025 (Erledigt 02. Juli 2025)
Zugehöriges Epic: EPIC-CICD, EPIC-ABSCHLUSS (Testing)
Sprint Planning: 20.06.2025 (simuliert)
Der Höhepunkt des Projekts: Nach vier Sprints der Infrastruktur- und Anwendungsentwicklung war es Zeit für die ultimative Automatisierung. Dieser Sprint transformierte den manuellen Deployment-Prozess in eine vollautomatisierte, sichere CI/CD-Pipeline - das letzte Puzzlestück für echte End-to-End-Automatisierung.
"Eine sichere und voll-automatisierte CI/CD-Pipeline ist etabliert. Sie wird bei einem Push auf den main-Branch
getriggert, authentifiziert sich sicher via OIDC bei AWS, installiert oder aktualisiert das Nextcloud Helm Chart im
EKS-Cluster, löst das 'Load Balancer Hostname'-Problem automatisiert und verifiziert das erfolgreiche Deployment durch
die Ausführung der Helm-Tests."
| User Story | Was wurde umgesetzt | Interessante Erkenntnisse/Herausforderungen | Abgeschlossen |
|---|---|---|---|
Nextcloud#20 |
IAM OIDC Provider & dedizierte Rolle für GitHub Actions, granulare Least-Privilege Policy | Dynamischer Cluster-Name führte zu robusterer Lösung via Terraform Remote State | 02.07.2025 |
Nextcloud#21 |
Vollständiger GitHub Actions Workflow, automatisches LoadBalancer-Hostname-Handling | Chicken-and-Egg Problem elegant mit Warteschleife und automatischem Upgrade gelöst | 02.07.2025 |
Nextcloud#23 |
Pipeline Status Badge im README mit Live-Status Anzeige | Einfache aber effektive Transparenz-Verbesserung für Stakeholder | 02.07.2025 |
| De-Scoped | Terraform Plan/Apply in CI/CD bewusst ausgeschlossen | Fokus auf Application Deployment - Infrastruktur-Automation bleibt im Backlog | - |
| Tabelle: Sprint 5 - User Stories |
| Komponente | Deliverable | Wichtigste Features | Nachweis |
|---|---|---|---|
| OIDC Authentication | Sichere GitHub-zu-AWS Integration | IAM OIDC Provider, Repository-spezifische Trust Policy, Least-Privilege Berechtigungen | Test-Workflow erfolgreich |
| CI/CD Pipeline | Vollautomatisierte Deployment-Pipeline | Push-triggered, helm upgrade --install, automatische Tests, LoadBalancer-Handling |
.github/workflows/deploy.yml |
| LoadBalancer Automation | Dynamische Hostname-Konfiguration | Warteschleife + automatisches helm upgrade mit korrektem nextcloud.host |
Workflow-Logs |
| Quality Gates | Integrierte Test-Automation | helm lint + helm test als Pipeline-Schritte, Failure-on-Error |
Pipeline-Status |
| Transparency | Live Pipeline Status | GitHub Actions Badge mit "passing" Status im README | Repository Hauptseite |
| Security | Passwortlose AWS-Integration | OIDC statt langlebige Keys, GitHub Secrets für sensitive Daten | IAM Role Trust Policy |
| Tabelle: Sprint 5 - Inkremente |
Bild: Sprint 5 - IAM OIDC Provider und GitHub Actions Rolle mit granularen Berechtigungen
Bild: Sprint 5 - Live GitHub Actions Workflow mit automatischem Deployment und Test-Ausführung
Bild: Sprint 5 - Automatische LoadBalancer-Hostname-Abfrage und dynamisches Helm-Upgrade
Bild: Sprint 5 - Grünes "passing" Status-Badge auf der Repository-Hauptseite
Hauptimpediment: Dynamischer vs. statischer Cluster-Name für CI/CD
Auswirkung: Pipeline muss flexibel auf verschiedene Cluster-Namen reagieren können
Ergebnis: Robustere Lösung durch Terraform Remote State Abfrage implementiert
Lösungsschritte
- 🔍 Annahme hinterfragt: Statischer Cluster-Name als Betriebseinschränkung erkannt
- 📋 Robuste Lösung: Remote State Parsing für dynamische Cluster-Namen
- 🎯 Iterative Verbesserung: Plan angepasst ohne Ziel aus Augen zu verlieren
Demo-Highlights: 🎯 PROJEKT-HÖHEPUNKT: Vollständige End-to-End-Automation live demonstriert - Code-Push →
automatisches Deployment → erfolgreiches Testing → grünes Status-Badge
Stakeholder-Feedback: Beeindruckt von nahtloser Automatisierung, elegante LoadBalancer-Lösung als besonders
professionell hervorgehoben
Sprint-Ziel Status: ✅ Vollständig erreicht (3/3 User Stories abgeschlossen)
Nächste Schritte: Sprint 6 fokussiert auf Dokumentations-Finalisierung
| 😊 Was lief gut | 😕 Was lief schlecht | 💡 Lessons Learned | ⚡ Action Items |
|---|---|---|---|
| Iterative Problemlösung bei dynamischen Clustern | Annahmen zu spät hinterfragen | Solide Basis aus Sprints 1-4 war entscheidend | Fokus auf saubere Dokumentation |
| OIDC-First Sicherheitsansatz ausgezahlt | Workflow-Komplexität durch Shell-Skripte | Adaptivität wichtiger als starrer Plan | Installations-Anleitung für Experten |
| Auf vorheriger Arbeit erfolgreich aufgebaut | Betriebskosten-Anforderungen zu spät bedacht | End-to-End Tests sind unverzichtbar | README finale Überprüfung |
| Komplettes Projektziel erreicht | LoadBalancer-Skript relativ komplex | Non-funktionale Requirements früh berücksichtigen | GitHub-Secrets Konfigurationsanleitung |
| Tabelle: Sprint 5 - Retro |
Dauer: 04. Juli - 09. Juli 2025 (Erledigt 02. Juli 2025)
Zugehöriges Epic: EPIC-ABSCHLUSS, EPIC-CICD
Sprint Planning: 03.07.2025 (simuliert)
Der ambitionierteste Sprint des Projekts: Über die reine CI/CD-Pipeline hinaus sollte der komplette Infrastruktur-Lebenszyklus automatisiert werden. Das Ziel war ein "One-Click"-Ansatz für die gesamte Umgebung - von der Erstellung bis zur sicheren Zerstörung aller AWS-Ressourcen.
"Das Projekt wird mit der Implementierung von zwei neuen, manuell triggerbaren GitHub Actions Workflows abgeschlossen: Ein 'Full Setup'-Workflow, der die gesamte AWS-Infrastruktur mit Terraform provisioniert und anschliessend die Nextcloud-Anwendung deployt, sowie ein 'Full Teardown'-Workflow, der die Anwendung sauber deinstalliert und danach die gesamte Infrastruktur wieder zerstört. Die finale Projektdokumentation, inklusive der neuen Workflows, der Systemarchitektur und einer umfassenden Reflexion, wird fertiggestellt."
| User Story | Was wurde umgesetzt | Interessante Erkenntnisse/Herausforderungen | Abgeschlossen |
|---|---|---|---|
Nextcloud#41 |
NEU: Full Setup Workflow mit terraform apply + deploy, wiederverwendbarer App-Workflow | IAM-Policy für terraform destroy-Berechtigungen musste erweitert werden | 02.07.2025 |
Nextcloud#42 |
NEU: Full Teardown Workflow mit helm uninstall + terraform destroy | Fehlertoleranzen für bereits entfernte Releases, sleep für saubere AWS-Abhängigkeiten | 02.07.2025 |
Nextcloud#28 |
Umfassende Installations-Anleitung mit Fokus auf neuen Lifecycle-Workflows | One-Click Setup als benutzerfreundlichster Ansatz dokumentiert | 02.07.2025 |
Nextcloud#26 |
Mermaid-basierte Architekturdiagramme direkt in README eingebettet | End-to-End und AWS-Netzwerk-Diagramme für vollständige Transparenz | 02.07.2025 |
Nextcloud#31 |
Terraform fmt, umfassende Code-Kommentierung, Workflow-Dokumentation | Obsoletes /kubernetes-manifests Verzeichnis entfernt - technische Schulden abgebaut | 02.07.2025 |
Nextcloud#32 |
Vollständiges Reflexionskapitel mit Theorie-Praxis-Abgleich | Kritische Bewertung der Lösung und konkrete Weiterentwicklungsempfehlungen | 02.07.2025 |
| Tabelle: Sprint 6 - User Stories |
| Komponente | Deliverable | Wichtigste Features | Nachweis |
|---|---|---|---|
| Lifecycle Automation | One-Click Setup/Teardown | Manual trigger via GitHub UI, terraform + helm Orchestrierung | .github/workflows/lifecycle.yml |
| Workflow Architecture | Wiederverwendbare Pipeline-Komponenten | Refactored deploy workflow, keine Code-Duplizierung | reusable-deploy-app.yml |
| Infrastructure Management | Vollständige AWS-Kontrolle | Auto-approve terraform apply/destroy, dynamische Ressourcen-Übergabe | IAM Policy erweitert |
| Documentation Suite | Produktionsreife Anleitung | Schritt-für-Schritt Setup, GitHub Secrets Konfiguration | README Kapitel 4.4 |
| Architecture Visualization | Eingebettete Diagramme | Mermaid End-to-End + AWS Network Diagramme | README Kapitel 3.3.x |
| Project Reflection | Comprehensive Analysis | Theorie-Praxis-Abgleich, Stärken/Schwächen, Weiterentwicklung | README Kapitel 7 |
| Tabelle: Sprint 6 - Inkremente |
Bild: Sprint 6 - GitHub Actions Manual Trigger mit Setup/Destroy Choice-Parameter
Bild: Sprint 6 - Komplette Umgebungs-Provisionierung: Terraform Apply → App Deployment
Bild: Sprint 6 - Saubere Umgebungs-Zerstörung: Helm Uninstall → Terraform Destroy
Bild: Sprint 6 - Eingebettete Mermaid-Diagramme für End-to-End und AWS-Netzwerk-Architektur
Hauptimpediment: IAM-Policy zu restriktiv für terraform destroy
Auswirkung: Terraform konnte erstellte Ressourcen nicht wieder löschen
Ergebnis: Erweiterte aber projektspezifische Berechtigungen für vollständigen Lifecycle
Lösungsschritte
- 🔐 Policy erweitert:
ec2:*,rds:*, etc. für terraform destroy-Operationen - 🧹 Clean Teardown: Sleep-Befehle für saubere AWS-Abhängigkeitsauflösung
- 🛡️ Fehlertoleranz: Workflow schlägt nicht bei bereits entfernten Releases fehl
Demo-Highlights: 🚀 TECHNISCHER ABSCHLUSS: One-Click Setup/Teardown live demonstriert - komplette AWS-Umgebung
auf Knopfdruck erstellt und wieder entfernt
Stakeholder-Feedback: Alle technischen Anforderungen erfüllt, aber grosse Architektur-Änderungen erfordern finale
Validierung vor Abgabe
Sprint-Ziel Status: ✅ Vollständig erreicht (6/6 User Stories abgeschlossen)
Nächste Schritte: 📋 ENTSCHEIDUNG: Zusätzlicher Hardening-Sprint für umfassende End-to-End-Tests
| 😊 Was lief gut | 😕 Was lief schlecht | 💡 Lessons Learned | ⚡ Action Items |
|---|---|---|---|
| One-Click Vision vollständig umgesetzt | Grosse Architektur-Änderungen in letztem Sprint | Lifecycle-Management ist der ultimative IaC-Test | Vollständiger Regressionstest erforderlich |
| Wiederverwendbare Workflow-Architektur | Push-to-Main Tests reichen nicht mehr aus | Refactoring verhindert Code-Duplizierung | Finale Präsentationsunterlagen erstellen |
| Umfassende Dokumentation fertiggestellt | IAM-Berechtigungen unterschätzt | Technische Schulden konsequent abgebaut | Feature-complete Produkt stabilisieren |
| Reflexion mit Theorie-Praxis-Abgleich | Validierungsaufwand nach grossen Änderungen | Documentation-First zahlt sich aus | End-to-End Vertrauen durch Tests wiederherstellen |
| Tabelle: Sprint 6 - Retro |
Zur systematischen Bewertung und Priorisierung der Projektrisiken wird eine visuelle Risikomatrix verwendet. Sie ordnet die Risiken nach ihrer Eintrittswahrscheinlichkeit und ihrer potenziellen Auswirkung ein.
| Auswirkung (A) | |||
|---|---|---|---|
| 1 (Gering) | 2 (Moderat) | ||
| Wahrscheinlichkeit (W) | 3 (Hoch) | R4 | |
| 2 (Mittel) | R3 | ||
| 1 (Niedrig) | R6 | ||
| Tabelle: Risikomatrix |
Das nachfolgende Risikoregister dokumentiert die Details zu jedem identifizierten Risiko:
| ID | Risiko | W (1-3) | A (1-3) | RW | Risiko-Level | Gegenmassnahmen | Status |
|---|---|---|---|---|---|---|---|
| R1 | Technische Komplexität der Integration | 3 | 3 | 9 | Hoch | Iteratives Vorgehen, Fokus auf Kernfunktionalität, Managed Services | Offen |
| R2 | Zeitlicher Aufwand für 50h sehr ambitioniert | 3 | 3 | 9 | Hoch | Striktes Scope-Management, realistische Aufwandsschätzung | Offen |
| R4 | Debugging-Aufwand (Terraform, Helm, CI/CD) | 3 | 2 | 6 | Hoch | Inkrementelles Testen, systematisches Logging | Offen |
| R5 | Komplexität des Secrets Managements | 2 | 3 | 6 | Hoch | GitHub Actions OIDC, Kubernetes Secrets, Least Privilege | Offen |
| R3 | Cloud-Kosten (AWS Managed Services) | 2 | 2 | 4 | Mittel | AWS Budget mit $10 Limit + E-Mail-Alerts, kleinste Instanzen | Mitigiert |
| R6 | Tool-Versionskonflikte | 1 | 2 | 2 | Niedrig | Dokumentierte Versionsanforderungen, Version Manager | Mitigiert |
| Tabelle: Risikoregister |
Risiken werden kontinuierlich überwacht und bei Bedarf aktualisiert.
| Rolle | Person | Verantwortlichkeiten |
|---|---|---|
| Projektdurchführung | Nenad Stevic | Technische Umsetzung, Dokumentation, Termineinhaltung |
| Experte Projektmanagement | Corrado Parisi (TBZ) | Methodische Begleitung, Projektstruktur-Feedback |
| Experte Fachbereich (IaC) | Armin Dörzbach (TBZ) | Technische Beratung, Code-Review, fachliche Bewertung |
| Tabelle: Projekt-Team |
Primärer Kanal: MS Teams (dedizierter Projekt-Channel)
Regelmässige Termine:
- Einzelbesprechungen gemäss TBZ-Ablaufplan für formelles Feedback
- Proaktive Kontaktaufnahme bei technischen Hindernissen oder Scope-Änderungen
Transparenz: Aktueller Projektstand jederzeit über GitHub Repository einsehbar
Wichtige Entscheidungen oder Scope-Änderungen werden mit beiden Experten abgestimmt und dokumentiert.
Bevor die erste Zeile Code geschrieben wird, lohnt sich ein strategischer Blick nach vorn. Diese SWOT-Analyse dient als Landkarte für das, was ich erwarte: Wo liegen die Stärken meines Plans, wo die absehbaren Hürden und welche Chancen und Risiken bringt das Umfeld mit sich?
| Mein grösster Vorteil | Der erwartete Knackpunkt | |
|---|---|---|
| Was ich kontrolliere | Stärke: Einsatz von modernen Industriestandards Mein Plan, auf top-aktuelle Tools wie Terraform, Kubernetes (EKS) und Helm zu setzen, ist die grösste Stärke. Das sichert nicht nur ein robustes Ergebnis, sondern auch maximale Relevanz. |
Schwäche: Technische Komplexität als Einzelkämpfer Die grösste Herausforderung wird die Komplexität sein. All diese mächtigen Tools fehlerfrei zu integrieren, ist als Einzelperson ohne direktes Team-Feedback eine enorme Aufgabe. |
| Was von aussen kommt | Chance: Hohe Relevanz für die Praxis Der Hauptgrund für dieses Projekt ist die hohe Nachfrage nach DevOps- und Cloud-Fähigkeiten. Ein erfolgreicher Abschluss ist nicht nur ein Schulprojekt, sondern ein wertvoller, praktischer Fähigkeitsnachweis. |
Gefahr: Unkontrollierbare Cloud-Kosten Das grösste externe Risiko sind definitiv die potenziellen AWS-Kosten. Ein Konfigurationsfehler oder ein unerwarteter Ressourcenverbrauch könnte teuer werden. Daher plane ich von Anfang an, Budget-Alerts einzurichten. |
| Tabelle: SWOT-Analyse |
Diese Analyse zeigt, dass das Projekt auf einem starken technologischen Fundament steht, die grössten Herausforderungen aber in der Komplexitätsbeherrschung und der Prozessdisziplin eines Einzelprojekts liegen.
In diesem Kapitel begründe ich meine Technologie-Wahl und erkläre die theoretischen Konzepte dahinter.
Die Technologie-Auswahl erfolgte systematisch basierend auf Projektanforderungen und Industriestandards. Ziel war eine moderne, wartbare Cloud-native Lösung.
[DIAGRAM PLACEHOLDER: Projekt-Architektur Overview]
Zeigt: AWS Cloud → EKS Cluster → Nextcloud Application mit CI/CD Pipeline
| Kriterium | AWS | Azure | Entscheidung | Begründung |
|---|---|---|---|---|
| Managed K8s Service | EKS (sehr ausgereift) | AKS (vergleichbar) | ✅ AWS | EKS bietet tiefere AWS-Integration (IAM, VPC, ALB). Aus privaten Projekten bereits bewährte Stabilität bekannt |
| Managed Database | RDS (umfangreich) | Azure Database | ✅ AWS | RDS PostgreSQL mit automatischen Backups, Read Replicas und Performance Insights. Nahtlose EKS-Integration |
| Vorhandene Kenntnisse | Ja | Begrenzt | ✅ AWS | Mehrjährige Erfahrung aus privaten Projekten mit EC2, S3, RDS. Reduziert Lernkurve erheblich |
| DSGVO-Compliance | eu-central-1 verfügbar | Ja | ✅ Beide | Frankfurt-Region erfüllt Schweizer Datenschutz-Anforderungen, AWS bietet transparente Compliance-Dokumentation |
| Community & Dokumentation | Sehr umfangreich | Gut | ✅ AWS | Grösste DevOps-Community, umfangreiche Terraform-Provider-Dokumentation, bewährte Best Practices verfügbar |
Tabelle: Cloud-Provider Vergleich
Gewählte Region: eu-central-1 (Frankfurt) - geringe Latenz zur Schweiz, DSGVO-konform
[SCREENSHOT PLACEHOLDER: AWS Console - EKS Cluster Overview]
Warum Kubernetes + EKS?
Vorteile von Managed EKS vs. Self-hosted:
- Reduzierter Management-Overhead: AWS übernimmt Control Plane (API-Server, etcd)
- Nahtlose AWS-Integration: IAM, VPC, Load Balancer, CloudWatch
- Fokus auf Anwendung: Mehr Zeit für Pipeline-Entwicklung statt Cluster-Administration
CKA-Kenntnisse nutzen: Bestehende Kubernetes-Zertifizierung optimal einsetzen
[DIAGRAM PLACEHOLDER: EKS Architecture]
Zeigt: AWS Control Plane + Worker Nodes + VPC Integration
Alternative betrachtet: Manuelles Setup (kubeadm)
- ❌ Zeitaufwand für HA, Backup, Upgrades zu hoch für 50h-Projekt
Manuelle Infrastruktur-Provisionierung über die AWS Console ist fehleranfällig, nicht reproduzierbar und schlecht dokumentierbar. Für ein professionelles DevOps-Projekt war ein Infrastructure-as-Code-Ansatz unerlässlich.
| Tool | Lesbarkeit | Cloud-Support | Lernaufwand | Entscheidung |
|---|---|---|---|---|
| Terraform | HCL-Syntax (sehr gut) | Multi-Cloud | Moderat | ✅ Gewählt |
| CloudFormation | JSON/YAML (umständlich) | AWS-only | Niedrig | ❌ |
| Tabelle: IAC-Tool Vergleich |
Warum Terraform überzeugte: Die HashiCorp Configuration Language (HCL) ist deutlich lesbarer als CloudFormation's
JSON-Syntax. Während "${aws_vpc.main.id}" in CloudFormation zu {"Ref": "MainVPC"} wird, bleibt Terraform-Code
intuitiv verständlich.
Das Killer-Feature: State Management. Terraform verwaltet den aktuellen Zustand der Infrastruktur in einer State-Datei, die für dieses Projekt in einem S3-Bucket mit DynamoDB-Locking ausgelagert wurde. Dies ermöglicht Drift Detection - Terraform erkennt manuelle Änderungen an der Infrastruktur und kann diese reparieren oder dokumentieren. CloudFormation bietet zwar ähnliche Funktionen, aber Terraform's State-Konzept ist ausgereifter und transparenter.
Zusätzlicher Vorteil: Die erlernten Terraform-Konzepte sind direkt auf andere Cloud-Provider übertragbar, was den Kompetenzerwerb nachhaltiger macht als AWS-spezifisches CloudFormation-Wissen.
[SCREENSHOT PLACEHOLDER: Terraform Plan Output]
Zeigt:terraform planmit geplanten Ressourcen-Änderungen
Kubernetes-YAML-Dateien sind statisch und schwer wiederverwendbar. Nextcloud benötigt verschiedene Konfigurationen für Development und Production, unterschiedliche Hostnamen und Image-Versionen. Copy-Paste von YAML-Dateien führt schnell zu Inkonsistenzen und Wartungsproblemen.
Darum: Helm behandelt Kubernetes-Manifeste als Templates und ermöglicht die Parametrisierung über eine zentrale
values.yaml. Dadurch wird {{ .Values.image.tag }} zur Laufzeit durch die gewünschte Version ersetzt, und
{{ .Values.nextcloud.host }} bestimmt den Hostnamen dynamisch.
| Merkmal | Helm | Kustomize | Begründung |
|---|---|---|---|
| Templating | Go-Templates (flexibel) | Patch-basiert | Helm ermöglicht komplexe Logik und Schleifen |
| Lifecycle | Install/Upgrade/Rollback | Nur Apply | Helm verwaltet Release-Historie komplett |
| Wiederverwendbarkeit | Charts + Values | Overlays | Charts sind echte Pakete, nicht nur Patches |
| Tabelle: Cluster-Config-Tool Vergleich |
Bewusst eigenes Chart entwickelt: Anstatt ein vorgefertigtes Nextcloud-Chart zu verwenden, wurde ein
projektspezifisches Chart erstellt. Dies ermöglichte massgeschneiderte Lösungen wie die trusted_domains ConfigMap, die
das bekannte Nextcloud-Problem mit dynamischen Hostnamen elegant löst. Zudem lerne ich was :)
[CODE SNIPPET PLACEHOLDER: values.yaml Struktur]
Zeigt: Konfigurable Parameter für Nextcloud Deployment
Das Auswahlkriterium war klar: Maximale Integration bei minimalem Wartungsaufwand. Da der Code bereits auf GitHub liegt, war die Pipeline-Wahl hauptsächlich eine Frage der Effizienz.
| Kriterium | GitHub Actions | Jenkins | GitLab CI | Gewichtung |
|---|---|---|---|---|
| Setup-Aufwand | Keine (in Repo) | Hoch (Server) | Mittel | 🔴 Kritisch |
| Authentifizierung | OIDC native | Manual | OIDC verfügbar | 🔴 Kritisch |
| Wartung | Serverless | Hoch | Mittel | 🟡 Wichtig |
| Flexibilität | Gut | Sehr hoch | Hoch | 🟢 Nice-to-have |
| Tabelle: CI/CD Tool Vergleich |
Der Game-Changer: OIDC-Authentifizierung. GitHub Actions bietet native OpenID Connect-Integration mit AWS. Das bedeutet: keine langlebigen Access Keys, keine Secrets in der Pipeline, sondern temporäre Token, die nur für die Dauer des Deployments gültig sind. Das ist nicht nur sicherer, sondern auch wartungsfreier.
Wiederverwendbare Workflows eliminierten Code-Duplizierung. Der reusable-deploy-app.yml Workflow wird sowohl vom
automatischen main-push als auch vom manuellen lifecycle Workflow aufgerufen - einmal schreiben, mehrfach nutzen.
[DIAGRAM PLACEHOLDER: CI/CD Pipeline Flow]
Zeigt: Git Push → GitHub Actions → AWS EKS Deployment
Ein Kubernetes-Projekt, das heute funktioniert, kann morgen fehlschlagen - z.B. wegen inkompatiblen Versionen der Tools.
Die kubectl-Version muss zur EKS-API-Version passen, Terraform-Provider entwickeln sich schnell weiter, und
Helm-Charts haben eigene Kompatibilitätsmatrix.
Die Lösung: Explizite Versionsfixierung auf allen Ebenen.
| Tool | Fixierte Version | Kritischer Punkt |
|---|---|---|
kubectl |
v1.28.x |
API-Kompatibilität mit EKS 1.28 |
terraform |
~> 1.5.0 |
AWS Provider Breaking Changes |
helm |
v3.12.x |
Chart API Stabilität |
| Tabelle: Versionen |
Implementierung erfolgte zweistufig: In terraform/versions.tf werden die Terraform- und AWS-Provider-Versionen
definiert, während die Client-Tools in der Projekt-Dokumentation spezifiziert sind. Das AWS-Provider-Constraint ~> 5.0
erlaubt Patch-Updates (5.0.1, 5.0.2), verhindert aber Major-Updates (6.0), die Breaking Changes einführen könnten.
[SCREENSHOT PLACEHOLDER: versions.tf File]
Zeigt: Terraform Provider Version Constraints
Die implementierte Lösung basiert auf bewährten Konzepten der modernen Cloud-Entwicklung.
Infrastructure as Code revolutioniert die Art, wie wir über Infrastruktur denken. Früher wurden Server "gepflegt" und " repariert" - heute werden sie "kompiliert" und "deployed". Der entscheidende Unterschied liegt im deklarativen Ansatz: Anstatt Terraform zu sagen "erstelle eine VPC, dann ein Subnetz, dann ein Gateway", beschreiben wir den gewünschten Endzustand.
Terraform wird zum Übersetzer zwischen unserem Wunsch und der Realität. Das Herzstück ist die .tfstate-Datei -
Terraforms Gedächtnis, das kontinuierlich "Was haben wir?" mit "Was wollen wir?" vergleicht und präzise Ausführungspläne
für die Differenz erstellt.
Versionierung verwandelt Infrastruktur in Software. Plötzlich werden Feature-Branches, Pull-Requests und Code-Reviews nicht nur für Anwendungscode, sondern auch für Netzwerke und Datenbanken möglich.
[DIAGRAM PLACEHOLDER: IaC Workflow - Declare → Plan → Apply → State Cycle]
Der Automatisierungsflow:
# GitHub Actions: main-push-deploy.yml
name: Deploy to EKS
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Lint Helm Chart
run: helm lint charts/nextcloud-chart/
- name: Deploy to EKS
run: helm upgrade --install nextcloud ./charts/nextcloud-chart
- name: Test Deployment
run: helm test nextcloudCode: GH Actions Workflow - Deploy
Environment-as-a-Service in Aktion:
# lifecycle.yml - Komplette Umgebung on-demand
- name: Terraform Apply
run: terraform apply -auto-approve
- name: Deploy Application
run: helm install nextcloud ./charts/nextcloud-chart
- name: Destroy Everything
if: github.event.inputs.action == 'destroy'
run: |
helm uninstall nextcloud
terraform destroy -auto-approveCode: GH Actions Workflow - Provision Infrastructure
Jeder git push auf main löst eine Kaskade aus: Validierung → Deployment → Testing → Live System. Kein manueller
Eingriff nötig.
[SCREENSHOT PLACEHOLDER: GitHub Actions Workflow Run]
Kubernetes ist komplex, aber für Nextcloud benötigen wir nur einige Schlüsselkomponenten:
| Komponente | Problem gelöst | Nextcloud-spezifisch |
|---|---|---|
| Deployment | Pod-Verfügbarkeit | Startet Nextcloud-Container neu bei Crash |
| Service | Stabile Netzwerk-Adresse | LoadBalancer für Internet-Zugang |
| PVC | Persistente Daten | User-Uploads überleben Pod-Restarts |
| ConfigMap | Dynamische Konfiguration | trusted_domains für Load Balancer URLs |
| Secret | Sichere Credentials | Datenbank-Passwörter base64-kodiert |
| Tabelle: Kubernetes Komponente für Nextcloud |
Das trusted_domains Problem:
Nextcloud verweigert standardmässig Zugriffe über unbekannte Hostnamen. In Kubernetes ändert sich aber der Hostname je nach Service-Konfiguration.
Lösung: ConfigMap injiziert die korrekten Domains zur Laufzeit.
Ein Chart, viele Möglichkeiten:
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
spec:
replicas: { { .Values.replicaCount } }
template:
spec:
containers:
- name: nextcloud
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
env:
- name: POSTGRES_HOST
value: { { .Values.database.host } }Code: Helm Chart - Deployment
Development vs Production:
# values-dev.yaml
replicaCount: 1
image:
tag: "27-apache"
database:
host: "localhost"
# values-prod.yaml
replicaCount: 3
image:
tag: "27-apache"
database:
host: "nextcloud-db.xyz.eu-central-1.rds.amazonaws.com"Code: Helm Chart - Deployment
Deployment-Kommandos:
# Development Environment
helm install nextcloud-dev ./charts/nextcloud-chart -f values-dev.yaml
# Production Environment
helm install nextcloud-prod ./charts/nextcloud-chart -f values-prod.yaml
# Update mit neuen Werten
helm upgrade nextcloud-prod ./charts/nextcloud-chart --set image.tag=28-apacheCode: Command Line - Configure Kubernetes
Release-Management:
$ helm list
NAME NAMESPACE REVISION STATUS CHART
nextcloud-dev default 1 deployed nextcloud-chart-0.1.0
nextcloud-prod default 3 deployed nextcloud-chart-0.1.0
$ helm rollback nextcloud-prod 2 # Zurück zur vorherigen VersionDie zentrale Herausforderung: Kubernetes ist für stateless Apps optimiert, Nextcloud ist stateful.
Nextcloud benötigt drei Arten von persistentem Zustand, die jeweils unterschiedlich gelöst werden:
Dateisystem-Persistierung: User-Uploads müssen Pod-Neustarts überleben. Ohne PersistentVolumeClaim würden alle Benutzerdateien beim nächsten Deployment verschwinden. Das AWS EBS Volume wird ausserhalb des Containers gemounted und übersteht alle Pod-Lebenszyklen.
Datenbank-Persistierung: Metadaten wie Benutzer, Freigaben und Dateiversionen sind weniger sichtbar, aber genauso kritisch. Die Entscheidung für AWS RDS anstatt einer In-Cluster-Datenbank trennt die Lebenszyklen von Anwendung und Daten - AWS übernimmt Backup, Patching und Failover.
Konfigurations-Persistierung: Die trusted_domains ConfigMap löst ein subtiles Problem. Nextcloud verweigert
standardmässig Zugriffe über unbekannte Hostnamen, aber in Kubernetes ändert sich der Hostname je nach
Service-Konfiguration.
| Zustand | Storage-Lösung | Lifecycle | Backup-Strategie |
|---|---|---|---|
| User-Dateien | AWS EBS (PVC) | Cluster-unabhängig | EBS Snapshots |
| App-Metadaten | AWS RDS | Cluster-unabhängig | RDS Automated Backups |
| Runtime-Config | ConfigMap | Cluster-abhängig | Git-Repository |
[DIAGRAM PLACEHOLDER: Stateful Architecture - Pod + EBS + RDS Separation]
Diese Architektur folgt dem Prinzip der Separation of Concerns: Jede Komponente hat eine klare Verantwortlichkeit, und die persistenten Elemente sind vom Kubernetes-Cluster-Lebenszyklus entkoppelt. Das Ergebnis ist eine robuste Anwendung, die sowohl die Flexibilität von Kubernetes als auch die Zuverlässigkeit von Managed Services nutzt.
Eine robuste Architektur ist das Fundament für eine erfolgreiche technische Lösung. Dieses Kapitel beschreibt das Gesamtsystem und seine Komponenten auf konzeptioneller Ebene.
Der End-to-End-Prozess von der Code-Änderung bis zum Endbenutzer-Zugriff folgt einem klaren, automatisierten Workflow:
[DIAGRAM PLACEHOLDER: Logische Gesamtarchitektur]
Zeigt: Developer → Git → GitHub Actions → AWS → EKS → User
Der Deployment-Flow in 7 Schritten:
| Schritt | Akteur | Aktion | Trigger |
|---|---|---|---|
| 1 | Developer | Code-Änderungen committen & pushen | Manuell |
| 2 | GitHub Actions | Pipeline automatisch auslösen | Git Push |
| 3 | CI/CD Pipeline | OIDC-Authentifizierung bei AWS IAM | Workflow Start |
| 4 | Terraform | Infrastruktur provisionieren (VPC, EKS, RDS) | lifecycle Workflow |
| 5 | Helm | Nextcloud-Anwendung deployen | Jeder Push |
| 6 | EKS Cluster | Nextcloud Image von Docker Hub pullen | Pod-Start |
| 7 | Load Balancer | Externen Zugriff für Browser ermöglichen | Service-Erstellung |
Kritische Datenflüsse:
- Nextcloud ↔ RDS: Metadaten über privates VPC-Netzwerk
- Nextcloud ↔ EBS: Benutzerdateien via PersistentVolumeClaims
- User ↔ Load Balancer: HTTPS-Traffic über öffentliches Internet
Der OIDC-Mechanismus eliminiert langlebige AWS-Credentials und sorgt für temporäre, sichere Authentifizierung während der Pipeline-Ausführung.
Netzwerk-Spezifikationen:
| Komponente | Konfiguration | Zweck |
|---|---|---|
| VPC CIDR | 10.0.0.0/16 |
Logisch isolierter Netzwerkbereich |
| Availability Zones | eu-central-1a, eu-central-1b |
Hochverfügbarkeit |
| Öffentliche Subnetze | /24 pro AZ |
Load Balancer, NAT Gateways |
| Private Subnetze | /24 pro AZ |
EKS Worker Nodes, RDS |
| NAT Gateways | 1 pro AZ | Ausgehende Internet-Verbindung |
Die Netzwerkarchitektur folgt dem Defense-in-Depth-Prinzip. Sicherheitskritische Ressourcen wie EKS Worker Nodes und die RDS-Datenbankinstanz operieren ausschliesslich in privaten Subnetzen ohne direkte Internet-Erreichbarkeit. Der Zugriff erfolgt ausschliesslich über den kontrollierten Load Balancer-Endpunkt.
[DIAGRAM PLACEHOLDER: AWS Netzwerkarchitektur - VPC mit Subnetz-Details]
Design-Entscheidung: Zwei NAT Gateways
Die Bereitstellung eines NAT Gateways pro Availability Zone ist eine bewusste Redundanz-Entscheidung. Ein einzelnes NAT Gateway wäre kostengünstiger, würde aber einen Single Point of Failure darstellen. Bei einem AZ-Ausfall könnten Worker Nodes in der anderen AZ keine ausgehenden Internet-Verbindungen mehr herstellen, was Updates und Image-Pulls unmöglich machen würde.
Routing-Strategie:
- Öffentliche Subnetze routen direkt über das Internet Gateway (IGW)
- Private Subnetze routen über das NAT Gateway ihrer jeweiligen AZ
- Cross-AZ-Traffic bleibt vollständig im AWS-Backbone
System-Verantwortlichkeiten nach Ebenen:
| Ebene | Komponente | Verantwortlichkeit | Datenfluss |
|---|---|---|---|
| Steuerung | GitHub + Actions | Source of Truth, Orchestrierung | Git-Commits → Pipeline-Trigger |
| Terraform | AWS-Ressourcen (VPC, EKS, RDS, IAM) | CLI ↔ AWS APIs | |
| Helm | Kubernetes-Ressourcen für Nextcloud | Client ↔ K8s API | |
| Infrastruktur | VPC | Sicheres Netzwerk-Fundament | HTTP/S Load Balancer → EKS |
| EKS | Kubernetes-Plattform | Docker Pull + App-Traffic | |
| RDS + EBS | Daten-Persistierung | Nextcloud Read/Write |
Schnittstellen-Design:
# Terraform → AWS
provider "aws" {
region = "eu-central-1"
}
# Helm → Kubernetes
provider "helm" {
kubernetes {
host = module.eks.cluster_endpoint
}
}
# Nextcloud → RDS
env:
- name: POSTGRES_HOST
value: "{{ .Values.database.host }}"Die Komponenten sind lose gekoppelt - jede Ebene kann unabhängig aktualisiert werden, ohne die anderen zu beeinträchtigen.
Das Problem: Standard-EKS-Konfigurationen führen zu subtilen Kompatibilitätsproblemen.
EKS Worker Nodes in privaten Subnetzen können standardmässig nicht auf den EC2 Instance Metadata Service (IMDS) zugreifen. Das ist problematisch, weil Systemkomponenten wie der EBS CSI Driver ihre eigene Availability Zone über IMDS ermitteln müssen, um EBS-Volumes korrekt zu mounten.
Die Lösung: Custom Launch Template
# terraform/launch_template.tf
resource "aws_launch_template" "eks_nodes" {
name_prefix = "eks-node-group-"
image_id = data.aws_ami.eks_worker.id
instance_type = "t3.medium"
metadata_options {
http_endpoint = "enabled"
http_tokens = "required"
http_put_response_hop_limit = 2 # Kritisch für EKS!
instance_metadata_tags = "disabled"
}
vpc_security_group_ids = [aws_security_group.eks_nodes.id]
tag_specifications {
resource_type = "instance"
tags = {
Name = "eks-worker-node"
}
}
}Warum hop_limit = 2?
Container in Kubernetes laufen in einer zusätzlichen Netzwerk-Schicht. Der Standard-Hop-Limit von 1 verhindert, dass Pods IMDS erreichen können. Mit Limit 2 können sowohl der Node als auch die darauf laufenden Pods auf Metadata zugreifen.
IAM Roles for Service Accounts (IRSA):
# EBS CSI Driver bekommt eigene AWS-Berechtigungen
apiVersion: v1
kind: ServiceAccount
metadata:
name: ebs-csi-controller-sa
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT:role/AmazonEKS_EBS_CSI_DriverRoleSicherheits-Architektur:
- Control Plane: Von AWS verwaltet, hochverfügbar
- Worker Nodes: Ausschliesslich in privaten Subnetzen
- Pod-to-AWS Communication: Via IRSA ohne Credentials auf Nodes
- External Access: Nur über kontrollierten Load Balancer
[DIAGRAM PLACEHOLDER: EKS Security Architecture - Control Plane + Worker Nodes + IRSA]
Diese Konfiguration löst nicht nur technische Probleme, sondern implementiert auch AWS Security Best Practices: Minimale Berechtigungen, keine langlebigen Credentials, und Defense in Depth durch Netzwerk-Segmentierung.
Die Umsetzung erfolgte in vier strategischen Phasen: Infrastruktur-Provisionierung, Anwendungs-Paketierung, Automatisierung und Konfigurationsoptimierung. Jede Phase löste spezifische technische Herausforderungen und baute auf den Erkenntnissen der vorherigen auf.
Die Herausforderung: Eine produktionsreife Kubernetes-Umgebung benötigt mehr als nur einen Cluster. Netzwerk-Segmentierung, Datenbank-Integration, Speicher-Management und Sicherheits-Konfigurationen müssen orchestriert werden.
Der Ansatz: Terraform ermöglicht deklarative Infrastruktur-Definition mit automatisiertem State-Management. Die Komponenten wurden in logischer Abhängigkeitsreihenfolge entwickelt: Netzwerk → Cluster → Speicher → Datenbank → Sicherheit.
Das Problem: Lokaler Terraform State verhindert Zusammenarbeit und Automatisierung.
| Ansatz | Lokaler State | Remote S3 Backend | Entscheidung |
|---|---|---|---|
| Kollaboration | Unmöglich | Multiple Entwickler | ✅ S3 Backend |
| CI/CD Integration | Nicht möglich | Nahtlos | ✅ S3 Backend |
| State Corruption | Risiko hoch | DynamoDB Locking | ✅ S3 Backend |
| Versionierung | Keine | S3 Versioning | ✅ S3 Backend |
Implementierung:
# backend/main.tf - Einmalige Backend-Infrastruktur
resource "aws_s3_bucket" "terraform_state" {
bucket = "nenad-stevic-nextcloud-tfstate"
lifecycle {
prevent_destroy = true
}
}
resource "aws_dynamodb_table" "terraform_locks" {
name = "nenad-stevic-nextcloud-tfstate-lock"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}Backend-Konfiguration in der Hauptanwendung:
# terraform/backend.tf
terraform {
backend "s3" {
bucket = "nenad-stevic-nextcloud-tfstate"
key = "nextcloud-app/main.tfstate"
region = "eu-central-1"
dynamodb_table = "nenad-stevic-nextcloud-tfstate-lock"
encrypt = true
}
}Tagging-Strategie für Kostenmanagement:
# terraform/locals.tf
locals {
common_tags = {
Projekt = "Nextcloud"
Student = "NenadStevic"
ManagedBy = "Terraform"
}
}
# terraform/provider.tf
provider "aws" {
region = var.aws_region
default_tags {
tags = local.common_tags
}
}Diese zentrale Tagging-Strategie ermöglicht präzise Kostenverfolgung im AWS Billing Dashboard.
Design-Entscheidung: Hochverfügbares Multi-AZ Setup
| Komponente | Konfiguration | Sicherheits-Impact |
|---|---|---|
| VPC CIDR | 10.0.0.0/16 |
Logische Isolation |
| Public Subnets | 2 AZs, /24 each |
Load Balancer, NAT Gateways |
| Private Subnets | 2 AZs, /24 each |
EKS Nodes, RDS (Internet-geschützt) |
| NAT Gateways | 1 pro AZ | Redundante Outbound-Konnektivität |
Kritische Routing-Entscheidung:
# terraform/network.tf - NAT Gateway pro AZ für Ausfallsicherheit
resource "aws_nat_gateway" "nat_gw_per_az" {
count = length(var.availability_zones)
allocation_id = aws_eip.nat_eip_per_az[count.index].id
subnet_id = aws_subnet.public[count.index].id
depends_on = [aws_internet_gateway.main_igw]
}
# Separate Route Table pro AZ
resource "aws_route_table" "private_rt_per_az" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat_gw_per_az[count.index].id
}
}Warum zwei NAT Gateways? Ein einzelnes Gateway wäre kostengünstiger, würde aber einen Single Point of Failure schaffen. Bei AZ-Ausfall könnten Pods keine Container-Images mehr pullen.
[DIAGRAM PLACEHOLDER: VPC Multi-AZ Architecture]
Zeigt: Public/Private Subnets pro AZ, NAT Gateway Redundanz
IAM-Rollen-Matrix:
| Rolle | Service | Attached Policies | Zweck |
|---|---|---|---|
eks-cluster-role |
eks.amazonaws.com |
AmazonEKSClusterPolicy |
Control Plane Management |
eks-node-role |
ec2.amazonaws.com |
AmazonEKSWorkerNodePolicyAmazonEC2ContainerRegistryReadOnlyAmazonEKS_CNI_Policy |
Worker Node Operations |
Das IMDS Problem und die Lösung:
Standard-EKS-Konfigurationen führen zu einem subtilen Problem: Pods können den EC2 Instance Metadata Service nicht erreichen, was den EBS CSI Driver funktionsunfähig macht.
# terraform/launch_template.tf - Lösung für IMDS-Zugriff
resource "aws_launch_template" "eks_nodes" {
name_prefix = "${lower(var.project_name)}-lt-"
metadata_options {
http_tokens = "required" # IMDSv2 enforcement
http_put_response_hop_limit = 2 # Pods können IMDS erreichen
}
lifecycle {
create_before_destroy = true
}
}
# EKS Node Group mit Custom Launch Template
resource "aws_eks_node_group" "main_nodes" {
cluster_name = aws_eks_cluster.main.name
node_group_name = "${var.project_name}-main-nodes"
node_role_arn = aws_iam_role.eks_node_role.arn
subnet_ids = aws_subnet.private[*].id # Sicherheit: Private Subnetze
launch_template {
id = aws_launch_template.eks_nodes.id
version = aws_launch_template.eks_nodes.latest_version
}
scaling_config {
desired_size = 2
max_size = 4
min_size = 1
}
}Cluster-Zugriff konfigurieren:
aws eks update-kubeconfig --region eu-central-1 --name nextcloud-eks-cluster
kubectl get nodes # ValidierungDas Authentifizierungs-Problem: Pods benötigen AWS-Berechtigungen ohne Access Keys im Cluster zu speichern.
OIDC-Integration:
# terraform/iam_irsa.tf
data "tls_certificate" "eks_oidc_thumbprint" {
url = aws_eks_cluster.main.identity[0].oidc[0].issuer
}
resource "aws_iam_openid_connect_provider" "eks_oidc_provider" {
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = [data.tls_certificate.eks_oidc_thumbprint.certificates[0].sha1_fingerprint]
url = aws_eks_cluster.main.identity[0].oidc[0].issuer
}EBS CSI Driver IAM-Rolle:
resource "aws_iam_role" "ebs_csi_driver_role" {
name = "${var.project_name}-ebs-csi-driver-role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Action = "sts:AssumeRoleWithWebIdentity",
Principal = {
Federated = aws_iam_openid_connect_provider.eks_oidc_provider.arn
},
Condition = {
StringEquals = {
"${replace(aws_iam_openid_connect_provider.eks_oidc_provider.url, "https://", "")}:aud" = "sts.amazonaws.com",
"${replace(aws_iam_openid_connect_provider.eks_oidc_provider.url, "https://", "")}:sub" = "system:serviceaccount:kube-system:ebs-csi-controller-sa"
}
}
}
]
})
}Trust Policy Debugging: Die ursprüngliche Implementation scheiterte mit AccessDenied. Die Lösung war eine
präzisere Condition-Syntax mit beiden aud und sub Validierung.
Entscheidung: EKS Add-on vs Helm Chart
| Kriterium | EKS Add-on | Helm Chart | Gewählt |
|---|---|---|---|
| AWS Integration | Nativ | Community | ✅ EKS Add-on |
| Version Compatibility | Garantiert | Manuell | ✅ EKS Add-on |
| Lifecycle Management | AWS verwaltet | Selbst verwaltet | ✅ EKS Add-on |
# terraform/eks_addons.tf
resource "aws_eks_addon" "ebs_csi_driver" {
cluster_name = aws_eks_cluster.main.name
addon_name = "aws-ebs-csi-driver"
service_account_role_arn = aws_iam_role.ebs_csi_driver_role.arn
resolve_conflicts_on_create = "OVERWRITE"
}Der EBS CSI Driver ist fundamentale Cluster-Infrastruktur, keine Anwendung. Die EKS Add-on-Methode folgt der Architektur-Trennung: Terraform für Infrastruktur, Helm für Anwendungen.
Sicherheits-Konfiguration:
# terraform/rds.tf
resource "aws_db_instance" "nextcloud" {
identifier = "${var.project_name}-db-instance"
engine = "postgres"
engine_version = "15.4"
instance_class = "db.t3.micro"
allocated_storage = 20
max_allocated_storage = 100 # Auto-scaling
storage_encrypted = true
db_name = "nextclouddb"
username = "nextcloudadmin"
password = data.aws_secretsmanager_secret_version.rds_master_password.secret_string
# Sicherheit: Nur private Subnetze
db_subnet_group_name = aws_db_subnet_group.main.name
vpc_security_group_ids = [aws_security_group.rds.id]
# Backup und Wartung
backup_retention_period = 7
backup_window = "03:00-04:00"
maintenance_window = "sun:04:00-sun:05:00"
multi_az = false # Kostenoptimierung für Demo
publicly_accessible = false # Kritisch: Keine Internet-Exposition
skip_final_snapshot = true # Nur für Demo-Umgebung
}Netzwerk-Isolation:
# terraform/security_groups.tf
resource "aws_security_group_rule" "eks_to_rds" {
type = "ingress"
from_port = 5432
to_port = 5432
protocol = "tcp"
security_group_id = aws_security_group.rds.id
source_security_group_id = aws_eks_cluster.main.vpc_config[0].cluster_security_group_id
}Diese Regel erlaubt PostgreSQL-Zugriff ausschliesslich von EKS-Pods - Least Privilege Prinzip umgesetzt.
Das Problem: Kubernetes YAML-Dateien sind statisch und umständlich zu verwalten. Unterschiedliche Umgebungen ( Dev/Prod) benötigen verschiedene Konfigurationen.
Die Lösung: Ein eigenes Helm Chart bietet vollständige Kontrolle über die Deployment-Logik und ermöglicht Parametrisierung.
charts/nextcloud-chart/
├── Chart.yaml # Metadaten
├── values.yaml # Standardkonfiguration
└── templates/
├── _helpers.tpl # Template-Funktionen
├── configmap.yaml # Nextcloud-Konfiguration
├── deployment.yaml # Hauptanwendung
├── pvc.yaml # Persistenter Speicher
├── secret.yaml # Credentials
└── service.yaml # Netzwerk-Exposition
Deployment mit Umgebungsvariablen:
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
spec:
replicas: { { .Values.replicaCount } }
template:
spec:
containers:
- name: nextcloud
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
env:
- name: POSTGRES_HOST
valueFrom:
secretKeyRef:
name: { { include "nextcloud-chart.secretName" . } }
key: POSTGRES_HOST
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: { { include "nextcloud-chart.secretName" . } }
key: POSTGRES_PASSWORD
volumeMounts:
- name: nextcloud-data
mountPath: /var/www/html
- name: config-volume
mountPath: /var/www/html/config/nextcloud-config.php
subPath: nextcloud-config.php
volumes:
- name: nextcloud-data
persistentVolumeClaim:
claimName: { { include "nextcloud-chart.fullname" . } }-data
- name: config-volume
configMap:
name: { { include "nextcloud-chart.fullname" . } }-configDas trusted_domains Problem:
Nextcloud verweigert standardmässig Zugriffe über unbekannte Hostnamen. In Kubernetes ist der Hostname aber dynamisch ( Load Balancer).
# templates/configmap.yaml - Lösung
apiVersion: v1
kind: ConfigMap
metadata:
name: { { include "nextcloud-chart.fullname" . } }-config
data:
nextcloud-config.php: |
<?php
$CONFIG = array (
'overwrite.cli.url' => 'http://{{ .Values.nextcloud.host }}',
'overwritehost' => '{{ .Values.nextcloud.host }}',
'trusted_domains' => array (
0 => 'localhost',
1 => '{{ .Values.nextcloud.host }}',
),
);Load Balancer Service:
# templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: { { include "nextcloud-chart.fullname" . } }
spec:
type: { { .Values.service.type } }
ports:
- port: { { .Values.service.port } }
targetPort: 80
protocol: TCP
selector:
{ { - include "nextcloud-chart.selectorLabels" . | nindent 4 } }values.yaml Struktur:
# Anwendungs-Konfiguration
replicaCount: 1
image:
repository: nextcloud
tag: "27-apache"
# Nextcloud-spezifische Einstellungen
nextcloud:
host: "" # Wird zur Laufzeit gesetzt
admin:
user: "admin"
password: "" # Via --set übergeben
# Datenbank-Konfiguration
database:
enabled: true
host: "" # RDS Endpoint
user: "nextcloudadmin"
password: "" # Via --set übergeben
database: "nextclouddb"
# Speicher-Konfiguration
persistence:
enabled: true
storageClass: "gp2"
size: 10Gi
# Service-Konfiguration
service:
type: LoadBalancer
port: 80Deployment-Kommandos:
# Installation
helm install nextcloud ./charts/nextcloud-chart \
--set database.host="nextcloud-db.region.rds.amazonaws.com" \
--set database.password="$RDS_PASSWORD" \
--set nextcloud.admin.password="$ADMIN_PASSWORD"
# Hostname-Update nach Load Balancer-Erstellung
helm upgrade nextcloud ./charts/nextcloud-chart \
--set nextcloud.host="a1b2c3d4.eu-central-1.elb.amazonaws.com"Die Vision: Code-Änderungen sollen automatisch validiert, deployed und getestet werden. Keine manuellen Schritte, keine langlebigen Credentials.
Workflow-Trigger und Jobs:
# .github/workflows/main-push-deploy.yml
name: Deploy Nextcloud Application
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write # OIDC-Token anfordern
contents: read # Repository lesen
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.CICD_ROLE_NAME }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Configure kubectl
run: |
aws eks update-kubeconfig --region ${{ secrets.AWS_REGION }} --name nextcloud-eks-cluster
- name: Lint Helm Chart
run: |
helm lint charts/nextcloud-chart/
- name: Deploy Application
run: |
helm upgrade --install nextcloud ./charts/nextcloud-chart \
--create-namespace \
--namespace nextcloud \
--set database.host="${{ secrets.RDS_ENDPOINT }}" \
--set database.password="${{ secrets.RDS_DB_PASSWORD }}" \
--set nextcloud.admin.password="${{ secrets.NEXTCLOUD_ADMIN_PASSWORD }}" \
--wait
- name: Get Load Balancer Hostname
run: |
echo "Waiting for Load Balancer..."
kubectl wait --for=condition=available --timeout=300s deployment/nextcloud -n nextcloud
LB_HOSTNAME=$(kubectl get svc nextcloud -n nextcloud -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
echo "Load Balancer: $LB_HOSTNAME"
helm upgrade nextcloud ./charts/nextcloud-chart \
--namespace nextcloud \
--set nextcloud.host="$LB_HOSTNAME"
- name: Test Deployment
run: |
helm test nextcloud --namespace nextcloudDas Sicherheitsproblem: Traditionelle CI/CD pipelines speichern AWS Access Keys als Secrets - ein Sicherheitsrisiko.
OIDC-Lösung:
# terraform/iam_cicd.tf
resource "aws_iam_openid_connect_provider" "github" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = [
"6938fd4d98bab03faadb97b34396831e3780aea1" # GitHub OIDC
]
}
resource "aws_iam_role" "cicd_role" {
name = "Nextcloud-cicd-role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Action = "sts:AssumeRoleWithWebIdentity",
Principal = {
Federated = aws_iam_openid_connect_provider.github.arn
},
Condition = {
StringLike = {
"token.actions.githubusercontent.com:sub" = "repo:Stevic-Nenad/Nextcloud:ref:refs/heads/main"
}
}
}
]
})
}Sicherheits-Vorteile:
- Keine langlebigen Credentials in GitHub Secrets
- Temporäre Token nur für spezifische Repository/Branch
- Automatische Token-Rotation durch AWS
Full Environment Management:
# .github/workflows/lifecycle.yml
name: Full Environment Lifecycle
on:
workflow_dispatch:
inputs:
action:
description: 'Action to perform'
required: true
default: 'setup'
type: choice
options:
- setup
- destroy
jobs:
terraform:
if: github.event.inputs.action == 'setup'
runs-on: ubuntu-latest
steps:
- name: Terraform Apply
run: |
cd terraform
terraform init
terraform apply -auto-approve
deploy:
if: github.event.inputs.action == 'setup'
needs: terraform
uses: ./.github/workflows/reusable-deploy-app.yml
destroy:
if: github.event.inputs.action == 'destroy'
runs-on: ubuntu-latest
steps:
- name: Destroy Application
run: |
helm uninstall nextcloud --namespace nextcloud
- name: Destroy Infrastructure
run: |
cd terraform
terraform destroy -auto-approveDieser Workflow ermöglicht komplette Umgebungen "on-demand" zu erstellen oder zu zerstören - Environment-as-a-Service.
Neben der Standard-Ressourcen-Provisionierung waren spezifische Anpassungen notwendig, um Kompatibilität und Sicherheit zu gewährleisten.
Das Problem: EBS CSI Driver kann Availability Zone nicht ermitteln.
Root Cause: Standard EKS-Nodes haben IMDS Hop Limit = 1, aber Container benötigen Hop Limit = 2.
Fehlersymptom:
Events:
Warning ProvisioningFailed persistentvolumeclaim/nextcloud-data
failed to provision volume with StorageClass "gp2": rpc error: code = Internal
desc = Could not create volume: UnauthorizedOperation: You are not authorized to perform this operation
Lösung - Custom Launch Template:
resource "aws_launch_template" "eks_nodes" {
metadata_options {
http_tokens = "required" # IMDSv2 erzwingen
http_put_response_hop_limit = 2 # Container können IMDS erreichen
}
}Das Problem: Nextcloud zeigt interne IPs in generierten URLs.
Symptom: Redirects führen zu internen Kubernetes Service-IPs statt externen Load Balancer-URLs.
Lösung - Dynamische Konfiguration:
# Via ConfigMap injiziert
<?php
$CONFIG = array (
'overwrite.cli.url' => 'http://a1b2c3d4.eu-central-1.elb.amazonaws.com',
'overwritehost' => 'a1b2c3d4.eu-central-1.elb.amazonaws.com',
'trusted_domains' => array (
0 => 'localhost',
1 => 'a1b2c3d4.eu-central-1.elb.amazonaws.com',
),
);Das Problem: Datenbank sollte nur von Nextcloud-Pods erreichbar sein.
Lösung - Präzise Security Group Rules:
resource "aws_security_group_rule" "eks_to_rds" {
type = "ingress"
from_port = 5432
to_port = 5432
protocol = "tcp"
security_group_id = aws_security_group.rds.id
source_security_group_id = aws_eks_cluster.main.vpc_config[0].cluster_security_group_id
}Sicherheits-Impact: Selbst mit VPC-Zugriff kann nur der EKS-Cluster die Datenbank erreichen. Alle anderen Services ( EC2, Lambda, etc.) werden blockiert.
Vollständiger Deployment-Prozess:
# 1. Infrastruktur erstellen
cd terraform
terraform init
terraform apply
# 2. Kubectl konfigurieren
aws eks update-kubeconfig --region eu-central-1 --name nextcloud-eks-cluster
# 3. Anwendung deployen
helm install nextcloud ./charts/nextcloud-chart \
--set database.host="$(terraform output -raw rds_endpoint)" \
--set database.password="$RDS_PASSWORD" \
--set nextcloud.admin.password="$ADMIN_PASSWORD"
# 4. Load Balancer URL ermitteln
kubectl get svc nextcloud -w
# 5. Hostname konfigurieren
helm upgrade nextcloud ./charts/nextcloud-chart \
--set nextcloud.host="$(kubectl get svc nextcloud -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')"
# 6. Funktionalität testen
helm test nextcloudValidierung der Persistenz:
# Pod löschen zum Test der Datenpersistenz
kubectl delete pod -l app.kubernetes.io/name=nextcloud-chart
# Neuer Pod sollte automatisch starten und Daten behalten
kubectl get pods -wEnvironment Cleanup:
# Anwendung entfernen
helm uninstall nextcloud
# Infrastruktur zerstören
terraform destroy -auto-approveDie Herausforderung: Eine fehlerhaft deployete Nextcloud-Instanz in der Cloud kostet Zeit und Geld. Jeder Fehler, der erst in der AWS-Umgebung entdeckt wird, verursacht einen teuren Debug-Zyklus.
Die Strategie: "Shift-Left" - Fehler so früh wie möglich fangen, bevor sie teuer werden.
Pipeline-integrierte Validierung:
| Stage | Tool | Was wird geprüft | Abbruch bei Fehler |
|---|---|---|---|
| Code-Qualität | helm lint |
Chart-Syntax, Best Practices | ✅ Sofort |
| Infrastruktur | terraform validate |
HCL-Syntax, Provider-Kompatibilität | ✅ Sofort |
| Template-Generierung | helm template |
Kubernetes-Manifest-Ausgabe | ✅ Sofort |
| Deployment-Validierung | kubectl wait |
Pod-Readiness, Service-Verfügbarkeit | ✅ Nach Timeout |
| Funktionalität | helm test |
HTTP-Endpunkt-Erreichbarkeit | ✅ Bei Fehlschlag |
Das Problem: Wie beweist man, dass Nextcloud wirklich läuft und nicht nur deployed ist?
Die Lösung: Ein eigener Test-Pod, der die Anwendung aus Cluster-Sicht validiert.
# templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "nextcloud-chart.fullname" . }}-test"
annotations:
"helm.sh/hook": test
"helm.sh/hook-weight": "1"
"helm.sh/hook-delete-policy": hook-succeeded
spec:
restartPolicy: Never
containers:
- name: wget
image: busybox
command: [ 'wget' ]
args: [ '--spider', '--timeout=10', 'http://{{ include "nextcloud-chart.fullname" . }}/status.php' ]Test-Ausführung:
# Deployment testen
helm test nextcloud
# Output:
NAME: nextcloud
LAST DEPLOYED: 2024-01-15T10:30:45Z
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: nextcloud-test
Last Started: 2024-01-15T10:31:00Z
Last Completed: 2024-01-15T10:31:05Z
Phase: SucceededValidierungsschritt in GitHub Actions:
# .github/workflows/main-push-deploy.yml
- name: Validate Infrastructure
run: |
cd terraform
terraform validate
terraform plan -detailed-exitcode
- name: Lint Helm Chart
run: |
helm lint charts/nextcloud-chart/
- name: Template Validation
run: |
helm template nextcloud charts/nextcloud-chart/ > /tmp/manifests.yaml
kubectl apply --dry-run=client -f /tmp/manifests.yaml
- name: Deploy and Test
run: |
helm upgrade --install nextcloud charts/nextcloud-chart/ --wait
helm test nextcloud --timeout 300sFehler-Eskalation: Jeder fehlgeschlagene Test bricht die Pipeline ab und verhindert fehlerhafte Deployments.
Kritische Funktionen, die automatisierte Tests nicht abdecken:
# 1. Testdatei hochladen
echo "Test-Content-$(date)" > testfile.txt
# Via Nextcloud UI hochladen
# 2. Pod-Neustart simulieren
kubectl delete pod -l app.kubernetes.io/name=nextcloud-chart
# 3. Neuer Pod sollte starten
kubectl get pods -w
# 4. Testdatei sollte noch existieren
# Via Nextcloud UI überprüfenWarum manuell? Datei-Upload-Tests benötigen Browser-Interaktion oder komplexe API-Aufrufe. Der Aufwand übersteigt den Nutzen für ein Proof-of-Concept.
Browser-Test:
- Load Balancer URL ermitteln:
kubectl get svc nextcloud - URL im Browser öffnen
- Login mit Admin-Credentials
- File-Upload/Download testen
Warum kritisch? Der Helm Test prüft nur cluster-interne Konnektivität. Externe Erreichbarkeit über den Load Balancer ist separater Failure-Mode.
Lifecycle-Workflow Validierung:
| Test-Szenario | Ziel | Dauer | Häufigkeit |
|---|---|---|---|
| Cold Setup | Komplette Umgebung aus nichts erstellen | ~20 Min | Nach Major-Änderungen |
| Hot Deployment | Anwendungs-Update auf bestehender Infra | ~5 Min | Bei jedem Push |
| Complete Teardown | Alle Ressourcen sauber entfernen | ~10 Min | Nach Tests |
Cold Setup Validierung:
# Workflow manuell triggern
gh workflow run lifecycle.yml -f action=setup
# Erfolgskriterien:
# ✅ Terraform Apply erfolgreich
# ✅ EKS Cluster erreichbar
# ✅ Nextcloud-Deployment läuft
# ✅ Load Balancer funktional
# ✅ Helm Test bestandenTeardown Validierung:
# Cleanup triggern
gh workflow run lifecycle.yml -f action=destroy
# Validierung:
aws ec2 describe-instances --filters "Name=tag:Projekt,Values=Nextcloud" # Keine Instanzen
aws rds describe-db-instances --filters "Name=tag:Projekt,Values=Nextcloud" # Keine DBs
aws elb describe-load-balancers # Keine Nextcloud Load BalancerKostenschutz: Complete Teardown verhindert vergessene, kostenfressende Ressourcen.
Gefundene kritische Issues:
| Problem | Entdeckt durch | Impact | Lösung |
|---|---|---|---|
| IMDS Hop Limit | Manueller PVC-Test | EBS Volumes funktionslos | Custom Launch Template |
| Trusted Domains | Browser-Test | Nextcloud-Redirects fehlerhaft | ConfigMap mit dynamischem Host |
| IRSA Trust Policy | helm test Fehlschlag |
EBS CSI Driver Access Denied | Präzisere Condition-Syntax |
Lessons Learned:
- Automatisierte Tests fangen Konfigurationsfehler früh
- Manuelle Tests decken UX-Probleme auf, die Scripts übersehen
- End-to-End Tests validieren die gesamte Wertschöpfungskette
Test-ROI: Jeder gefundene Fehler in der lokalen Umgebung spart 10-15 Minuten AWS-Deployment-Zeit und verhindert frustrierende Debug-Sessions in der Cloud.
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#7, Nextcloud#5 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Verifizieren, dass die globalen Standard-Tags (Projekt, Student, ManagedBy) auf allen via Terraform erstellten Ressourcen angezeigt werden. |
| Testschritte |
|
| Erwartetes Ergebnis | Alle in local.common_tags definierten Tags sind mit korrekten Werten vorhanden. |
| Tatsächliches Ergebnis | ✅ Tags auf VPC, Subnetzen, IGW, NAT Gateways und Routen erfolgreich verifiziert. |
| Nachweis | Screenshot vpc_tags_verification.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#5 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Sicherstellen, dass VPC, Subnetze, IGW und je AZ genau ein NAT Gateway korrekt erstellt sind. |
| Testschritte |
|
| Erwartetes Ergebnis | Komponenten und Routing wie definiert; AZ-NAT-GW-Architektur intakt. |
| Tatsächliches Ergebnis | ✅ Alles wie erwartet, AZ-spezifische NAT-Gateways korrekt. |
| Nachweis | Screenshot vpc_functionality_verification.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#6 |
| Status | ✅ Abgeschlossen (oder anpassen, falls teilweise) |
| Zielsetzung | Verifizieren, dass der Terraform-State im S3-Bucket gespeichert und via DynamoDB gelockt wird. |
| Testschritte |
|
| Erwartetes Ergebnis | S3-Backend initialisiert; State wird zentral verwaltet. |
| Tatsächliches Ergebnis | ✅ Initialisierung & State-Speicherung funktionierten. |
| Nachweis | Screenshot terraform_remote_backend.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#8 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Sicherstellen, dass EKS Cluster + Managed Node Group bereitgestellt und via kubectl erreichbar sind. |
| Testschritte |
|
| Erwartetes Ergebnis | Nodes im Status Ready, private IP-Adressen. |
| Tatsächliches Ergebnis | ✅ 2 Worker Nodes Ready, private IPs, IAM-Rollen korrigiert. |
| Nachweis | Screenshot eks_nodes_ready.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#9 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Verifizieren, dass das ECR Repository mit Scan-on-Push, Lifecycle-Policy & Tags erstellt ist. |
| Testschritte |
|
| Erwartetes Ergebnis | Repository-Konfiguration entspricht Terraform. |
| Tatsächliches Ergebnis | ✅ Alle Einstellungen in AWS Konsole bestätigt. |
| Nachweis | Screenshot ecr_repository_verification.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#10 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | OIDC-Provider & EBS-CSI-IAM-Rolle besitzen korrekte Trust Policy. |
| Testschritte |
|
| Erwartetes Ergebnis | Trust Policy entspricht exakt der Terraform-Definition. |
| Tatsächliches Ergebnis | ✅ Provider & Rolle identisch mit Definition. |
| Nachweis | Screenshot irsa_trust_policy_verification.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#11 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Sicherstellen, dass PVC → dynamisch EBS Volume erstellt & gebunden wird. |
| Testschritte |
|
| Erwartetes Ergebnis | PVC & PV Bound; Volume wird erstellt & gelöscht. |
| Tatsächliches Ergebnis | ✅ PVC binnen Sekunden Bound; Volume korrekt gehandhabt. |
| Nachweis | Screenshot ebs_pvc_bound_verification.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#12, #13 |
| Status | (nach Apply ausfüllen) |
| Zielsetzung | Verifizieren, dass RDS instanz privat platziert & nur vom EKS-Cluster erreichbar ist. |
| Testschritte |
|
| Erwartetes Ergebnis | DB privat, Zugriff nur via EKS-SG. |
| Tatsächliches Ergebnis | (nach Apply eintragen) |
| Nachweis | Screenshot rds_sg_inbound_rules.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Sprint-Fehleranalyse (indirekt #11, #14) |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Sicherstellen, dass IMDS-Hop-Limit korrekt und Topologie-Labels gesetzt sind. |
| Testschritte |
|
| Erwartetes Ergebnis | IMDS-Konnektivität & Topologie-Labels ok. |
| Tatsächliches Ergebnis | ✅ Nach Launch-Template-Fix alles grün; PVC-Probleme gelöst. |
| Nachweis | Screenshot eks_node_imds_topology.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#20 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | GitHub Actions kann per OIDC die IAM-Rolle Nextcloud-cicd-role übernehmen. |
| Testschritte |
|
| Erwartetes Ergebnis | Workflow läuft durch; ARN zeigt assumed-role/Nextcloud-cicd-role. |
| Tatsächliches Ergebnis | ✅ Workflow erfolgreich; Rolle übernommen. |
| Nachweis | Screenshot github_actions_oidc_workflow.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#21 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Sicherstellen, dass Push → Workflow → Helm-Deploy → Helm-Tests erfolgreich ist. |
| Testschritte |
|
| Erwartetes Ergebnis | Workflow mit grünem Haken, Logs zeigen dynamische Datenübergabe. |
| Tatsächliches Ergebnis | ✅ Workflow lief fehlerfrei; Helm-Tests bestanden. |
| Nachweis | Screenshot ci_cd_pipeline_summary.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#23 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Badge zeigt Live-Status & verlinkt zur Workflow-Seite. |
| Testschritte |
|
| Erwartetes Ergebnis | Badge sichtbar, Status korrekt, Link funktioniert. |
| Tatsächliches Ergebnis | ✅ Anzeige & Verlinkung wie erwartet. |
| Nachweis | Screenshot readme_pipeline_badge.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#41 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Manueller setup-Workflow provisioniert komplette Infrastruktur + App. |
| Testschritte |
|
| Erwartetes Ergebnis | Beide Jobs grün; Nextcloud online. |
| Tatsächliches Ergebnis | ✅ Workflow setzte Umgebung fehlerfrei auf. |
| Nachweis | Screenshot lifecycle_setup_workflow.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#42 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Manueller destroy-Workflow entfernt App & Infrastruktur vollständig und idempotent. |
| Testschritte |
|
| Erwartetes Ergebnis | Ressourcen vollständig entfernt; zweiter Lauf überspringt Steps. |
| Tatsächliches Ergebnis | ✅ Workflow entfernte alles; zweiter Lauf ohne Fehler. |
| Nachweis | Screenshot lifecycle_destroy_workflow.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#28 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Anleitung (Kap. 4.4) ermöglicht neuen Nutzern vollständiges Aufsetzen + Teardown. |
| Testschritte |
|
| Erwartetes Ergebnis | Kapitel logisch, lückenlos, verständlich. |
| Tatsächliches Ergebnis | ✅ Anleitung führt sicher durch Happy Path. |
| Nachweis | Verweis auf endgültiges Kapitel 4.4 (installation_guide_verification.png) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#26 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Diagramme repräsentieren finale Architektur (gesamt & AWS-Netzwerk) korrekt. |
| Testschritte |
|
| Erwartetes Ergebnis | Diagramme spiegeln Realität exakt wider. |
| Tatsächliches Ergebnis | ✅ Diagramme aktuell & vollständig. |
| Nachweis | Zusammengestelltes Bild architecture_diagrams.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#32 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Kapitel 7 bietet ehrliche, fundierte Reflexion inkl. Verbesserungspotenziale. |
| Testschritte |
|
| Erwartetes Ergebnis | Kohärente, kritische Auseinandersetzung. |
| Tatsächliches Ergebnis | ✅ Kapitel erfüllt Anforderungen. |
| Nachweis | Screenshot reflections_chapter.png (Abschnitt 5.6.1) |
| Kriterium | Beschreibung |
|---|---|
| User Story | Nextcloud#31 |
| Status | ✅ Abgeschlossen |
| Zielsetzung | Code ist formatiert, dokumentiert, frei von Artefakten. |
| Testschritte |
|
| Erwartetes Ergebnis | Format sauber, Kommentare erklären Warum, Repo frei von Altlasten. |
| Tatsächliches Ergebnis | ✅ Alle Checks bestanden; Repo sauber. |
| Nachweis | Screenshot codebase_quality_checks.png (Abschnitt 5.6.1) |
| Testfall | Datei | Kurzbeschreibung |
|---|---|---|
| T5.6.1 | vpc_tags_verification.png |
Tags auf VPC & NAT GW |
| T5.6.2 | vpc_functionality_verification.png |
VPC-/Routing-Stichprobe |
| T5.6.3 | terraform_remote_backend.png |
S3 State + terraform init |
| T5.6.4 | eks_nodes_ready.png |
kubectl get nodes Ready |
| T5.6.5 | ecr_repository_verification.png |
ECR Details & Lifecycle |
| T5.6.6 | irsa_trust_policy_verification.png |
IAM Trust Policy |
| T5.6.7 | ebs_pvc_bound_verification.png |
PVC/PV Bound + EBS Volume |
| T5.6.8 | rds_sg_inbound_rules.png |
RDS-SG Inbound 5432 |
| T5.6.9 | eks_node_imds_topology.png |
IMDS Hop-Limit & Topology-Label |
| T5.6.10 | github_actions_oidc_workflow.png |
GitHub Actions OIDC-Run |
| T5.6.11 | ci_cd_pipeline_summary.png |
Workflow-Übersicht grün |
| T5.6.12 | readme_pipeline_badge.png |
README Badge “passing” |
| T5.6.13 | lifecycle_setup_workflow.png |
setup-Workflow grün |
| T5.6.14 | lifecycle_destroy_workflow.png |
destroy-Workflow grün |
| T5.6.15 | installation_guide_verification.png |
Kapitel 4.4 (Ausschnitt) |
| T5.6.16 | architecture_diagrams.png |
Gesamt- & Netzwerk-Diagramm |
| T5.6.17 | reflections_chapter.png |
Auszug Kapitel 7 |
| T5.6.18 | codebase_quality_checks.png |
terraform fmt Output |
Diese README.md-Datei dient als zentrale und umfassende Projektdokumentation. Alle relevanten Informationen, von der
initialen Evaluation über die Architekturentscheidungen und die technische Implementierung bis hin zur Reflexion, sind
hier festgehalten oder direkt verlinkt.
Das Inhaltsverzeichnis am Anfang dieser Datei bietet eine schnelle Navigation zu allen relevanten Abschnitten. Jedes Hauptkapitel beginnt mit einer kurzen Einleitung, die den Zweck des Kapitels erläutert. Die agilen Sprint-Zusammenfassungen in Kapitel 2.3 dokumentieren den Projektfortschritt inkrementell und nachvollziehbar.
Für die Umsetzung dieses Projekts wurden ausschliesslich offizielle Dokumentationen der Hersteller und etablierte Community-Ressourcen herangezogen.
Primäre Werkzeuge:
- Cloud Provider: Amazon Web Services (AWS)
- Infrastructure as Code (Infra): Terraform v1.9.x
- Infrastructure as Code (App Config): Helm v3.15.x
- Container Orchestration: Kubernetes v1.29 (via AWS EKS)
- CI/CD: GitHub Actions
- Containerisierung: Docker (für das Nextcloud-Image)
- Anwendung: Nextcloud (offizielles Image von Docker Hub)
- Datenbank: AWS RDS for PostgreSQL v16.2
- Versionskontrolle: Git (gehostet auf GitHub)
Wichtige Referenzdokumentationen:
- Terraform Documentation
- Helm Documentation
- AWS EKS Best Practices Guides
- GitHub Actions Documentation
- Kubernetes Documentation
Unterstützung durch KI-Systeme:
Zur Effizienzsteigerung und Unterstützung in verschiedenen Phasen dieses Projekts wurden KI-gestützte Sprachmodelle eingesetzt. Die finale Verantwortung für den Code, die Architektur und die Dokumentation lag jedoch jederzeit beim Autor. Die KI-Systeme dienten als Werkzeug und nicht als primärer Ersteller.
- Verwendete Modelle: ChatGPT (OpenAI), Gemini (Google), Claude (Anthropic)
- Anwendungsbereiche:
- Brainstorming und Ideenfindung: Entwicklung von Lösungsansätzen für komplexe Probleme (z.B. LoadBalancer-Hostname-Automatisierung).
- Konzepterklärungen: Vereinfachte Erläuterungen zu AWS-Services, Kubernetes-Konzepten (z.B. IRSA, IMDS) und Terraform-Syntax.
- Code-Generierung und Refactoring: Erstellung von Boilerplate-Code (z.B. GitHub-Action-Grundgerüste) und Vorschläge zur Code-Verbesserung.
- Fehlersuche (Debugging): Analyse von Fehlermeldungen und Vorschläge für mögliche Ursachen und Lösungen.
- Grammatik und Formulierung: Korrektur und stilistische Verbesserung der Dokumentation in dieser
README.md-Datei.
Der gesamte Quellcode dieses Projekts (Terraform, Helm-Charts, GitHub-Actions-Workflows usw.) steht unter
der MIT-Lizenz.
Die Dokumentation dieses Repositories ist, sofern nicht anders gekennzeichnet, ebenfalls unter MIT veröffentlicht.
Das verwendete Nextcloud-Docker-Image unterliegt der AGPL-3.0 (→
siehe Nextcloud-Projekt).
Die ehrliche Geschichte eines Projekts zwischen Faszination und Überforderung - und warum das völlig in Ordnung ist.
Seien wir ehrlich: Die Scrum-Zeremonien konsequent durchzuziehen war... kompliziert.
Sprint Planning funktionierte noch ganz gut - da hatte ich konkrete Tasks und User Stories zum Planen. Aber die Retrospektiven? Das fühlte sich extrem seltsam an. Mit sich selbst über "was lief gut, was lief schlecht" zu diskutieren ist surreal. Meistens verschmolzen Review und Retrospektive zu einem grossen "Was habe ich geschafft und wo bin ich hängengeblieben?"-Moment.
Das tägliche Daily Scrum? Vergiss es. Manchmal erinnerte ich mich daran, meist nicht. Ich arbeitete lieber mit meinem lokalen Kanban-Board und vergass dann wochenlang, das offizielle GitHub-Board zu aktualisieren. Erst wenn ich für die Sprint-Dokumentation alles nachträglich eintragen musste, wurde mir bewusst, wie inkonsistent ich war.
Und dann kam das grosse Chaos. Irgendwann gegen Ende verlor ich mehrere Wochen Fortschritt, weil sich persönliche Sachen, Arbeit und Studium zu einem perfekten Sturm entwickelten. Dinge kamen dazwischen, die Prioritäten verschoben sich, und plötzlich hatte ich wochenlang nicht mehr am Projekt gearbeitet. Das war frustrierend und stressig - besonders weil die Deadline näher rückte.
Aber hier ist das Verrückte: Trotz allem war es unglaublich faszinierend.
Wenn alles funktionierte, wenn ich einen gh workflow run lifecycle.yml -f action=setup ausführte und 20 Minuten später
eine komplette Nextcloud-Instanz in der Cloud lief - das war pure Magie. So viele bewegliche Teile: Terraform erstellt
die Infrastruktur, EKS startet die Cluster, GitHub Actions orchestriert alles, Helm deployed die Anwendung, Load
Balancer leiten Traffic weiter. Und irgendwie funktioniert es zusammen.
Die Komplexität war überwältigend. Ich habe ehrlich gesagt viele Konfigurationen implementiert, ohne das grosse Bild zu verstehen. IRSA Trust Policies? Keine Ahnung, warum diese spezielle JSON-Syntax funktioniert, aber sie tut es. EKS Launch Templates mit IMDS Hop Limits? Ich habe die Lösung gefunden und implementiert, aber die zugrunde liegenden EC2-Netzwerk-Mechanismen sind mir immer noch ein Rätsel.
Das ist vermutlich der ernüchterndste Lerneffekt: Ich bräuchte wahrscheinlich ein intensives DevOps-Bootcamp über mehrere Monate, um wirklich zu verstehen, was ich da gebaut habe. Momentan fühlt es sich an, als hätte ich ein komplexes Uhrwerk zusammengebaut, das funktioniert - aber ich könnte dir nicht erklären, warum jedes Zahnrad genau dort sein muss.
Die Tools waren auch nicht immer meine Freunde.
Terraform? Grossartig, wenn es funktioniert. Frustrierend, wenn kryptische Fehlermeldungen kommen und man nicht weiss, ob es ein Syntax-Problem, ein AWS-Problem oder ein State-Problem ist. GitHub Actions? Mächtig, aber das Debugging ist schmerzhaft - man kann nicht einfach einen Breakpoint setzen.
Helm war anfangs verwirrend mit all den Templates und Values, wurde aber zum Ende hin zu meinem Lieblings-Tool. Kubernetes selbst? Immer noch ein Mysterium in vielen Bereichen. Ich kann ein Deployment erstellen und einen Service exponieren, aber wenn etwas schief geht, fühle ich mich oft hilflos.
Das GitHub Board-Management war katastrophal. Ich arbeitete hauptsächlich mit meinem lokalen Setup - Post-its, Notizen, mentale TODOs. Das offizielle Board aktualisierte ich nur sporadisch, meist erst wenn ich für die Sprint-Reviews alles nachträglich dokumentieren musste. Das ist ehrlich gesagt ein typisches Problem: Die Tools, die für die Dokumentation gut sind, sind nicht unbedingt die Tools, mit denen ich gerne arbeite.
Das Projekt war ein Erfolg, auch wenn der Weg chaotisch war.
Am Ende funktioniert alles. Ein Button erstellt eine komplette Cloud-Infrastruktur, ein anderer löscht sie wieder. Das ist beeindruckend, auch wenn ich nicht jeden Aspekt davon vollständig durchdringe.
Die grössten Erkenntnisse waren nicht technisch, sondern meta:
- Komplexe Systeme funktionieren oft, auch wenn man nicht alles versteht - und das ist okay
- Documentation-as-Code ist grossartig, aber nur wenn man es auch tut (anstatt es aufzuschieben)
- Work-Life-Balance ist nicht nur ein Buzzword - wenn sie kippt, leiden alle Projekte
- Manchmal ist "es funktioniert" wichtiger als "ich verstehe warum es funktioniert"
Wenn ich das Projekt nochmal machen würde? Ich würde versuchen, konsequenter mit dem Prozess zu sein, aber ehrlich gesagt würde wahrscheinlich ähnliches Chaos entstehen. Das ist menschlich. Das Wichtige ist, dass ich trotz aller Umwege und Stolpersteine etwas Funktionierendes und Nützliches geschaffen habe.
Und das Gefühl, wenn der ganze Stack zum ersten Mal funktioniert hat? Unbezahlbar. Dafür hat sich jede frustrierende Debug-Session gelohnt.
Zusätzliche Materialien, die das Verständnis unterstützen oder für die Nachvollziehbarkeit relevant sind.
Die hier aufgeführten Markdown-Vorlagen dienten als Grundlage und Inspiration für die Dokumentation der Scrum-Zeremonien und Artefakte.
- Sprint Planning Vorlage
- Daily Scrum Log Vorlage
- Sprint Review Vorlage
- Sprint Retrospektive Vorlage
- User Story Vorlage
Platz für zusätzliche Links, interessante Artikel oder Dokumente, die im Projektkontext relevant waren.
Der vollständige Quellcode und diese Dokumentation sind öffentlich zugänglich unter: https://github.com/Stevic-Nenad/Nextcloud
Der aktuelle Stand der Aufgaben und das Product/Sprint Backlog sind einsehbar unter: https://github.com/users/Stevic-Nenad/projects/1/views/1
Selbstständigkeitserklärung
Ich erkläre hiermit, dass ich die vorliegende Semesterarbeit selbstständig und ohne fremde Hilfe verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel benutzt habe. Alle Stellen, die dem Wortlaut oder dem Sinn nach anderen Werken entnommen sind, wurden unter Angabe der Quelle kenntlich gemacht.
Ort, Datum Nenad Stevic
