Zum Inhalt springen
Beta

Relocate to STACKIT: VMware mit Coriolis migrieren

Zuletzt aktualisiert am

Stackit LogoStackit Logo
STACKIT

Relocate to STACKIT: VMware mit Coriolis migrieren

Migrieren Sie VMware-VMs mit Coriolis nach STACKIT: Endpoints vorbereiten, Zieldisks synchronisieren, neue VMs bereitstellen und prüfen sowie Cutover und Übergabe abschließen.

PLAN

Transfer und Deployment verstehen

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
PLAN

Migrationsobjekte unterscheiden

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
SAFE

Zugriffe und Berechtigungen vorbereiten

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
BASE

Migrationsnetzwerke verbinden

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
STEP

VM und Zielumgebung vorbereiten

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
PLAN

Betriebseingaben festlegen

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
SAFE

An Coriolis authentifizieren

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
PLAN

Provider und Worker auswählen

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
BASE

Plattform-Endpoints konfigurieren

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
AUTO

Zieldisks aufbauen und synchronisieren

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
LIVE

Neue STACKIT-VM erstellen

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
SAFE

Test-VM validieren

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
AUTO

Quelländerungen synchronisieren

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
LIVE

Einfrieren, synchronisieren und umschalten

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen
GOAL

Migrierten Workload übergeben

Coriolis kopiert VMware-VM-Disks nach STACKIT, passt das Gastbetriebssystem an die virtuelle Zielhardware an und startet die migrierte VM in einem STACKIT-Projekt. Anwendung und Datenbank bleiben in der VM. Dies ist eine Relocate-Migration, kein Neuaufbau der Anwendung und kein Wechsel zu einer verwalteten Datenbank.

Folgen Sie dieser Reihenfolge: Quelle und Ziel vorbereiten, Coriolis mit beiden Plattformen verbinden, Disks übertragen, ein isoliertes Ziel testen, Änderungen synchronisieren und den finalen Cutover durchführen. Die API-Beispiele verwenden curl und jq; die Python-Helfer des Beispiel-Repositorys sind nicht erforderlich.

Coriolis trennt Diskdaten übertragen von einer neuen Ziel-VM bereitstellen. Ein Transfer definiert Quelle und Zieleinstellungen. Jede Execution schreibt die vollständigen Diskdaten oder später geänderte Blöcke auf Ziel-Volumes. Eine abgeschlossene Kopie startet noch keine Anwendungs-VM.

Ein Deployment verwendet den übertragenen Diskzustand, klont ihn für die Test- und finalen Server dieser Anleitung, passt das Gastbetriebssystem an und erstellt einen neuen STACKIT-Server. Es bildet den Workload auf neuer virtueller Hardware ab; weder das ursprüngliche ESXi-VM-Objekt noch dessen CPU-/RAM-Hardware werden unverändert verschoben. Das Quell-Sizing ist die Grundlage für eine ausdrückliche Zuordnung zu einem STACKIT-Maschinentyp.

VMware-Quelle1. Datentransfer2. VM-BereitstellungLaufende VMAnwendung + DatenbankQuell-VMDKsErstkopie + Delta-ExecutionsSynchronisierte STACKIT-VolumesGeklonte Deployment-VolumesGast-OS / VirtIO / Boot anpassenNeue STACKIT-VMZugeordnete CPU + RAM, NICs, Firmware Quelldisks lesenDeployment-Anfrage

Ein vorhandenes geklontes Test-Deployment bildet einen bestimmten Zeitpunkt ab. Spätere Executions aktualisieren die übertragenen Volumes, nicht die Disks dieser Test-VM. Erstellen Sie ein neues Deployment, um eine neuere Synchronisation zu testen. Mit auto_deploy: false fordern Sie jede Disk-Synchronisation und jede VM-Erstellung ausdrücklich getrennt an.

Das Beispiel verwendet scf-relocate-app: Ubuntu 24.04, Spring Boot und PostgreSQL 16 in einer VM mit 12-GiB-Systemdisk und 8-GiB-Datenbankdisk. Für andere unterstützte VMs verwenden Sie dieselben Coriolis-Vorgänge, aber deren Betriebssystem, Kapazität, Netzwerke und Anwendungsabnahmetests.

  1. Stellen Sie eine lizenzierte Coriolis-Appliance mit VMware- und STACKIT-Providern bereit. Nutzen Sie den Coriolis STACKIT Installer für die Bereitstellung auf STACKIT.
  2. Prüfen Sie ESXi-/vCenter-Version, Gastbetriebssystem und Diskaufbau anhand der Support-Matrix der installierten Provider. Die VMware-Lizenz muss API-Snapshots, CBT und Diskexport erlauben.
  3. Erstellen Sie einen dedizierten VMware-Migrationsaccount und einen STACKIT-Service-Account. Gewähren Sie benötigte Inventar-, Snapshot-, CBT-, Export- und Datastore-Rechte auf den betroffenen VMs/Datastores. Der STACKIT-Account benötigt Zugriff auf das Zielprojekt und Berechtigungen zum Erstellen und Verwalten von Migrationsservern, Volumes, NICs und Security Groups.
  4. Bereiten Sie Zielkapazität, Netzwerke, Quoten und eine isolierte Testumgebung vor.
  5. Definieren Sie Wartungsfenster, Anwendungsabnahme, Verkehrsumschaltung und Rollback-Verantwortung. Bewahren Sie Quell-VM und Backups bis zum Ende des Aufbewahrungszeitraums auf.

Die Anfragen verwenden das Transfer-/Deployment-API-Profil der Coriolis-2608.2-Appliance und ihrer VMware-/STACKIT-Provider. Lesen Sie vor der Erstellung die installierten Provider-Schemas; sie definieren gültige Felder. Diese Anleitung verwendet Transfers, nicht den separaten Replica-/DR-Ablauf.

Für Server-Agent-Prüfungen aktivieren Sie STACKIT Agent Service einmal pro Zielprojekt und installieren/provisionieren danach den Agent im Zielgast. Projektaktivierung und Gastbereitstellung sind separate Vorgänge. SSH-basierte Validierung benötigt keinen Server Agent.

BetriebsteamVMware-UmgebungCoriolis-ApplianceSTACKIT-ZielprojektvCenter / ESXiQuell-VM: OS, Anwendung, DatenbankREST-API und AuftragsplanungCoriolis-WorkerTemporärer Migrations-WorkerÜbertragene VolumesMigrierte Anwendungs-VM HTTPS: Endpoints, Transfers, DeploymentsAufgaben planenAPI 443 und Diskexport 902Snapshots und DiskzugriffSSH 22 und HTTPS-Transfer 5566Transferdisks schreibenKlonen, anpassen und bereitstellen

Routen Sie den Coriolis-Worker zum privaten Migrationsnetzwerk. Im selben STACKIT-Projekt können Sie ein angeschlossenes Netzwerk oder eine freigegebene geroutete Verbindung nutzen. Für eine lokale Appliance verwenden Sie Standort-VPN oder private Anbindung. Das VPN stellt Erreichbarkeit her, ist aber kein Coriolis-Migrationsmechanismus. Ein bestimmtes VPN-Produkt oder Zwischenhost ist nicht erforderlich.

Halten Sie temporäre Worker privat. Beschränken Sie Worker-Zugriffe auf Coriolis und administrative Zugriffe auf freigegebene Quellen. Verbinden Sie Test-VMs weder mit produktivem Verkehr noch mit identitätssensitiven Diensten.

Verwenden Sie auf dem Arbeitsplatz Bash, curl, jq und vertrauenswürdige TLS-Zertifikate. Für optionale Server-Agent-Befehle installieren Sie die offizielle STACKIT CLI. Deaktivieren Sie keine Zertifikatsprüfung. Halten Sie Authentifizierungsdateien und API-Antworten privat und außerhalb von Git. Nutzen Sie eine dedizierte Bash-Sitzung und stoppen Sie bei fehlgeschlagenen Anfragen, statt mit leeren oder veralteten Kennungen fortzufahren.

Terminal-Fenster
set -euo pipefail
umask 077
WORK="$HOME/coriolis-migration"
mkdir -p "$WORK"
chmod 700 "$WORK"
CORIOLIS_URL='https://coriolis.example.com'
CORIOLIS_USER='migration-operator'
CORIOLIS_PROJECT='admin'
CORIOLIS_PASSWORD_FILE="$HOME/.config/coriolis/password"
VMWARE_HOST='vcenter.example.com'
VMWARE_USER='migration-user@vsphere.local'
VMWARE_PASSWORD_FILE="$HOME/.config/coriolis/vmware-password"
STACKIT_KEY_FILE="$HOME/.config/stackit/service-account.json"
STACKIT_ORGANIZATION_ID='replace-with-organization-uuid'
STACKIT_PROJECT_ID='replace-with-project-uuid'
STACKIT_REGION='eu01'
STACKIT_AVAILABILITY_ZONE='eu01-1'
MIGRATION_NETWORK_ID='replace-with-migration-network-uuid'
TARGET_NETWORK_ID='replace-with-application-network-uuid'
TARGET_SECURITY_GROUP_ID='replace-with-application-security-group-uuid'
WORKER_IMAGE_ID='replace-with-ubuntu-worker-image-uuid'
WORKER_MACHINE_TYPE='c3i.2'
TARGET_MACHINE_TYPE='c3i.2'
SOURCE_NETWORK='VM Network'

Ersetzen Sie vor der Ausführung alle Beispielhostnamen, Nutzernamen und replace-with-...-Werte:

Die API liefert CORIOLIS_PROJECT_ID, WORKER_REGION_ID, SOURCE_ENDPOINT_ID, TARGET_ENDPOINT_ID, VM_ID, TRANSFER_ID, EXECUTION_ID und DEPLOYMENT_ID. Erfinden Sie keine IDs und ersetzen Sie sie nicht durch den Anzeigenamen einer VM. TARGET_SERVER_ID ist die UUID des erzeugten STACKIT-Servers. Das Beispiel nutzt ein Zielnetzwerk für Worker und isolierte Anwendung; bei getrennter Landing-Zone-Architektur verwenden Sie unterschiedliche Netzwerk-IDs. Deaktivieren Sie Shell-Tracing und ausführliche HTTP-Protokollierung bei Authentifizierungsvorgängen.

Migrieren Sie den vorhandenen Gast; installieren Sie OS, Anwendung oder Datenbank nicht als Vorbereitung neu. Erfassen Sie VM-Kennungen, vCPU/RAM, Firmware, Disks, Mounts, Netzwerkadapter, Accounts, Anwendungsdienste und Datenabhängigkeiten. Erstellen und prüfen Sie ein anwendungskonsistentes Backup.

Für das Beispiel erfassen Sie dieses Quellinventar:

Diese Namen, Pfade und Endpoints gehören zum Beispiel. Erfassen Sie für andere Workloads deren Entsprechungen und fachliche Abnahmetests. Coriolis setzt weder Spring Boot noch PostgreSQL, eine leere Datendisk oder einen bestimmten VM-Namen voraus.

Erfassen Sie vor der Erstkopie den Anwendungszustand und einen Konsistenzpunkt. Stoppen Sie im dedizierten Beispiel den synthetischen Schreiber und sichern Sie unabhängige SQL-/HTTP-Nachweise. Führen Sie die Befehle im Quellgast aus, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo systemctl stop relocate-writer.timer relocate-writer.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

GUEST_EVIDENCE ist ein privates Ausgabeverzeichnis im Gast. Bewahren Sie Quellnachweise auf, ohne sie bei der Zielabnahme zu überschreiben. Halten Sie den Beispielschreiber während Erstkopie und Test-Deployment gestoppt. Vereinbaren Sie für produktive Anwendungen Backup/Konsistenzpunkt und Vergleichsverfahren mit den Verantwortlichen; berücksichtigen Sie Schreibzugriffe während der Online-Kopie.

Erstellen und entfernen Sie mit dem dedizierten Account einen Test-Snapshot der ausgewählten VM. Prüfen Sie Datastore-Reserve, Snapshot-Konsolidierung und laufende VMware Tools. Aktivieren Sie CBT für VM/Disks vor dem ersten Transfer nach dem freigegebenen VMware-Verfahren. Hier ist automatically_enable_cbt: false gesetzt, weil CBT ausdrücklich vorbereitet wird.

Die Quell-VM braucht eine stabile Kennung und muss im Coriolis-Inventar erscheinen. Beheben Sie fehlende Kennungen, nicht unterstützte Versionen oder Exportfehler vor der Kopie. Ändern Sie VM-Identitäten oder Provider-Bibliotheken nicht als allgemeinen Migrationsschritt.

Bereiten Sie Zielprojekt, Netzwerke und Security Groups entsprechend der Eingabetabelle vor. Reservieren Sie Kapazität für übertragene Volumes, temporäre Worker sowie Test-/finale Server. Bereiten Sie ein Worker-Image mit cloud-init vor und prüfen Sie Maschinentypen und Zone.

Vervollständigen Sie Routing und Firewall-Regeln aus der Architekturtabelle vor der Endpoint-Konfiguration. Prüfen Sie die Wege vom Coriolis-Worker, nicht nur vom Browser-Arbeitsplatz. Die Weboberfläche ist eine Steuerungsverbindung und transportiert nicht sämtlichen Diskverkehr.

Ermitteln Sie Identitäts- und Migrations-API-Pfade. Der konfigurierte HTTPS-Ursprung ist derselbe wie für die Weboberfläche:

Terminal-Fenster
curl --fail --silent --show-error "$CORIOLIS_URL/api/config" > "$WORK/config.json"
IDENTITY_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.keystone' "$WORK/config.json")"
CORIOLIS_API_URL="$CORIOLIS_URL$(jq -er '.config.servicesUrls.coriolis' "$WORK/config.json")"
USER_DOMAIN=$(jq -er '.config.defaultUserDomain' "$WORK/config.json")

Erstellen Sie die Passwortanfrage aus der geschützten Datei und fordern Sie ein zunächst nicht projektgebundenes Keystone-Token an. Der Antwortheader X-Subject-Token enthält das Token:

Terminal-Fenster
jq -n --arg username "$CORIOLIS_USER" --arg domain "$USER_DOMAIN" \
--rawfile password "$CORIOLIS_PASSWORD_FILE" \
'{auth:{identity:{methods:["password"],password:{user:{name:$username,
password:($password|rtrimstr("\n")),domain:{name:$domain}}}},scope:"unscoped"}}' \
> "$WORK/login.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/login.json" \
-D "$WORK/unscoped.headers" -o "$WORK/unscoped.json"
UNSCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/unscoped.headers")
printf 'X-Auth-Token: %s\n' "$UNSCOPED_TOKEN" > "$WORK/unscoped-request.headers"
curl --fail --silent --show-error -H @"$WORK/unscoped-request.headers" \
"$IDENTITY_URL/auth/projects" > "$WORK/projects.json"
CORIOLIS_PROJECT_ID=$(jq -er --arg project "$CORIOLIS_PROJECT" \
'[.projects[]|select(.name==$project)]|if length==1 then .[0].id else error("Select one authorized Coriolis project") end' \
"$WORK/projects.json")

Binden Sie das Token an das ausgewählte Coriolis-Projekt. Speichern Sie den Header privat und verwenden Sie ihn für jede Migrationsanfrage. Das Token wird aus einer Datei gelesen, nicht als Kommandozeilenargument übergeben:

Terminal-Fenster
jq -n --rawfile token "$WORK/unscoped-request.headers" --arg project "$CORIOLIS_PROJECT_ID" \
'{auth:{identity:{methods:["token"],token:{id:($token|sub("^X-Auth-Token: ";"")|rtrimstr("\n"))}},
scope:{project:{id:$project}}}}' > "$WORK/scope.json"
curl --fail --silent --show-error -X POST "$IDENTITY_URL/auth/tokens" \
-H 'Content-Type: application/json' --data-binary @"$WORK/scope.json" \
-D "$WORK/scoped.headers" -o "$WORK/scoped.json"
SCOPED_TOKEN=$(awk 'tolower($1)=="x-subject-token:" {gsub("\r","",$2); print $2}' "$WORK/scoped.headers")
printf 'X-Auth-Token: %s\n' "$SCOPED_TOKEN" > "$WORK/coriolis.headers"
API="$CORIOLIS_API_URL/$CORIOLIS_PROJECT_ID"
unset UNSCOPED_TOKEN SCOPED_TOKEN

API ist die projektbezogene Migrationsbasis, beispielsweise https://coriolis.example.com/coriolis/<coriolis-project-id>. Bei 401 ist neue Authentifizierung erforderlich; prüfen Sie vor erneuter Anfrage den Zustand des bestehenden Vorgangs.

Terminal-Fenster
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/providers" > "$WORK/providers.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" "$API/regions" > "$WORK/regions.json"
jq '.regions[]|{id,name,enabled}' "$WORK/regions.json"
WORKER_REGION_ID='replace-with-enabled-coriolis-worker-region-id'
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/16" > "$WORK/vmware-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/16" > "$WORK/stackit-connection-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/vmware_vsphere/schemas/8" > "$WORK/source-environment-schema.json"
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/providers/stackit/schemas/4" > "$WORK/destination-environment-schema.json"

Wählen Sie eine aktivierte Region mit erreichbaren Quell-/Zielsystemen und setzen Sie deren ID als WORKER_REGION_ID. Public ist nur der Name einer logischen Coriolis-Worker-Gruppe und aktiviert keine öffentlichen IPs. STACKIT_REGION bleibt die Ziel-Cloud-Region. Schema 16 liefert hier Verbindungseinstellungen, 8 die VMware-Quellumgebung und 4 die STACKIT-Zielumgebung. Validieren Sie Anfragen vor dem Absenden gegen diese zurückgegebenen JSON-Schemas.

Erstellen Sie den VMware-Endpoint. host ist die vCenter- oder unterstützte Standalone-ESXi-Adresse, nicht die Gast-IP. Der Account muss alle ausgewählten VMs und zugehörigen Datastores sehen:

Terminal-Fenster
jq -n --arg host "$VMWARE_HOST" --arg username "$VMWARE_USER" \
--rawfile password "$VMWARE_PASSWORD_FILE" --arg worker "$WORKER_REGION_ID" \
'{endpoint:{name:"vmware-source",type:"vmware_vsphere",mapped_regions:[$worker],
connection_info:{host:$host,port:443,username:$username,
password:($password|rtrimstr("\n")),allow_untrusted:false}}}' > "$WORK/vmware-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/vmware-endpoint-request.json" \
"$API/endpoints" > "$WORK/vmware-endpoint.json"
SOURCE_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/vmware-endpoint.json")

Erstellen Sie den STACKIT-Endpoint. service_account_key enthält das ursprüngliche Schlüssel-JSON in Base64. Das ist Kodierung, keine Verschlüsselung; schützen Sie die Anfragedatei:

Terminal-Fenster
jq -n --arg organization "$STACKIT_ORGANIZATION_ID" --arg project "$STACKIT_PROJECT_ID" \
--arg region "$STACKIT_REGION" --arg worker "$WORKER_REGION_ID" --rawfile key "$STACKIT_KEY_FILE" \
'{endpoint:{name:"stackit-destination",type:"stackit",mapped_regions:[$worker],
connection_info:{organization_id:$organization,project_id:$project,
region_name:$region,service_account_key:($key|@base64)}}}' > "$WORK/stackit-endpoint-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/stackit-endpoint-request.json" \
"$API/endpoints" > "$WORK/stackit-endpoint.json"
TARGET_ENDPOINT_ID=$(jq -er '.endpoint.id' "$WORK/stackit-endpoint.json")

Prüfen Sie beide Verbindungen und verlangen Sie valid: true. Aktualisieren Sie danach das Quellinventar:

Terminal-Fenster
for ENDPOINT_ID in "$SOURCE_ENDPOINT_ID" "$TARGET_ENDPOINT_ID"; do
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary '{"validate-connection":null}' \
"$API/endpoints/$ENDPOINT_ID/actions" > "$WORK/validate-$ENDPOINT_ID.json"
jq -e '.["validate-connection"].valid==true' "$WORK/validate-$ENDPOINT_ID.json"
done
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/endpoints/$SOURCE_ENDPOINT_ID/instances?refresh=true&limit=100" > "$WORK/source-instances.json"
jq '.instances[]|{id,name,os_type,power_state}' "$WORK/source-instances.json"
VM_ID='replace-with-selected-instance-id-from-coriolis'

Wählen Sie die exakte zurückgegebene VM-ID, gleichen Sie sie mit dem Quellinventar ab und setzen Sie VM_ID. Bei größeren Beständen rufen Sie vor der Auswahl alle Inventarseiten ab. Speichern Sie jede Ressourcen-ID. Nach unterbrochenem POST prüfen Sie bestehende Endpoints/Aufträge, statt Duplikate zu erzeugen. Endpoint-Validierung beweist Zugangsdaten/API-Zugriff, nicht den gesamten Diskpfad.

Erstellen Sie eine Transfer-Definition für die VM. Während der Erstkopie bleibt die Quelle an; das Wartungsfenster betrifft finale Synchronisation und Umschaltung. Legen Sie Diskrichtlinie und spätere Deployment-Zuordnung jetzt fest. Beides gehört zur Migrationsdefinition, Transfer-Execution und Deployment bleiben aber getrennte Vorgänge. Ergebnis sind synchronisierte Volumes, kein gebooteter Server.

Terminal-Fenster
jq -n --arg source "$SOURCE_ENDPOINT_ID" --arg destination "$TARGET_ENDPOINT_ID" --arg vm "$VM_ID" \
--arg project "$STACKIT_PROJECT_ID" --arg source_network "$SOURCE_NETWORK" \
--arg target_network "$TARGET_NETWORK_ID" --arg migration_network "$MIGRATION_NETWORK_ID" \
--arg security_group "$TARGET_SECURITY_GROUP_ID" --arg image "$WORKER_IMAGE_ID" \
--arg worker_type "$WORKER_MACHINE_TYPE" --arg target_type "$TARGET_MACHINE_TYPE" \
--arg zone "$STACKIT_AVAILABILITY_ZONE" \
'{transfer:{scenario:"live_migration",origin_endpoint_id:$source,destination_endpoint_id:$destination,
instances:[$vm],source_environment:{export_transfer_mechanism:"openvixdisklib",
automatically_enable_cbt:false,verify_disk_integrity:true,skip_nfc_validation:false},
destination_environment:{project:$project,network_map:{($source_network):$target_network},
migr_network:$migration_network,migr_machine_type:$worker_type,machine_type:$target_type,
availability_zone:$zone,migr_image_map:{linux:$image},set_dhcp:true,
migr_worker_use_public_ip:false,use_public_ip:false,preserve_fixed_ips:false,
retain_user_credentials:true,security_groups:[$security_group],data_transfer_mechanism:"HTTPS",
volumes_are_zeroed:false,delete_disks_on_server_termination:false},
network_map:{($source_network):$target_network},clone_disks:true,skip_os_morphing:false}}' \
> "$WORK/transfer-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/transfer-request.json" \
"$API/transfers" > "$WORK/transfer.json"
TRANSFER_ID=$(jq -er '.transfer.id' "$WORK/transfer.json")

Die Anfrage konfiguriert Linux-Gäste. Für Windows richten Sie Windows-Worker/Image und VirtIO-Treiber des Providers ein und nutzen Windows-Abnahmetests. Trennen Sie Transfers bei unterschiedlichem Sizing oder Gastregeln. Für Wellen nehmen Sie alle ausgewählten IDs in instances auf und koordinieren den finalen Schreibstopp je Anwendungsabhängigkeitsgruppe.

Erstellen Sie eine Execution des Transfers. shutdown_instances: false belässt Quellsteuerung bei Ihnen; auto_deploy: false trennt Diskkopie und Zielstart:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/initial-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/initial-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/initial-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/initial-status.json"

Wiederholen Sie die GET-Statusabfrage bis zum Endzustand. Fahren Sie erst fort, wenn Execution, Replikation und DELETE_TRANSFER_SOURCE_RESOURCES / DELETE_TRANSFER_TARGET_RESOURCES jeweils COMPLETED sind. Die Bereinigung entfernt temporäre Transferressourcen, nicht die Quell-VM. Beheben Sie ERROR und prüfen Sie Bereinigung vor einer weiteren Execution desselben Transfers. Bei verlorener POST-Antwort listen Sie dessen Executions auf und ermitteln die ID; wiederholen Sie POST nicht ohne Abgleich des Ergebnisses.

Erstellen Sie aus dem vollständig übertragenen Diskzustand einen neuen STACKIT-Server. Deployment erstellt Server/NICs/Volumes, bereitet Boot und Treiber durch OS Morphing vor und startet den Gast. Die Quell-VM bleibt ein separates ESXi-Objekt mit eigener Identität und eigenem Stromzustand.

Quellkonfiguration auf STACKIT-Ressourcen abbilden

Abschnitt betitelt „Quellkonfiguration auf STACKIT-Ressourcen abbilden“

Nutzen Sie Quellinventar als Ausgangspunkt und geben Sie die Zuordnung vor dem Deployment frei:

machine_type dimensioniert den finalen Server; migr_machine_type nur temporäre Worker. Ohne machine_type wählt der STACKIT-Provider einen minimal geeigneten Typ anhand der Quellanforderungen. Hier wird TARGET_MACHINE_TYPE ausdrücklich gesetzt, damit die freigegebene Zuordnung verwendet wird. Die Übertragung der Disks allein ist keine Freigabe des Zielsizings.

Erfassen Sie vor der Kopie den Quell-Datenstand. Halten Sie den synthetischen Schreiber bis zur Testabnahme gestoppt. Eine fortlaufend beschriebene produktive Datenbank braucht ein eigenes Konsistenz-/Testverfahren; Online-Diskkopie ersetzt weder konsistentes Backup noch finalen Schreibstopp.

Mit clone_disks: true entsteht ein Testserver mit separaten Deployment-Volumes, während die übertragenen Volumes für weitere Synchronisation erhalten bleiben. Halten Sie ihn von produktivem Verkehr getrennt. Erstellen Sie das Deployment erst nach bestandener Kopie und Bereinigung:

Terminal-Fenster
jq -n --arg transfer "$TRANSFER_ID" \
'{deployment:{transfer_id:$transfer,clone_disks:true,force:false,skip_os_morphing:false}}' \
> "$WORK/deployment-request.json"
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/rehearsal-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/rehearsal-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/rehearsal-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/rehearsal-status.json"

Verlangen Sie last_execution_status: COMPLETED sowie abgeschlossene Anpassungs-, Finalisierungs- und Bereinigungsaufgaben. force: false verhindert erzwungene Bereitstellung. Geklonte Disks erhalten Transferdaten für spätere Synchronisation. Der Test ist ein separates Ziel, keine produktive Umschaltung.

Ermitteln Sie erzeugte NIC-/Volume-Kennungen:

Terminal-Fenster
jq --arg vm "$VM_ID" \
'.deployment.info[$vm].instance_deployment_info|{instance_name,nic_ids,volumes_info}' \
"$WORK/rehearsal-status.json"

Ordnen Sie diese IDs in STACKIT dem tatsächlichen Server zu und speichern Sie seine UUID als TARGET_SERVER_ID. Namen sind zwischen Quelle, Tests und finalem Deployment nicht eindeutig. Prüfen Sie private Adresse, Netzwerk, Security Groups und Disks vor dem Login. Beziehen Sie den SSH-Hostschlüsselfingerabdruck über einen vertrauenswürdigen Verwaltungsweg; der Quellfingerabdruck ist kein Nachweis für den Zielhostschlüssel.

Vergleichen Sie Quellinventar und exaktes Ziel. Führen Sie Gastbefehle über freigegebenes privates SSH/Konsole oder einen provisionierten STACKIT Server Agent aus. Halten Sie Tests von produktiven Clients, geplanten Schreibern und identitätssensitiven Integrationen getrennt.

Beginnen Sie bei Linux mit diesen Standardprüfungen:

Terminal-Fenster
systemd-detect-virt
uname -r
test -d /sys/firmware/efi && printf 'EFI boot\n'
lsblk -o NAME,SIZE,FSTYPE,UUID,MOUNTPOINTS
findmnt
ip -br address
ip route
systemctl --failed --no-pager
getent passwd
getent group
ls -l /sys/class/block/vd*/device/driver /sys/class/net/*/device/driver

Setzen Sie die freigegebene SSH-Richtlinie nach retain_user_credentials durch. Im Ubuntu-Beispiel bleibt die bestehende administrative Sitzung geöffnet. Konfigurieren und prüfen Sie schlüsselbasiertes SSH vor dem Neuladen:

Terminal-Fenster
printf 'PasswordAuthentication no\n' | sudo tee /etc/ssh/sshd_config.d/00-migration-ssh.conf >/dev/null
printf 'ssh_pwauth: false\n' | sudo tee /etc/cloud/cloud.cfg.d/99-migration-ssh.cfg >/dev/null
sudo systemctl daemon-reload
sudo systemctl start ssh
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E '^(passwordauthentication|pubkeyauthentication) '
sudo systemctl reload ssh

Verlangen Sie passwordauthentication no und pubkeyauthentication yes, danach einen neuen schlüsselbasierten Login über den freigegebenen Weg. Beheben Sie widersprüchliche wirksame Regeln. Setzen Sie für die Java-Unit SuccessExitStatus=143, damit regulärer SIGTERM-Stopp als Erfolg gilt. Starten Sie die Anwendung nicht nur neu, um einen ungeklärten Fehler zu verbergen.

Prüfen Sie Dienstzustand, Lese-/Schreibverhalten, Datenkonsistenz und externe Abhängigkeiten. Erwartungswert ist der erfasste Quellzustand, nicht der Datenstand des Tests selbst. Halten Sie isolierte Abnahmeschreibzugriffe vom Vergleich mit der maßgeblichen Quelle getrennt.

Wiederholen Sie SQL-/HTTP-/Mount-Prüfungen im Zielgast, nicht auf Appliance oder Arbeitsplatz:

Terminal-Fenster
umask 077
GUEST_EVIDENCE="$HOME/migration-evidence"
mkdir -p "$GUEST_EVIDENCE"
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), count(*) FILTER (WHERE kind='seed'), count(*) FILTER (WHERE kind='write'),
md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;" \
> "$GUEST_EVIDENCE/data.txt"
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S \
> "$GUEST_EVIDENCE/api.json"
findmnt -n -o UUID --target /srv/relocate-data > "$GUEST_EVIDENCE/data-uuid.txt"
sudo -u postgres psql -d relocate -Atc 'SHOW data_directory;'

Sammeln Sie Quell-/Zielnachweise in getrennten Ordnern; überschreiben Sie den Ausgangsstand nicht. Verlangen Sie identische Gesamt-/Seed-/Write-Anzahlen, Inhaltsprüfsumme und Mount-UUID. PostgreSQL muss /srv/relocate-data/postgresql verwenden; relocate-demo.service und postgresql@16-relocate.service müssen aktiv sein. Zehn neue Quellschreibzugriffe erhöhen beispielsweise 1.004 auf 1.014 Datensätze; maßgeblich sind Ihre erfassten Zahlen, keine feste Zahl dieser Anleitung.

Prüfen Sie den Server Agent unabhängig von installierten Paketen. Authentifizieren Sie am Arbeitsplatz die offizielle CLI mit STACKIT_KEY_FILE, setzen Sie die abgeglichene Server-UUID und fordern Sie einen rein lesenden Befehl an:

Terminal-Fenster
TARGET_SERVER_ID='replace-with-matched-stackit-server-uuid'
stackit auth activate-service-account --service-account-key-path "$STACKIT_KEY_FILE"
stackit server command create --server-id "$TARGET_SERVER_ID" --project-id "$STACKIT_PROJECT_ID" \
--region "$STACKIT_REGION" --template-name RunShellScript \
--params 'script=id -u; uname -r; systemd-detect-virt' \
--assume-yes --output-format json > "$WORK/agent-command.json"
AGENT_COMMAND_ID=$(jq -er '.id' "$WORK/agent-command.json")
stackit server command describe "$AGENT_COMMAND_ID" --server-id "$TARGET_SERVER_ID" \
--project-id "$STACKIT_PROJECT_ID" --region "$STACKIT_REGION" --output-format json

Verlangen Sie abgeschlossenen Status und Exitcode 0. AGENT_COMMAND_ID ist die zurückgegebene Befehls-ID, keine Serverkennung. Prüfen Sie Monitoring-Dateneingang, Backup-Umfang und Wiederherstellung vor Übergabe.

Eine weitere Execution desselben Transfers synchronisiert Quelländerungen. Schließen Sie vorherige Kopier-/Deployment-Aufgaben vorher ab. Pro Delta ist kein neuer Transfer erforderlich. Ein vorhandenes geklontes Test-Deployment erhält diese Änderungen nicht; erstellen Sie ein neues Deployment aus frisch geklonten Disks für den aktualisierten Datenstand.

Im dedizierten Beispiel prüfen Sie das Delta mit einmalig zehn synthetischen Schreibzugriffen. Verifizieren Sie vorher die tatsächliche VMware-Quelle statt eines gleichnamigen STACKIT-Klons; systemd-detect-virt muss VMware erkennen. Halten Sie den Hintergrundschreiber gestoppt und fügen Sie keine synthetischen Datensätze in produktive Anwendungen ein:

Terminal-Fenster
for WRITE_NUMBER in {1..10}; do
curl --fail --silent --show-error -X POST http://127.0.0.1:8080/api/writes || exit 1
done
curl --fail --silent --show-error http://127.0.0.1:8080/api/evidence | jq -S

Prüfen Sie exakt zehn zusätzliche Datensätze, unveränderte Seed-Daten und SQL-/HTTP-Übereinstimmung. Erfassen Sie die neue Anzahl/Prüfsumme. Wiederholen Sie keine ungewisse Schreibserie; vergleichen Sie zuerst die Anzahl. Nutzen Sie bei produktiven VMs normale Änderungen und fachliche Konsistenzprüfungen.

Synchronisieren Sie am Arbeitsplatz die Disks und prüfen Sie genau diese neue Execution:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/delta-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/delta-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/delta-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/delta-status.json"

Verlangen Sie abgeschlossene Replikation/Prüfsummen und beide Bereinigungsaufgaben. Wiederholen Sie Deployment mit clone_disks: true, speichern Sie die neue DEPLOYMENT_ID und gleichen Sie die neuen STACKIT-Ressourcen-IDs ab. Wiederholen Sie Gast-/Datenabnahme gegen den neuen Quellstand. Bewahren oder entfernen Sie ältere Testserver nach Testplan; deren alte Daten sind kein Delta-Ergebnis.

Erstkopie und Test-Deployment liegen vor dem Wartungsfenster. Finale Kopie verwendet den eingefrorenen Quellzustand; produktiver Verkehr wechselt erst nach Abnahme der finalen neuen VM.

Vor dem WartungsfensterWartungsfensterProduktion und Aufbewahrung1. Ersttransfer der DisksQuell-VM bleibt an2. Neue Test-VMDiskklone + OS Morphing3. Delta-ExecutionsMit neuer Test-VM prüfen4. Schreiber + Quell-VM stoppenFinalen Datenstand erfassen5. Finale Disk-SynchronisationNoch keine Anwendungs-VM6. Finale neue VM erstellenOS + Anwendung + Daten prüfen7. Freigegebenen Verkehr umschaltenZielschreiber aktivieren8. Überwachen und übergebenQuelle für Wiederherstellung auslassen Abnahme bestanden

Führen Sie den freigegebenen Wartungsplan in dieser Reihenfolge aus:

  1. Stoppen Sie Clientschreibzugriffe, Hintergrundjobs und abhängige Schreiber der Migrationsgruppe.
  2. Stoppen Sie die Quellanwendung, erfassen Sie finale Datenbankanzahl/Prüfsumme und stoppen Sie die Datenbank sauber.
  3. Fahren Sie den Gast regulär über VMware herunter und bestätigen Sie poweredOff in vCenter/ESXi.
  4. Führen Sie eine finale Execution desselben Transfers aus; Replikation und Bereinigung müssen abgeschlossen sein.
  5. Erstellen Sie das finale Deployment, warten Sie auf alle Aufgaben und ermitteln Sie exakte Server-/NIC-/Volume-IDs.
  6. Wiederholen Sie OS-, Zugriffs-, Anwendungs- und finale Datenabnahme auf diesem Server.
  7. Schalten Sie freigegebene DNS-/Load-Balancer-/Routing-Ziele um, aktivieren Sie Zielschreiber und prüfen Sie Clientverkehr.
  8. Überwachen Sie die Anwendung und bewahren Sie die ausgeschaltete Quelle für den vereinbarten Zeitraum auf.

Im Ubuntu-/PostgreSQL-Beispiel stoppen Sie Schreibzugriffe im verifizierten Quellgast:

Terminal-Fenster
sudo systemctl stop relocate-writer.timer relocate-writer.service relocate-demo.service
sudo -u postgres psql -d relocate -At -F '|' -c \
"SELECT count(*), md5(string_agg(record_id || ':' || payload, E'\n' ORDER BY record_id)) FROM migration_records;"
sudo pg_ctlcluster --mode fast 16 relocate stop
sudo sync

Übernehmen Sie finale Anzahl/Prüfsumme vor dem regulären VMware-Herunterfahren in den Abnahmenachweis. Eine gesendete Shutdown-Anfrage beweist noch keinen ausgeschalteten Zustand. Erzwingen Sie keinen Power-off, um einen fehlgeschlagenen Anwendungs-/Datenbankstopp zu umgehen.

Die finale Synchronisation am Arbeitsplatz nutzt dieselbe API wie das Delta, jetzt aber mit ausgeschalteter Quelle und festem erwarteten Datenstand:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' \
--data-binary '{"execution":{"shutdown_instances":false,"auto_deploy":false}}' \
"$API/transfers/$TRANSFER_ID/executions" > "$WORK/final-execution.json"
EXECUTION_ID=$(jq -er '.execution.id' "$WORK/final-execution.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/transfers/$TRANSFER_ID/executions/$EXECUTION_ID?include_task_info=true" \
> "$WORK/final-status.json"
jq '.execution|{id,status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-status.json"

Nach COMPLETED für finale Kopie und Bereinigung wiederholen Sie den Deployment-POST mit derselben deployment-request.json. Erfassen und prüfen Sie das neue finale Deployment:

Terminal-Fenster
curl --fail --silent --show-error -X POST -H @"$WORK/coriolis.headers" \
-H 'Content-Type: application/json' --data-binary @"$WORK/deployment-request.json" \
"$API/deployments" > "$WORK/final-deployment.json"
DEPLOYMENT_ID=$(jq -er '.deployment.id' "$WORK/final-deployment.json")
curl --fail --silent --show-error -H @"$WORK/coriolis.headers" \
"$API/deployments/$DEPLOYMENT_ID?include_info=true&include_task_info=true" \
> "$WORK/final-deployment-status.json"
jq '.deployment|{id,last_execution_status,tasks:[.tasks[]|{task_type,status}]}' "$WORK/final-deployment-status.json"

Verlangen Sie abgeschlossene Deployment-Aufgaben. Prüfen Sie finalen Server gegen eingefrorene Quellanzahl, Prüfsumme und Mount-UUID, nicht gegen eine frühere Test-VM. Führen Sie keine parallelen Kopier-/Deployment-Vorgänge auf demselben Transfer aus.

Vor Zielschreibzugriffen bedeutet Rollback: Ziel isolieren/stoppen, Verkehr fernhalten und die aufbewahrte Quelle nach Plan wieder starten. Nach Zielschreibzugriffen müssen neue Zieldaten vor Rückkehr abgeglichen werden; bloßes Neustarten der alten VM verliert sie. Löschen Sie die Quelle erst nach Aufbewahrungszeitraum und Freigabe durch die Anwendungsverantwortlichen.

Übergeben Sie Quell-/Zielinventar, Endpoint-/Transfer-/Execution-/Deployment-IDs, finale Server-/NIC-/Volume-IDs, abgeschlossene Aufgaben, Anwendungs-/Datenabnahme, SSH-/Identitätsregeln, Monitoring und Backup-/Recovery-Konfiguration. Schützen Sie Dateien mit Zugangsdaten und beachten Sie deren Aufbewahrungsrichtlinie. Veröffentlichen Sie keine rohen Endpoint-Anfragen oder Authentifizierungsheader.

Entfernen Sie übrig gebliebene temporäre Worker erst nach Abgleich von Zugehörigkeit und Aufgabenstatus. Prüfen Sie Security Groups und Ressourcenkosten. Dokumentieren Sie tatsächliche Zielvolumegrößen statt Quellgröße anzunehmen. Wiederholen Sie Vorbereitung, Zuordnung und Abnahme für weitere VMs und migrieren Sie abhängigkeitsgerechte Wellen über dieselbe API-Sequenz.

Externe Quelle cloudbase.it Cloudbase Coriolis Externe Seite öffnen Führt von der Route weg Code & Registry github.com Beispiel-Workload mit Spring Boot und PostgreSQL Repository öffnen