Veröffentlicht am

Lift-and-Shift vs Refactoring: Migration im Vergleich

Teilen:
Authors

TL;DR

Lift-and-Shift bringt Anwendungen schnell in Container, ohne den Code zu ändern – ideal bei Zeitdruck und begrenztem Budget. Refactoring zerlegt die Anwendung in Microservices und nutzt Kubernetes-Features voll aus, kostet aber deutlich mehr Zeit. Das Strangler-Fig-Pattern bietet einen pragmatischen Mittelweg: schrittweise Migration einzelner Komponenten ohne Big-Bang-Risiko.

Zwei Strategien, ein Ziel

Jede Kubernetes-Migration beginnt mit der gleichen Frage: Verschieben wir die Anwendung unverändert in Container, oder bauen wir sie um? Hier ein schneller Überblick als Dockerfile-Vergleich:

# Lift-and-Shift: Bestehende WAR-Datei in Container packen
FROM tomcat:10-jre21
COPY target/legacy-app.war /usr/local/tomcat/webapps/app.war
EXPOSE 8080
CMD ["catalina.sh", "run"]

# Refactoring: Einzelner Microservice als Spring Boot JAR
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY build/libs/order-service.jar app.jar
USER 1000
ENTRYPOINT ["java", "-XX:MaxRAMPercentage=75.0", "-jar", "app.jar"]

Der Unterschied ist fundamental: Lift-and-Shift nimmt den Monolithen mit, Refactoring zerlegt ihn.

Entscheidungsmatrix

KriteriumLift-and-ShiftRefactoring
Zeitaufwand2-4 Wochen3-12 Monate
Kosten initialNiedrigHoch
BetriebskostenHöher (oversized Container)Niedriger (optimiert)
SkalierbarkeitBegrenzt (ganzer Monolith)Granular (pro Service)
Team-Skills nötigDocker-GrundlagenMicroservices, K8s-Erfahrung
RisikoGeringMittel bis hoch
Kubernetes-Nutzung~20% der Features~80% der Features

Lift-and-Shift in der Praxis

Beispiel: Eine Java-Monolith-Anwendung mit Tomcat, PostgreSQL-Datenbank und Session-basierter Authentifizierung.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: legacy-monolith
spec:
  replicas: 1  # Monolith = schwer horizontal skalierbar
  selector:
    matchLabels:
      app: legacy-monolith
  template:
    metadata:
      labels:
        app: legacy-monolith
    spec:
      containers:
        - name: app
          image: registry.example.com/legacy-app:1.0
          ports:
            - containerPort: 8080
          resources:
            requests:
              memory: "2Gi"
              cpu: "1000m"
            limits:
              memory: "4Gi"
              cpu: "2000m"
          volumeMounts:
            - name: app-data
              mountPath: /data/uploads
      volumes:
        - name: app-data
          persistentVolumeClaim:
            claimName: legacy-pvc

Der Monolith läuft jetzt in Kubernetes, aber die Architektur hat sich nicht verändert. Skalierung ist nur vertikal möglich (mehr RAM/CPU). Sessions sind nicht replizierbar, daher replicas: 1.

Was Sie gewinnen: Standardisiertes Deployment, Infrastructure-as-Code, einfacheres Rollback, CI/CD-Pipeline.

Was Sie nicht gewinnen: Auto-Scaling, unabhängige Deployments einzelner Features, Resilience bei Teilausfällen.


Refactoring: Derselbe App als Microservices

Die gleiche Anwendung, zerlegt in drei Services:

# Order Service - skaliert unabhängig
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service
          image: registry.example.com/order-service:2.1
          ports:
            - containerPort: 8080
          resources:
            requests:
              memory: "256Mi"
              cpu: "100m"
            limits:
              memory: "512Mi"
              cpu: "500m"
          readinessProbe:
            httpGet:
              path: /health/ready
              port: 8080
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: order-service-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: order-service
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

Drei separate Services (Order, User, Notification) statt einem Monolithen. Jeder Service skaliert unabhängig, hat eigene Datenbank und eigenes Release-Tempo.

Das Strangler-Fig-Pattern als Mittelweg

Das Strangler-Fig-Pattern vermeidet die Alles-oder-Nichts-Entscheidung. Sie betreiben den Monolithen weiter und extrahieren schrittweise einzelne Module als Microservices.

Schritt 1: Monolith läuft in K8s (Lift-and-Shift)
┌─────────────────────────┐
Monolith[Orders][Users][Notif]└─────────────────────────┘

Schritt 2: Ersten Service extrahieren
┌─────────────────────────┐   ┌──────────────┐
Monolith          │   │ Notification[Orders][Users]        │──▶│   Service└─────────────────────────┘   └──────────────┘

Schritt 3: Weitere Services extrahieren
┌──────────┐  ┌──────────┐  ┌──────────────┐
Order   │  │  User    │  │ NotificationService  │  │ Service  │  │   Service└──────────┘  └──────────┘  └──────────────┘

Der Vorteil: Jeder Schritt ist rückgängig machbar. Sie brauchen kein Feature-Freeze und das Team sammelt Microservice-Erfahrung am lebenden System. Typischerweise beginnen Sie mit dem am wenigsten kritischen Modul (oft Notifications oder Reporting).

Wann welche Strategie?

Lift-and-Shift wählen, wenn:

  • Datacenter-Vertrag läuft in 3 Monaten aus
  • Budget für Refactoring fehlt
  • Team hat noch keine Kubernetes-Erfahrung
  • Anwendung wird in 1-2 Jahren abgelöst

Refactoring wählen, wenn:

  • Anwendung hat 5+ Jahre Lebensdauer vor sich
  • Skalierung ist ein echtes Problem (nicht nur theoretisch)
  • Team hat Microservice-Erfahrung
  • Einzelne Module haben stark unterschiedliche Lastprofile

Strangler Fig wählen, wenn: Sie sich nicht sicher sind. Es ist der sicherste Weg und lässt alle Optionen offen.


FAQ

Wie lange dauert eine typische Lift-and-Shift-Migration?

Für eine einzelne Anwendung: 2-4 Wochen inklusive Containerisierung, Testing und Deployment-Pipeline. Bei mehreren Anwendungen rechnen Sie mit 1-2 Tagen pro App nach der ersten.

Ist Lift-and-Shift nur eine Zwischenlösung?

Nicht unbedingt. Wenn die Anwendung stabil läuft und keine Skalierungsprobleme hat, kann Lift-and-Shift der Endzustand sein. Refactoring nur um des Refactorings willen verschwendet Budget.

Welche Komponente sollte ich zuerst aus dem Monolithen extrahieren?

Wählen Sie ein Modul mit wenigen Abhängigkeiten, klarer API-Grenze und geringem Geschäftsrisiko. Notification-Services oder Reporting-Module eignen sich oft gut als erster Kandidat.

Was kostet Refactoring im Vergleich zu Lift-and-Shift?

Faktor 5-10x bei den initialen Kosten. Ein Lift-and-Shift für eine mittelgroße App kostet ca. 10.000-20.000 EUR, ein vollständiges Refactoring 80.000-200.000 EUR. Die Betriebskosten kehren sich langfristig um.

Kann ich Lift-and-Shift und Refactoring kombinieren?

Ja, genau das ist das Strangler-Fig-Pattern. Starten Sie mit Lift-and-Shift und extrahieren Sie nach und nach die Module, die den größten Nutzen als eigenständige Services bringen.

Legacy zu Kubernetes migrieren?

Wir begleiten Ihre Migration von VMs zu Containern – ohne Produktionsausfall. Erfahrung aus 50+ Migrationsprojekten.

Kubernetes-Beratung gesucht?

Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen