Blog

Große(r) Startskripte auf Azure Windows VMs ausführen

Laurens Knoll

Laurens Knoll

Aktualisiert Oktober 17, 2025
4 Minuten

Kürzlich stand ich vor der Herausforderung, ein großes Startskript auf einer virtuellen Windows-Maschine mit eingeschränkter Internetverbindung auszuführen. In diesem Blog zeige ich Ihnen, wie Sie ein Startskript komprimieren und große(re) Startskripte ausführen können.

Skripte für den VM-Start

Startskripte werden zur Konfiguration oder Initialisierung einer virtuellen Maschine beim Booten oder bei der Bereitstellung verwendet. Das Skript wird normalerweise als Benutzerdaten bereitgestellt und mit cloud-init ausgeführt. Siehe AWS, Azure und GCP.

Azure Windows VM Startup-Skripte

Azure bietet verschiedene Optionen zur Konfiguration eines Startskripts. Die einfachste Lösung ist die CustomScriptExtension. Diese Erweiterung nimmt Ihr Skript an und führt es aus.

resource "azurerm_virtual_machine_extension" "vm_initialize" {
  virtual_machine_id = var.virtual_machine_id
  name               = "My VM Init Script"

  publisher                  = "Microsoft.Compute"
  type                       = "CustomScriptExtension"
  type_handler_version       = "1.10"

  # NOTE: Script is executed from a cmd-shell, therefore escape " as ".
  #       Second, since value is json-encoded, escape " as ".
  settings = <<SETTINGS
    {
      "commandToExecute": "powershell -Command Write-Output "Hello CustomScriptExtension!""
    }
SETTINGS
}

Große Startup-Skripte ausführen

Sie können die CustomScriptExtension nur einmal für Ihre VM einsetzen. Daher können Sie Skripte schnell zu einem großen Skript zusammenfassen. Dies hat zur Folge, dass Sie mit den Beschränkungen für Befehlszeilenstrings konfrontiert werden: Ein einzelner Befehl darf nicht länger als 8191 Zeichen sein.

Wir reduzieren die Anzahl der Zeichen, indem wir das Skript mit der base64gzip-Methode von Terraform komprimieren. Als nächstes aktualisieren wir den PowerShell-Befehl zum Dekodieren und Aufrufen des Skripts:

$InputStream = [IO.MemoryStream]::New([System.Convert]::FromBase64String("base64gzipped string..."));
$GzipStream = [IO.Compression.GzipStream]::New($InputStream, [IO.Compression.CompressionMode]::Decompress);
$ScriptReader=[IO.StreamReader]::New($GzipStream, [System.Text.Encoding]::UTF8);
Set-Content "C:WindowsTempstartup-script.ps1" $ScriptReader.ReadToEnd();
$ScriptReader.Close();
."C:WindowsTempstartup-script.ps1" -parameterX "someValue"

Schließlich wird der Befehl in die Terraform-Konfiguration integriert:

resource "azurerm_virtual_machine_extension" "vm_initialize" {
  virtual_machine_id = var.virtual_machine_id
  name               = "My Large VM Init Script"

  publisher                  = "Microsoft.Compute"
  type                       = "CustomScriptExtension"
  type_handler_version       = "1.10"

  # NOTE 1: Script is executed from a cmd-shell, therefore escape " as ".
  #         Second, since value is json-encoded, escape " as ".
  # NOTE 2: A Windows command is limited to 8191 characters. Therefore 
  #         the script is gzipped and base64 encoded. Source:
  #         https://docs.microsoft.com/en-us/troubleshoot/windows-client/shell-experience/command-line-string-limitation#more-information
  settings = <<SETTINGS
    {
      "commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command $is=[IO.MemoryStream]::New([System.Convert]::FromBase64String("${base64gzip(file("${path.module}/startup-script.ps1"))}")); $gs=[IO.Compression.GzipStream]::New($is, [IO.Compression.CompressionMode]::Decompress); $r=[IO.StreamReader]::New($gs, [System.Text.Encoding]::UTF8); Set-Content "C:WindowsTempstartup-script.ps1" $r.ReadToEnd(); $r.Close(); ."C:WindowsTempstartup-script.ps1" -parameterX "${var.some_value}""
    }
SETTINGS
}

Diskussion

Die CustomScriptExtension ist nicht perfekt für Startskripte geeignet. Idealerweise wird ein Startskript zum Zeitpunkt der Bereitstellung ausgeführt und stoppt die VM bei einem Ausfall. Benutzerdefinierte Daten sind das Azure-Angebot für diesen Zweck. Dazu müssen Sie ein benutzerdefiniertes Image erstellen, um Ihr Skript auszuführen. Die Erstellung eines benutzerdefinierten Abbilds macht jedoch den Zweck des Startskripts zunichte, da Sie nur die Software und die Konfiguration des benutzerdefinierten Abbilds einbinden. Ich würde es begrüßen, wenn Azure dies mit festen Metadatenschlüsseln wie GCP verbessern würde. In GCP ist die Ausführung eines Startskripts so einfach wie die Zuweisung des Skripts zu den VM-Metadaten mit dem Schlüssel windows-startup-script-ps1.

Die angewandte Komprimierung ist nicht unbegrenzt skalierbar. Irgendwann ist das Skript zu groß, um es zu inlinen. Die von Azure angebotene Alternative besteht darin, das Skript in einem Speicherkonto zu hosten und die dem System zugewiesene verwaltete Identität für den Zugriff auf das Speicherkonto über eine private Netzwerkverbindung zu verwenden. Die Verwaltung dieser zusätzlichen Infrastruktur ist eine Herausforderung, da Sie die Datei zum Speicherkonto hinzufügen müssen. Dazu ist ein Zugriff auf die Datenebene erforderlich, der das Hinzufügen von Überprüfungen erfordert, um Verzögerungen bei der Ausbreitung von IAM, privaten Endpunkten oder Firewall-Regeln zu vermeiden. Daher würde ich empfehlen, das Skript in einer vertrauenswürdigen Artefaktregistrierung zu hosten. Auf diese Weise können Sie das Skript immer noch abrufen, seine Integrität überprüfen und sogar größere Startskripte ausführen.

Fazit

Die Ausführung von Startup-Skripten sollte einfach sein. Unabhängig von den Umgebungseinschränkungen. Indem Sie das Startskript komprimieren, können Sie größere Skripte mit dem CustomScriptExtension ausführen.

Foto von Tam Ming von Pexels

Verfasst von

Laurens Knoll

As a cloud consultant I enjoy improving what your company does best. I enable your business using cloud technology and enable your engineers by applying software engineering practices to your infrastructure domain.

Contact

Let’s discuss how we can support your journey.