AMAZON ECS → STACKIT KUBERNETES ENGINE · TUTORIAL

Amazon ECS zu STACKIT Kubernetes: ein durchgespieltes Beispiel

ECS hat auf STACKIT kein Eins-zu-eins-Gegenstück: Die Container bleiben, Task Definition und Service werden zu Kubernetes-Objekten auf der STACKIT Kubernetes Engine (SKE). Dieses Tutorial führt StackToIT auf einer kleinen Fargate-Umgebung aus und zeigt, was es schreibt, was es zurückhält und was Sie entscheiden, bevor der erste Pod läuft.

Die Eingabe: eine Task Definition, ein Service

Eine für diese Seite geschriebene Demo-Umgebung: ein Fargate-Service mit drei Tasks zu je 0,5 vCPU und 1 GiB hinter einem Application Load Balancer, ein Secret, ein einfacher Umgebungswert und eine awslogs-Log-Gruppe. Links Task Definition und Service, rechts das Deployment, das StackToIT dafür entworfen hat (der lange Kommentarkopf der Datei ist hier weggelassen; alles Gezeigte ist unverändert).

Beispieleingabe · Task Definitionmain.tf
resource "aws_ecs_task_definition" "web" {
  family                   = "shop-web"
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  cpu                      = "512"
  memory                   = "1024"
  execution_role_arn       = aws_iam_role.task_execution.arn

  container_definitions = jsonencode([
    {
      name         = "web"
      image        = "registry.example.com/shop/web:1.8.2"
      essential    = true
      portMappings = [{ containerPort = 8080, protocol = "tcp" }]
      environment  = [{ name = "APP_ENV", value = "production" }]
      secrets      = [{ name = "DATABASE_URL", valueFrom = aws_secretsmanager_secret.db_url.arn }]
      logConfiguration = {
        logDriver = "awslogs"
        options = {
          "awslogs-group"         = "/ecs/shop-web"
          "awslogs-region"        = "eu-central-1"
          "awslogs-stream-prefix" = "web"
        }
      }
    }
  ])
}
Beispieleingabe · Servicemain.tf
resource "aws_ecs_service" "web" {
  name            = "web"
  cluster         = aws_ecs_cluster.shop.id
  task_definition = aws_ecs_task_definition.web.arn
  desired_count   = 3
  launch_type     = "FARGATE"

  network_configuration {
    subnets         = [aws_subnet.app_a.id, aws_subnet.app_b.id]
    security_groups = [aws_security_group.web.id]
  }

  load_balancer {
    target_group_arn = aws_lb_target_group.web.arn
    container_name   = "web"
    container_port   = 8080
  }
}
Kubernetes-Entwurf von StackToITterraform/kubernetes/web/manifests.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app.kubernetes.io/name: web
spec:
  replicas: 0 # held back until the start step of the plan scales to the number the header names
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 3
  selector:
    matchLabels:
      app.kubernetes.io/name: web
  template:
    metadata:
      labels:
        app.kubernetes.io/name: web
    spec:
      containers:
      - name: web
        image: "registry.example.com/shop/web:1.8.2"
        ports:
        - containerPort: 8080
          protocol: TCP
        env:
        - name: APP_ENV
          valueFrom:
            configMapKeyRef:
              name: web-env
              key: APP_ENV
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: web-secrets
              key: DATABASE_URL
        resources:
          requests:
            cpu: "500m"
            memory: "1024Mi"
          limits:
            cpu: "500m"
            memory: "1024Mi"
        readinessProbe:
          httpGet:
            path: "/healthz"
            port: 8080
          periodSeconds: 30
          timeoutSeconds: 6
          successThreshold: 3
          failureThreshold: 3

Der Ablauf

Fünf Schritte von den Terraform-Dateien bis zur laufenden Workload. Die ersten beiden erledigt StackToIT, alles Weitere ist Arbeit Ihres Teams mit den Dateien, die StackToIT geschrieben hat.

  1. 1 · Bewertung ausführen

    Führen Sie StackToIT in dem Ordner aus, der das Terraform enthält. Es liest die Dateien, verbindet sich nie mit AWS und schreibt einen Ausgabeordner mit Entwurf, Entscheidungen und Ausführungsplan.

  2. 2 · Klassifizierung lesen

    Cluster und Service werden als REPLATFORM eingestuft, das umgebende Netzwerk, Secret, Rolle, Log-Gruppe und Load Balancer als RECONFIGURE. Task Definition und Target Group haben keine eigene Einheit: Ihr Inhalt fließt in den Service ein.

  3. 3 · Entscheidungen beantworten

    Beantworten Sie die offenen Entscheidungen in review/decisions.yaml (wie der Load Balancer die Pods erreicht, ob die Pods segmentiert werden, in welchem Netzwerk der Cluster und seine Konsumenten liegen, das Opt-in für die API-Aufrufe) und setzen Sie die Variablen des Node-Pools (Maschinentyp, Minimum, Maximum) in der Datei mit den Zielwerten.

  4. 4 · Erst den Cluster anwenden, dann die Manifeste

    Zuerst das Terraform für den SKE-Cluster anwenden. Die Manifeste werden mit replicas auf 0 geschrieben, damit nichts läuft und keine Verbindung zu einem Datenspeicher aufbaut, bevor dessen Daten da sind.

  5. 5 · Hochskalieren und Traffic umschalten

    Nach dem Datenumzug auf die im Quellsystem genannte Zahl der Tasks skalieren, den Smoke-Test der Checkliste ausführen, Load Balancer oder DNS-Eintrag umstellen und ECS weiterlaufen lassen, bis Sie das Ergebnis abgenommen haben.

Was der Lauf meldet

Die Zusammenfassung, die der Befehl für die Demo-Umgebung ausgibt (console.txt im Ausgabeordner). Aufgerufen wurde im Eingabeordner stacktoit assess . <Ausgabeordner> --offline --no-validate; --offline ist der dokumentierte Weg, ohne Netzwerkanfragen zu arbeiten, und --no-validate hat die OpenTofu-Prüfung der Quelle übersprungen; deshalb meldet die Zusammenfassung sie als nicht gelaufen.

Lauf-Zusammenfassungconsole.txt
Source:                 input
Source files:           1
Resources scanned:      13
  support resources:    1  (+0 Terraform helpers, out of scope; 1 + 0 = the 1 support node of summary.support.nodes in assessment.json)
Migration units:        10  (10 instances)
Unit dependencies:      14
Source checks:          Built-in source checks passed — OpenTofu validation of the source was not run

STACKIT mapping
────────────────────────────────────────────
DIRECT              0  
RECONFIGURE         8  ████████████████████████ 80%
REPLATFORM          2  ██████ 20%
CONTAINERIZE        0  
REDESIGN            0  
MANUAL_REVIEW       0  
BLOCKED             0    (the mapping class BLOCKED, not the execution blockers, which Migration readiness counts)

Wie die ECS-Einstellungen auf Kubernetes landen

ECS-Einstellung in der DemoKubernetes-Ergebnis im EntwurfWas Sie prüfen
desired_count = 3replicas: 0 in der Datei, im Startschritt auf 3 skaliertDer Startschritt schreibt die Zahl auch in die Datei; erneutes Anwenden mit 0 würde die Pods wieder zurückhalten
cpu 512, memory 1024 am TaskRequests und Limits von 500m und 1024Mi am ContainerRequests und Limits sind hier gleich; mit realer Auslastung neu bewerten
secrets valueFrom aus einem Secrets-Manager-SecretsecretKeyRef auf ein Secret web-secrets, Schlüssel DATABASE_URLDas Secret legen Sie an; der Wert steht nie im Entwurf
environment APP_ENVeine ConfigMap web-env mit leerem data-BlockWerte werden absichtlich nicht kopiert, weil ein Wert unter jedem Namen ein Geheimnis sein kann
Health Check /healthz der Target GroupreadinessProbe httpGet auf /healthz, Port 8080Die Quelle setzt nur den Pfad, daher schreibt der Entwurf die dokumentierten Standardwerte der Target Group (Intervall 30, Schwellwerte 3, Timeout je nach Protokoll); das kubelet akzeptiert jeden Status von 200 bis 399
Deployment minimum 100 %, maximum 200 % (Standardwerte, nicht gesetzt)maxUnavailable 0, maxSurge 3StackToIT leitet beides für drei Replikate nach den Rundungsregeln von ECS ab
awslogs-Log-Treibernicht übernommenDer Container schreibt nach stdout; wohin der Cluster die Logs liefert, entscheiden Sie, zum Beispiel STACKIT Logs
launch_type FARGATE, Netzwerkmodus awsvpcnicht übernommenPods laufen im Netzwerk des Node-Pools; es gibt keine Netzwerkschnittstelle und keine Security Group pro Task

Cluster und Load Balancer

Fargate kennt keine Nodes, deshalb ist die Größe des Node-Pools eine Variable, die Sie aus den Task-Größen ableiten, die der Bericht summiert (für diesen Service 1,5 vCPU und 3 GiB an Untergrenze und Obergrenze). Der Load Balancer erreicht die Pods über einen NodePort-Service auf Port 30000, mit den Node-Adressen als Pool-Zielen.

STACKIT-Terraform von StackToITterraform/kubernetes.tf
resource "stackit_ske_cluster" "shop" {
  project_id = var.project_id
  name       = "shop"
  node_pools = [{
    name               = "workloads"
    machine_type       = var.shop_machine_type
    minimum            = var.shop_nodes_min
    maximum            = var.shop_nodes_max
    availability_zones = var.availability_zones
  }]
}
STACKIT-Terraform von StackToITterraform/loadbalancing.tf (Target Pool)
  target_pools = [{
    name        = "web"
    target_port = 30000
    targets     = [for ip in var.web_target_ips : { ip = ip }]
    active_health_check = {
      healthy_threshold   = var.web_health_healthy_threshold
      interval            = var.web_health_interval
      interval_jitter     = var.alb_interval_jitter
      timeout             = var.web_health_timeout
      unhealthy_threshold = var.web_health_unhealthy_threshold
      http_health_checks = {
        ok_status = var.web_health_ok_status
        path      = "/healthz"
      }
    }
  }]
Kubernetes-Entwurf von StackToITterraform/kubernetes/web/manifests.yaml (Service)
apiVersion: v1
kind: Service
metadata:
  name: web-nodeport
  labels:
    app.kubernetes.io/name: web
spec:
  type: NodePort
  selector:
    app.kubernetes.io/name: web
  ports:
  - name: p8080-tcp
    port: 8080
    targetPort: 8080
    protocol: TCP
    nodePort: 30000

Entscheiden, wie der Traffic die Pods erreicht

Option laut PlanBedeutungWas es Sie kostet
NodePort hinter dem erzeugten Load Balancer (der Entwurf)Ein NodePort-Service und ein Target Pool aus den Node-IPsSie halten die Node-Adressen aktuell, wenn der Pool skaliert; Load Balancer und Nodes müssen im selben Netzwerk liegen
Ein Ingress-Controller hinter dem Load BalancerEin Controller wie ingress-nginx routet per Ingress-Regeln zu ClusterIP-ServicesSie installieren und betreiben den Controller; der Entwurf schreibt weder ihn noch die Ingress-Regeln
Die SKE-Erweiterung ALB IngressWird über die SKE-API am Cluster aktiviert; das Anlegen einer IngressClass stellt einen verwalteten Application Load Balancer bereit, und die Ingress-Objekte dieser Klasse legen seine Routen festStand November 2026 nur auf Anfrage über den STACKIT Support erhältlich, als Opt-in-Funktion, die sich ohne Ankündigung ändern kann und die STACKIT nicht für den Produktivbetrieb empfiehlt; der erzeugte Load-Balancer-Block wird nicht angewendet

Die Checkliste, die den Workload zurückhält

applications/web.json meldet den Workload als nicht bereit und führt drei blockierende Punkte (Umgebungswert, Secret, Smoke-Test). Die Workload gilt erst als bereit, wenn Ihr Team sie in der Entscheidungsdatei abhakt; StackToIT deployt nichts und führt keinen Test aus.

Anwendungs-Checklisteterraform/applications/web.json (readiness)
  "readiness": "NOT_READY",
  "readiness_words": "Checklist items are open: StackToIT lists the work and counts an item done only when the customer marks it in the decisions file (application_checklists); StackToIT never deploys the application.",

Was Sie vor dem Anwenden ändern

Der Entwurf ist ein Ausgangspunkt. Diese Änderungen und Antworten verlangt der Demo-Lauf.

  • Dem Cluster eine Größe geben

    Maschinentyp sowie minimale und maximale Node-Anzahl setzen. Das Maximum muss mindestens der Zahl der Zonen entsprechen; standardmäßig sind drei Zonen gewählt.

  • Den Load Balancer platzieren

    Der Quell-Load-Balancer überspannt zwei Subnetze, die auf STACKIT getrennte Netzwerke sind. Seine Ziele sind die Cluster-Nodes, deshalb platziert ihn der Entwurf in dem Netzwerk, das SKE für den Cluster anlegt. Der Provider exportiert weder dieses Netzwerk noch die Node-Adressen: Sie wenden zuerst den Cluster an und setzen danach Netzwerk-ID und Node-IPs.

  • Das Zertifikat hochladen

    Der HTTPS-Listener nennt eine Zertifikats-ARN. Die ARN wird nicht umgesetzt: Zertifikat bei STACKIT hochladen und die ID in der Listener-Variable übergeben.

  • Zugriff einschränken

    Die Quelle lässt jede IPv4-Adresse auf Port 443 zu, der erzeugte Load Balancer ebenso. Entscheiden Sie, ob ein erlaubter Quellbereich geschrieben wird.

  • Die Netzwerkrichtlinie schreiben

    Die Security Group der Tasks wird nicht auf Pods übertragen. Der Plan nennt als Optionen eine NetworkPolicy, eine Security Group an den Nodes oder den Verzicht auf Segmentierung.

  • ConfigMap und Secret füllen

    APP_ENV in die ConfigMap eintragen, web-secrets mit DATABASE_URL anlegen und prüfen, ob die Nodes die Image-Registry erreichen.

Fragen aus den Teams

Kann ich Fargate-artige Task-Größen auf SKE beibehalten?

Fargate gibt es auf STACKIT nicht. Die Pods laufen im Node-Pool; aus den Task-Größen werden Requests und Limits der Container, und der Node-Pool wird aus deren Summe plus System-Pods und Surge beim Rolling Update dimensioniert.

Wendet StackToIT die Manifeste auf meinen Cluster an?

Nein. Es schreibt Manifeste, Terraform und Ausführungsplan. Ihr Team wendet sie nach den beantworteten Entscheidungen mit der Kubeconfig des Clusters an.

Was passiert mit der Task-Rolle meiner Anwendung?

Die Demo-Umgebung hat nur eine Execution-Rolle. Der Entwurf macht daraus einen STACKIT-Service-Account ohne Berechtigungen, denn für die Rolle des Plattform-Agenten, der Images zieht und Secrets einspielt, findet der Lauf kein STACKIT-Gegenstück. Weder diese Rolle noch eine Task-Rolle kommt in den Pods an: Es wird kein ServiceAccount und keine Workload-Identität erzeugt. Wie Images gezogen werden und wie sich die Anwendung authentifiziert, entscheiden Sie.

Wie mache ich nach dem Cutover einen Rollback?

Der Kopf des Manifests beschreibt es: Der ECS-Service bleibt in Betrieb, Sie leiten den Traffic dorthin zurück. Die Pods können angewendet bleiben; ECS wird erst herunterskaliert und gelöscht, nachdem die Pods die Last über den von Ihnen gewählten Zeitraum getragen haben.

Quellen

Ihr nächster Schritt: STACKIT.

Erzählen Sie uns von Ihrer Umgebung. Wir zeigen Ihnen, was StackToIT dafür liefert: Zielarchitektur, Terraform-Artefakte und einen strukturierten Migrationsplan.