AMAZON EC2 → STACKIT COMPUTE ENGINE · TUTORIAL

Amazon EC2 zu STACKIT Compute Engine, praktisch

Dieses Tutorial führt einen Webserver vom AWS-Terraform zu einem STACKIT-Entwurf. Sie starten mit acht Ressourcen, führen einen Befehl aus und lesen das Ergebnis: einen stackit_server, ein stackit_volume, Security-Group-Regeln, eine öffentliche IP und ein Dokument zur Kopie des Datenträgers. Der letzte Abschnitt nennt, was Sie ändern, bevor irgendetwas angewendet wird.

Das Tutorial in fünf Schritten

Alles unten entstand am 4. November 2026 aus einer für diese Seite geschriebenen Umgebung.

  1. 1. Das Terraform in einen Ordner legen

    Die Beispielumgebung hat eine VPC, ein Subnetz, eine Security Group, ein Schlüsselpaar, eine Instanz vom Typ m6i.large mit 40-GiB-gp3-Root-Disk, ein verschlüsseltes 200-GiB-Datenvolume mit Attachment und eine Elastic IP.

  2. 2. Die Bewertung ausführen

    Der Befehl lautet stacktoit assess ./ec2-demo. Er liest das Terraform offline, bewertet sieben Einheiten und schreibt den Berichtsordner. Er ruft weder AWS auf noch verändert er etwas in STACKIT.

  3. 3. Die Klassen lesen

    Zwei Einheiten sind DIRECT (Schlüsselpaar und Elastic IP), fünf RECONFIGURE (VPC, Subnetz, Security Group, Instanz, Volume). Keine verlangt ein Redesign.

  4. 4. Entwurf und Datenkopie-Dokument lesen

    Der Ordner terraform enthält den Entwurf. Der Ordner handover enthält eine Konnektivitäts-Checkliste für den Server und ein Dokument zur Kopie des Datenträgers.

  5. 5. Die offenen Eingaben beantworten

    Nennen Sie Image, Maschinentyp und Performance-Klasse, prüfen Sie das Startskript, entscheiden Sie über die Egress-Vorgabe und führen Sie den Lauf erneut aus, bis im Bericht kein Wert mehr fehlt.

Die Instanz und ihr Datenvolume

Links die EC2-Instanz, das EBS-Volume und das Attachment. Rechts die Ressourcenblöcke des Entwurfs mit zwei ihrer Kommentarzeilen, den „NOT CARRIED“-Hinweisen zum Typ gp3 und zum Gerätenamen; die übrigen Prüfkommentare der Datei sind ausgelassen. Beachten Sie die drei Variablen: Image, Maschinentyp und Performance-Klasse wählen Sie.

Beispieleingabemain.tf
resource "aws_instance" "web" {
  ami                    = "ami-0abcdef1234567890"
  instance_type          = "m6i.large"
  subnet_id              = aws_subnet.app.id
  vpc_security_group_ids = [aws_security_group.web.id]
  key_name               = aws_key_pair.ops.key_name

  root_block_device {
    volume_size = 40
    volume_type = "gp3"
  }

  user_data = <<-EOT
    #!/bin/bash
    systemctl enable --now nginx
  EOT

  tags = {
    Name = "web-01"
  }
}

resource "aws_ebs_volume" "data" {
  availability_zone = "eu-central-1a"
  size              = 200
  type              = "gp3"
  encrypted         = true
  tags = {
    Name = "web-01-data"
  }
}

resource "aws_volume_attachment" "data" {
  device_name = "/dev/sdf"
  volume_id   = aws_ebs_volume.data.id
  instance_id = aws_instance.web.id
}
STACKIT-Terraform von StackToITterraform/compute.tf
# NOT CARRIED (aws_instance.web): root_block_device.volume_type = gp3 — the boot volume's performance is a STACKIT performance class (boot_volume.performance_class, pinned provider): AWS volume types, IOPS and throughput do not map — not generated, choose the class.
resource "stackit_server" "web" {
  project_id        = var.project_id
  name              = "web-01"
  machine_type      = var.web_machine_type
  availability_zone = var.availability_zone
  boot_volume = {
    source_type           = "image"
    source_id             = var.web_image_id
    size                  = 40
    delete_on_termination = true
  }
  keypair_name       = stackit_key_pair.ops.name
  user_data          = var.web_user_data
  network_interfaces = [stackit_network_interface.web.network_interface_id]
  labels = {
    Name = "web-01"
  }
}

# NOT CARRIED (aws_volume_attachment.data): device_name = /dev/sdf — stackit_server_volume_attach has no device name (pinned provider); find the volume in the guest by its ID, not by the device path.
resource "stackit_volume" "data" {
  project_id        = var.project_id
  name              = "web-01-data"
  availability_zone = var.availability_zone
  size              = 200
  performance_class = var.data_performance_class
  labels = {
    Name = "web-01-data"
  }
}

resource "stackit_server_volume_attach" "data" {
  project_id = var.project_id
  server_id  = stackit_server.web.server_id
  volume_id  = stackit_volume.data.volume_id
}
  • Boot-Volume

    Die Root-Größe von 40 GiB wird übernommen, der Typ gp3 nicht: STACKIT steuert die Leistung über eine Performance-Klasse, deshalb fragt der Lauf nach Ihrer Wahl.

  • Image statt AMI

    Eine AMI-ID bedeutet auf STACKIT nichts. Der Entwurf nimmt eine STACKIT-Image-ID als Variable, denn welches Image Ihrer AMI entspricht, entscheiden Sie.

  • Startskript zurückgehalten

    Das user_data wird nicht in den Entwurf kopiert. Der Lauf deklariert dafür eine sensible Variable und verlangt, das Skript zuerst zu prüfen, weil solche Skripte häufig AWS-APIs aufrufen oder die EC2-Metadatenpfade lesen.

  • Attachment ohne Gerätenamen

    stackit_server_volume_attach kennt keinen Gerätenamen; Sie finden den Datenträger im Gast über Größe und Seriennummer.

Die Security Group, Regel für Regel

Die beiden Ingress-Regeln werden eins zu eins übernommen. Die Egress-Regel der Quelle (jeder Verkehr überallhin) wird nicht kopiert: Das Subnetz hatte keine Route ins Internet, deshalb beschränkt der Lauf ausgehenden Verkehr mit einer eigenen Egress-Gruppe auf den VPC-Bereich und schreibt zwei API-Aufrufe, die die Allow-all-Egress-Regeln von STACKIT löschen.

Beispieleingabemain.tf
resource "aws_security_group" "web" {
  name        = "web-sg"
  description = "HTTPS from the internet, SSH from the office"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["203.0.113.0/24"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
STACKIT-Terraform von StackToITterraform/security.tf
resource "stackit_security_group" "web" {
  project_id  = var.project_id
  description = "HTTPS from the internet, SSH from the office"
  name        = "web-sg"
}

resource "stackit_security_group_rule" "web_ingress_1" {
  project_id        = var.project_id
  security_group_id = stackit_security_group.web.security_group_id
  direction         = "ingress"
  ether_type        = "IPv4"
  ip_range          = "0.0.0.0/0"
  port_range = {
    max = 443
    min = 443
  }
  protocol = {
    name = "tcp"
  }
}

resource "stackit_security_group_rule" "web_ingress_2" {
  project_id        = var.project_id
  security_group_id = stackit_security_group.web.security_group_id
  direction         = "ingress"
  ether_type        = "IPv4"
  ip_range          = "203.0.113.0/24"
  port_range = {
    max = 22
    min = 22
  }
  protocol = {
    name = "tcp"
  }
}
  • Geschlossener Egress ist eine Vorgabe, die Sie bestätigen

    Der Entwurf erlaubt ausgehenden Verkehr nur in den VPC-Bereich, mehr konnte das Quell-Subnetz nicht erreichen. Die Entscheidung bleibt offen, bis Sie sie in decisions.yaml beantworten; drei automatisierte Schritte beruhen auf dieser Vorgabe. Solange die Allow-all-Regeln nicht gelöscht sind, gelten sie neben der eingeschränkten Gruppe, und nichts ist beschränkt.

  • Regeln nennen Bereiche, keine AWS-Objekte

    Eine Security-Group-Regel, die auf eine AWS-Präfixliste oder einen VPC-Bereich zeigte, muss mit STACKIT-Netzwerkpräfixen neu geschrieben werden.

Was der Lauf schreibt und wo Sie es lesen

Pfade sind relativ zum Ausgabeordner des Laufs.

Datei oder OrdnerInhaltLesen Sie es, wenn
assessment.jsonJede Einheit mit Klasse, Konfidenz, Ziel und BegründungSie die Zuordnung prüfen
terraform/compute.tf, network.tf, security.tfDie Ressourcenblöcke des Entwurfs mit PrüfkommentarenSie den Plan vorbereiten
terraform/handover/server-web/Eine Konnektivitäts-Checkliste für den Servervor dem Cutover
terraform/handover/volume-data/data-copy.mdDie Schritte zur Kopie des DatenträgersSie das Datenfenster planen
execution/api/iaas/Zwei Skripte, die die Allow-all-Egress-Regeln löschenSie die Egress-Vorgabe bestätigen
migration/technical-sequencing.mdVier Wellen in AbhängigkeitsreihenfolgeSie die Arbeit terminieren
execution/manual/actions.md29 manuelle Schritte in 19 ArbeitspaketenSie die Migration personell planen

Den Datenträger kopieren: Verfahren und Prüfungen

Das Datenkopie-Dokument legt eine dateibasierte Kopie mit rsync über SSH zwischen den beiden Servern fest, nach dem Verfahren, das die Block-Storage-Anleitung von STACKIT beschreibt, mit eigenem Schlüssel und gestoppten Diensten für den letzten Durchlauf. Unten stehen zwei seiner Prüfungen nach der Übertragung, unverändert: Dateien und Bytes auf beiden Seiten zählen, dann den Inhalt per Prüfsumme vergleichen. StackToIT führt keinen dieser Befehle aus; Ihr Team tut es nach einer Generalprobe.

Zählung auf beiden Seitenterraform/handover/volume-data/data-copy.md
find <target-mount> -type f | wc -l
du -sb <target-mount>
find <source-mount> -type f | wc -l
du -sb <source-mount>
Inhalt auf beiden Seitenterraform/handover/volume-data/data-copy.md
rsync -aHAX --numeric-ids -nc --itemize-changes -e ssh <user>@<source-host>:<source-mount>/ <target-mount>/
sha256sum <large-file> <one-file-per-top-level-directory>
  • Erster Durchlauf bei laufender Quelle

    Die Kopie selbst ist rsync -aHAX --numeric-ids -e ssh vom Quell- auf den Ziel-Mountpoint, ausgeführt auf dem Ziel. Der erste Durchlauf ist nicht konsistent, weil die Quelle weiterschreibt; der letzte Durchlauf mit demselben Befehl läuft in einem Schreibstopp, den Sie festlegen. Der Lauf vermerkt, dass die rsync-Zeile auf der STACKIT-Anleitung fehlerhaft abgedruckt ist, und übernimmt die Syntax aus dem rsync-Handbuch.

  • Größeneinheit prüfen

    Der Lauf übernimmt 200 als Zahl. STACKIT gibt die Volume-Größe in GB an, ohne zu sagen, ob GiB gemeint sind; sind es 10^9 Byte, ist das Volume rund 7 % kleiner. Das Dokument verlangt daher, vor dem ersten Durchlauf die nutzbare Größe am Ziel mit lsblk -b gegen den belegten Platz der Quelle zu prüfen.

  • Rückweg

    Behalten Sie Quellinstanz, Volume und Elastic IP, bis das Ziel verifiziert ist. Nach dem Cutover am Ziel geschriebene Daten werden mit demselben Befehl in Gegenrichtung zurückkopiert oder als verloren akzeptiert; das ist eine Entscheidung.

Das ändern Sie vor dem Anwenden

Der Entwurf ist ein Vorschlag. Diese Werte und Entscheidungen liegen zwischen ihm und einem Plan.

  • project_id, Image, Maschinentyp

    Drei Variablen ohne Standardwert. m6i.large hat etwa 2 vCPU und 8 GiB, also ein Verhältnis von 1:4. Die Maschinentyp-Liste von STACKIT gibt der General-Familie (g) dasselbe Verhältnis 1:4, und die Zahl nach Familie und Generation nennt die vCPU-Anzahl. Beginnen Sie also mit einem g-Typ mit 2 vCPU und prüfen Sie ihn in der Liste.

  • data_performance_class

    Wählen Sie die Klasse für das Datenvolume; die Variable listet die Klassen aus dem Katalog, den der Lauf gelesen hat.

  • web_user_data

    Prüfen Sie das Startskript, entfernen Sie AWS-spezifische Aufrufe und übergeben Sie es als Cloud-init.

  • Elastic IP zu öffentlicher IP

    Die öffentliche IP ist eine neue Adresse. DNS-Namen und Freigabelisten, die auf die alte zeigten, werden beim Cutover umgestellt; senken Sie die TTL rechtzeitig.

  • Private DNS und Routen

    Der Lauf vermerkt, dass die private Namensauflösung des AWS-Resolvers nicht nachgebildet wird und dass das Routing des Subnetzes eine Entscheidung Ihres Netzwerkteams ist.

Fragen von Plattformteams

Kann ich meine AMI in STACKIT importieren?

Der Entwurf nimmt eine STACKIT-Image-ID: ein öffentliches Image oder ein hochgeladenes raw- oder qcow2-Image. Verlassen Sie sich nicht darauf, die AMI mit VM Import/Export exportieren zu können: AWS dokumentiert den Export nur für eine VM, die zuvor aus Ihrer eigenen Umgebung importiert wurde. Für die meisten Server ist der praktische Weg ein öffentliches STACKIT-Image plus das Cloud-init-Skript; das Datenvolume wird getrennt kopiert.

Wird das Verschlüsselungsflag meines EBS-Volumes übernommen?

Nicht als Einstellung. Der Lauf vermerkt, dass STACKIT Verschlüsselung im Ruhezustand für Block Storage dokumentiert und dass ein kundeneigener Schlüssel eine eigene Anforderung ist; für das Flag wird daher nichts erzeugt.

Stoppt StackToIT den Server oder kopiert den Datenträger?

Nein. StackToIT liest Terraform und schreibt Dateien. Jeder Befehl im Datenkopie-Dokument wird von einer Person ausgeführt.

Warum verlangt der Entwurf, Egress-Regeln per API zu löschen?

Weil das Quell-Subnetz nur den VPC-Bereich erreichte und der Entwurf das beibehält. STACKIT legt standardmäßig Allow-all-Egress-Regeln an; die zwei Skripte entfernen sie und laufen erst, wenn Sie eine Bestätigungsvariable setzen.

Wie lange dauert die Kopie?

Das kann der Lauf nicht wissen. Datenmenge und Änderungsrate stehen nicht im Terraform, daher verlangt das Dokument, die Dauer einer Generalprobe zu messen.

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.