DevOps Projekt 2: Lift & Shift – von lokalem Multi-VM Setup zu AWS

Weiterentwicklung meines lokalen Projekts (Vagrant Multi-VM) zu einer Lift-&-Shift Migration auf AWS. Fokus: gleiche Anwendung / gleiche Rollen, aber Cloud-Infrastruktur mit EC2, S3, Application Load Balancer, Route 53, ACM und Auto Scaling.

AWS EC2 S3 ALB (HTTPS) Route 53 ACM Zertifikat Auto Scaling Security Groups IAM (Keys & Roles) Tomcat Java 17 Maven
Wichtig:
Dieses Projekt zeigt die Entwicklung von Local Automation (Vagrant) zu einer Cloud-Migration (AWS) – inklusive Security, DNS, HTTPS, Artefakt-Management und Skalierung.

1. Projektziel

Ziel war es, den bestehenden lokalen Multi-Service-Stack (NginxTomcatDB/Cache/Queue) als Lift & Shift nach AWS zu übertragen. Dabei bleibt die Anwendung (WAR, Ports, Services) konzeptionell gleich – aber die Infrastruktur wird cloud-ready:

2. Architektur-Übersicht: Lokal → AWS

Links: lokales Multi-VM Setup (Vagrant). Rechts: AWS Architektur (ALB + EC2 + S3 + DNS + Auto Scaling).

Hinweis:
Lokal war Nginx der Entry Point. In AWS übernimmt diese Rolle der Application Load Balancer (HTTPS), während Tomcat horizontal skaliert werden kann (ASG). Artefakte liegen zentral in S3.

3. Ausführungsablauf (AWS) – Visuelles Schema

Dieses Diagramm entspricht dem realen Implementierungsablauf – inklusive des Artefakt-Flows Build → S3 → EC2.

AWS Lift & Shift Build → S3 → EC2 ALB + Auto Scaling + Security AWS Konsole Anmeldung Key Pair erstellen SSH Zugriff Security Groups definieren Netzwerk-Regeln EC2 starten User Data (Bash) Route 53 (Private DNS) Name statt IP Build (Maven) WAR erzeugen S3 Upload (AWS CLI) IAM Keys Tomcat EC2: Artefakt Download IAM Role (kein Key auf EC2) ALB einrichten (HTTPS) ACM Zertifikat Domain verbinden (externes DNS) z. B. GoDaddy → ALB End-to-End Validierung Health/Logs/HTTP Auto Scaling Group (Tomcat) Skalierung + Ersatz Ablauf: Konsole → Zugriff/Security → Compute/DNS → Build/Artefakt → Deploy → HTTPS/Domain → Verify → Skalierung

Kernidee:
Der Ablauf trennt klar zwischen Build, Artefakt-Speicherung und Runtime und folgt damit DevOps- und AWS-Best-Practices.

4. Login in den AWS Account

- Ziel:

Zugriff auf die AWS-Konsole als "Root user", um Cloud-Infrastruktur zu erstellen und zu verwalten. (https://aws.amazon.com/de/console/)

Warum?

AWS Management Console – EC2 Dashboard (Login erfolgreich)
AWS Management Console – erfolgreicher Login mit Zugriff auf das EC2 Dashboard (Region: N. Virginia).

5 Key Pair erstellen

- Ziel:

SSH-Key als ".pem-Datei" für den sicheren Zugriff auf EC2-Instanzen über Git Bash.

Warum ist das unverzichtbar?

Was wird erstellt?

project-prod-key.pem

Spätere Nutzung

ssh -i project-prod-key.pem ec2-user@<PUBLIC_IP>

Hinweis: Diese SSH-Verbindung wird später verwendet, um sich direkt mit der EC2-Instanz zu verbinden. Dabei ist ec2-user der standardmäßige Linux-Benutzer auf Amazon-Linux-Instanzen und <PUBLIC_IP> die öffentliche IP-Adresse der EC2, über die sie aus dem Internet erreichbar ist.

6 Security Groups erstellen

- Ziel:

Netzwerkregeln (Firewall) zwischen den Komponenten definieren.

- Wichtiges Konzept:

Eine Security Group „blockiert“ keine Maschine – sie erlaubt gezielt Netzwerkverkehr (Flows).

- Erstellte Security Groups:

🔹 SG 1 – Load Balancer (SG-ALB)

Inbound Rules (Erlaubter eingehender Traffic)

  • HTTP (80) → 0.0.0.0/0 ( Für alle IPv4)
  • HTTP (80) → ::/0 (IPv6)
  • HTTPS (443) → 0.0.0.0/0 (IPv4)
  • HTTPS (443) → ::/0 (IPv6)

Outbound Rules (Erlaubter ausgehender Traffic)

  • All traffic → 0.0.0.0/0 (IPv4)
Hinweis: Der Load Balancer ist der einzige öffentliche Entry Point.

🔹 SG 2 – Tomcat (SG-Tomcat)

Inbound Rules

  • 8080 → SG-ALB – HTTP.Anfragen vom Load Balancer zur App(tomcat)
  • SSH 22 (MyIP) → Admin-IP – Sicherer administrativer Zugriff

Outbound Rules (Erlaubter ausgehender Traffic)

  • All traffic → 0.0.0.0/0

🔹 SG 3 – Backend (SG-Backend)

Inbound Rules

- Kein Public Access
- Backend ist isoliert und abgesichert

Hinweis: Die Port- und Host-Konfiguration aller Backend-Services (MySQL, Memcached, RabbitMQ) befindet sich zentral in src/main/resources/application.properties.
AWS Management Console – EC2 Dashboard (Login erfolgreich)

7. EC2-Instanzen mit User Data (Bash) starten

- Ziel:

EC2-Instanzen so starten, dass sie sich beim ersten Boot automatisch konfigurieren.

- Wie viele EC2 und warum?

Rolle     EC2                Warum
Tomcat      1                 Anwendung
MySQL       1                 Daten
Memcached   1                 Cache
RabbitMQ    1                 Messaging

Gleiche Aufteilung wie im lokalen Vagrant-Projekt.

- Wie wird eine EC2 konkret erstellt?

Bevor wir EC2-Instanzen herstellen und starten, bereiten wir den Code und die Provisioning-Dateien sauber vor. So bleiben Infrastruktur und Applikationskonfiguration versioniert, reproduzierbar und auditierbar.

Prerequisite:
Für die AWS-Migration arbeiten wir in einer eigenen Git-Branch awsliftandshift. Dadurch bleiben das lokale Vagrant-Setup und die AWS-Änderungen klar getrennt.
git checkout -b awsliftandshift 
git push -u origin awsliftandshift
Repository klonen und in VS Code öffnen. userdata/ in Projektordner anlegen, der alle Dateien(Konfiguration + Service-Skripte) enthält, die beim EC2-Start genutzt werden. Diese Skripte existieren, um EC2-Instanzen automatisch beim ersten Boot zu provisionieren (User Data). Dadurch entfällt manuelle Konfiguration per SSH und das Setup wird reproduzierbar
git clone <repo-url>
cd project-root
code .
AWS Management Console – EC2 Dashboard (Login erfolgreich)
  • application.properties: Zentrale App-Konfiguration (DB/Cache/Queue Hosts & Ports). In AWS bevorzugt über Private DNS (Route 53) statt fester IPs.
  • al2023rmq.repo: Diese Datei wird in rabbitmq.sh aufgeruft und definiert offizielle RabbitMQ- und Erlang-Repositories, um eine kompatible, sichere und stabile Installation von RabbitMQ auf Amazon Linux zu gewährleisten.
  • mysql.sh: Installiert & konfiguriert die Datenbank (User/Grants/Schema) – damit die App sofort persistente Daten speichern kann.
  • memcache.sh: Installiert Memcached und startet den Service – für schnelle Sessions/Cache, weniger DB-Last.
  • rabbitmq.sh: Installiert RabbitMQ, richtet User/Permissions ein – für asynchrone Kommunikation (Queue).
  • tomcat_ubuntu.sh: Installiert Java + Tomcat und aktiviert den Service – vorbereitet für das Deployment des ROOT.war.

Jetzt Herstellen der EC2-Instanzen mit Konfiguration in AWS(Launch instances) :

Die folgende Tabelle zeigt die exakten Einstellungen, mit denen die vier EC2-Instanzen erstellt werden (Name, AMI, Typ, Key Pair, Security Group und das passende User-Data-Skript).

Instance Name AMI Instance Type Key Pair Network Settings (Security Group) User Data
profile-db01 Amazon Linux t3.micro profile-prod-key.pem SG-Backend backend.sh
profile-mc01 Amazon Linux t3.micro profile-prod-key.pem SG-Backend memcache.sh
profile-rmq01 Amazon Linux t3.micro profile-prod-key.pem SG-Backend rabbitmq.sh
profile-app01 Ubuntu 24.04 t3.micro profile-prod-key.pem SG-Tomcat tomcat_ubuntu.sh

Hinweis: Die Backend-Instanzen (db01, mc01, rmq01) liegen bewusst in SG-Backend (kein Public Access). Die Applikationsinstanz app01 nutzt SG-Tomcat, damit nur der Load Balancer (und Admin-SSH) Zugriff erhält. profile-app01 auf Ubuntu 24, weil Tomcat + Java + die Applikation unter Ubuntu stabiler sind.

AWS EC2 Instances – laufende Application- und Backend-Server
Übersicht der laufenden EC2-Instanzen (profile-app01, profile-db01, profile-mc01, profile-rmq01) – jede Instanz repräsentiert einen dedizierten Service der Anwendung.
wichtig: dann in Git Bash:
ssh -i project-prod-key.pem ec2-user@<PUBLIC_IP>
sudo -i
systemctl status "service-name"

für profile-app01 Ec2 wird ec2-user als ubuntu ersetzt

Ergebnis:

8. IPs zu Name Mapping mit Route 53

- Ziel:

IPs durch interne DNS-Namen ersetzen.

- Warum Route 53?

IP-Adressen von EC2-Instanzen können sich ändern (z. B. bei Neustarts). Durch Route 53 werden stabile DNS-Namen verwendet, die:

– In Route 53 "Private Hosted Zone" herstellen

Private Zone, an das VPC gebunden:

Domain name: myapp.internal

- Erstellte Records:

Name                  Zeigt auf
db01.myapp.internal    MySQL privates IP
mc01.myapp.internal    Memcached privates IP
rmq01.myapp.internal   RabbitMQ privates IP

Hinweis: Hier ist Route 53 für tomcat(app01) nicht nötig, da es Load Balancer verwendet wird.

- Nutzung in der Anwendung

Anpassungen In application.properties:

jdbc.url=jdbc:mysql://db01.myapp.internal:3306/db
memcached.host=mc01.myapp.internal
rabbitmq.host=rmq01.myapp.internal

Checks:

Ergebnis:

9. Anwendung aus Source Code builden

- Ziel:

Java-Quellcode kompilieren und ein deploybares Artefakt erzeugen (ROOT.war).

- Wo wird dieser Schritt ausgeführt?

Hinweis: Keine EC2 ist bei diesem Schritt beteiligt.

- Warum so?

Der Build erfolgt lokal. Das WAR wird in ein S3-Bucket in AWS hochgeladen (IAM Access Keys) und von der Tomcat-EC2 anschließend per IAM Role sicher aus S3 heruntergeladen.

- AWS Konfiguration

- Code Struktur (VS Code)

profile/
├── src/                    # Java-Quellcode
├── pom.xml                 # Maven-Konfiguration
├── application.properties  # Config (DB/Cache/Queue via DNS)
└── target/
    └── ROOT.war            # Generiertes Artefakt

- Exakte Commands (Git Bash):

Teil A – Lokal (Git Bash): Build + Upload nach S3

cd profile
mvn install                 # Build → erzeugt das WAR im target/ Ordner

aws configure                     # AWS CLI: IAM Access Key/Secret Key konfigurieren
aws s3 cp target/profile-v2.war s3://BUCKET-NAME/     # Artefakt nach S3 hochladen
aws s3 ls s3://BUCKET-NAME/                           # Prüfen, ob profile-v2.war vorhanden ist

Teil B – Auf AWS (Tomcat EC2): Download + Deployment

# 1) Verbindung zur Tomcat-EC2 (app01)
ssh -i project-prod-key.pem ubuntu@PUBLIC_IP_TOMCAT
sudo -i

# 2) AWS CLI installieren (nur falls nicht vorhanden)
snap install aws-cli --classic

# 3) Artefakt von S3 holen
aws s3 cp s3://BUCKET-NAME/profile-v2.war /tmp/

# 4) Deployment auf Tomcat 10
systemctl daemon-reload
systemctl stop tomcat10

ls /var/lib/tomcat10/webapps                # Default Apps prüfen
rm -rf /var/lib/tomcat10/webapps/ROOT       # Default ROOT entfernen

cp /tmp/profile-v2.war /var/lib/tomcat10/webapps/ROOT.war   # WAR als ROOT deployen
systemctl start tomcat10
 
AWS EC2 Instances – laufende Application- und Backend-Server
# 5) Quick Check lokal auf der EC2 curl -I http://localhost:8080/

Erwartetes Ergebnis: HTTP/1.1 200 OK

Hinweis: ROOT.war wird automatisch nach ROOT/ entpackt. Dadurch ist die App direkt unter / erreichbar .

10. Application Load Balancer Setup mit HTTPS (ACM)

Ziel

Der Load Balancer ist der zentrale Einstiegspunkt (Single Entry Point) für alle Benutzeranfragen an die Anwendung und die Absicherung des Benutzerzugriffs mit HTTPS.

Warum?

User (HTTPS mit Zertifikat von ACM)
  ↓
ALB (TLS Termination)
  ↓
Tomcat EC2 (HTTP)

Werkzeuge & Setup für den Load Balancer

In diesem Schritt wird der Load Balancer mit HTTPS abgesichert und mit der Tomcat-Anwendung verbunden.

Health Check

Der Status der Tomcat-Instanzen wird über die Target Group geprüft. Der Status muss Healthy sein.

Ergebnis im Browser

GoDaddy steuert nur das DNS-Routing (wohin die Domain zeigt). Das TLS-Zertifikat wird in AWS über ACMALB genutzt (HTTPS).

Merksatz:
GoDaddy sagt wohin der Traffic geht (DNS). ACM/ALB sorgen dafür, dass der Traffic verschlüsselt ankommt (HTTPS).

11. Auto Scaling Group (Tomcat)

- Ziele

- Funktionsweise

User
  ↓
ALB
  ↓
Auto Scaling Group
  ├─ Tomcat EC2 #1
  ├─ Tomcat EC2 #2
  └─ Tomcat EC2 #3

- Werkzeuge & Setup für die Auto Scaling Group

Für die Einrichtung einer Auto Scaling Group werden drei zentrale Komponenten benötigt. Diese sorgen dafür, dass Tomcat-Instanzen automatisch erstellt, ersetzt und skaliert werden können.

Ergebnis:
Die Anwendung bleibt hochverfügbar. Bei Lastspitzen oder Instanz-Ausfällen reagiert AWS automatisch – ohne manuelles Eingreifen.

12. Fazit

Die Lift-&-Shift-Strategie ( Build(lokal) → S3(AWS) → EC2(AWS) ) ermöglicht eine schnelle Migration ohne Code-Änderungen. Sie schafft eine stabile Basis, auf der spätere Optimierungen sicher aufgebaut werden können.

Aufbauend auf diesem Projekt sind Cloud-Native-Weiterentwicklungen geplant.

Zur Cloud-Native (profile-projekt)