ADMIN

2026

06

2026-05-28T12:00:00

Migration und Transformation

PRAXIS

042

Testumgebung

AutomatedLab

PowerShell-Automatisierung

Fortgeschrittene Testumgebungen mit AutomatedLab (2)

Digitaler Zwilling

von Sebastian Jung

Raimund Andrée

Veröffentlicht in Ausgabe 06/2026 - PRAXIS

Der erste Teil dieses Workshops beschäftigte sich mit dem initialen Erstellen einer Umgebung, die Tests einer 3-Tier-Applikation ermöglicht. Auf dem Weg dahin erfassen wir in Teil 2 Systeminformationen, stellen IIS-Features bereit und zeigen, wie PowerShell-Module sauber in die VMs gelangen. Am Ende steht dann ein digitaler Zwilling der IT-Produktionsumgebung.

In Testumgebungen konfigurieren Sie Server häufig für bestimmte Einsatzzwecke (wie Sie bei Bedarf Systeminformationen aller VMs zentral einsammeln, zeigt Listing 1). Für Webanwendungen installieren Sie dann etwa IIS und aktivieren nur die benötigten Komponenten. Mit dem Invoke-LabCommand führen Sie diese Konfiguration zentral vom Host aus und stellen sicher, dass alle Webserver identisch eingerichtet sind. Nachfolgend erwähnen wir übrigens vier weitere Listings, die Sie aus Gründen des Layouts weiter hinten im Artikel finden.
Listing 1: Systeminformationen einsammeln
$info = Invoke-LabCommand -ActivityName 'Systeminformationen sammeln' -ScriptBlock {
[PSCustomObject]@{
Computername = $env:COMPUTERNAME
OS_Version = (Get-CimInstance Win32_OperatingSystem).Caption
OS_Build = (Get-CimInstance Win32_OperatingSystem).BuildNumber
Uptime_Tage = ((Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime).Days
RAM_GB = [math]::Round((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB, 2)
Freier_Platz_C = [math]::Round((Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='C:'").FreeSpace / 1GB, 2)
Prozessoren = (Get-CimInstance Win32_Processor).NumberOfCores
}
} -ComputerName (Get-LabVM) -PassThru
IIS-Features zentral und reproduzierbar installieren
Listing 2 installiert IIS mit den erforderlichen Features, stoppt die Default-Website und erstellt eine eigene Site für die Anwendung. Definieren Sie die benötigten IIS-Komponenten in einem Array und installieren Sie sie in einer Schleife. So erkennen Sie im Output sofort, welches Feature installiert wurde oder einen Fehler verursacht. Stoppen Sie anschließend die Default-Website, um Portkonflikte zu vermeiden. Erstellen Sie danach eine eigene Website und verknüpfen Sie diese mit dem Anwendungsverzeichnis. So richten Sie alle Webserver reproduzierbar ein und vermeiden manuelle Nacharbeit.
Listing 2: IIS einspielen
Invoke-LabCommand -ActivityName 'IIS konfigurieren' -ScriptBlock {
# IIS-Rolle installieren
$features = @(
    'Web-Server',
    'Web-WebServer',
    'Web-Common-Http',
    'Web-Default-Doc',
    'Web-Dir-Browsing',
    'Web-Http-Errors',
    'Web-Static-Content',
    'Web-Health',
    'Web-Http-Logging',
    'Web-Performance',
    'Web-Stat-Compression',
    'Web-Security',
    'Web-Filtering',
    'Web-Mgmt-Tools',
    'Web-Mgmt-Console'
)
foreach ($feature in $features) {
    Write-Host "Installiere Feature: $feature"
    Install-WindowsFeature -Name $feature -IncludeManagementTools
}
# Standard-Website stoppen
Import-Module WebAdministration
Stop-Website -Name "Default Web Site"
# Benutzerdefinierte Website erstellen
New-Website -Name "ContosoApp" `
          -PhysicalPath "C:\inetpub\wwwroot" `
          -Port 80 `
          -Force
Write-Host "IIS erfolgreich konfiguriert"
} -ComputerName (Get-LabVM -Role WebServer)
Mehrstufige Konfigurationen sauber automatisieren
In der Praxis konfigurieren Sie Server meist in mehreren aufeinander aufbauenden Schritten. Dazu gehören etwa das Erstellen einer Datenbank, das Anlegen von Benutzern und das anschließende Testen der Verbindung. Auch solche Abläufe lassen sich vollständig und reproduzierbar automatisieren.
In Testumgebungen konfigurieren Sie Server häufig für bestimmte Einsatzzwecke (wie Sie bei Bedarf Systeminformationen aller VMs zentral einsammeln, zeigt Listing 1). Für Webanwendungen installieren Sie dann etwa IIS und aktivieren nur die benötigten Komponenten. Mit dem Invoke-LabCommand führen Sie diese Konfiguration zentral vom Host aus und stellen sicher, dass alle Webserver identisch eingerichtet sind. Nachfolgend erwähnen wir übrigens vier weitere Listings, die Sie aus Gründen des Layouts weiter hinten im Artikel finden.
Listing 1: Systeminformationen einsammeln
$info = Invoke-LabCommand -ActivityName 'Systeminformationen sammeln' -ScriptBlock {
[PSCustomObject]@{
Computername = $env:COMPUTERNAME
OS_Version = (Get-CimInstance Win32_OperatingSystem).Caption
OS_Build = (Get-CimInstance Win32_OperatingSystem).BuildNumber
Uptime_Tage = ((Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime).Days
RAM_GB = [math]::Round((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB, 2)
Freier_Platz_C = [math]::Round((Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='C:'").FreeSpace / 1GB, 2)
Prozessoren = (Get-CimInstance Win32_Processor).NumberOfCores
}
} -ComputerName (Get-LabVM) -PassThru
IIS-Features zentral und reproduzierbar installieren
Listing 2 installiert IIS mit den erforderlichen Features, stoppt die Default-Website und erstellt eine eigene Site für die Anwendung. Definieren Sie die benötigten IIS-Komponenten in einem Array und installieren Sie sie in einer Schleife. So erkennen Sie im Output sofort, welches Feature installiert wurde oder einen Fehler verursacht. Stoppen Sie anschließend die Default-Website, um Portkonflikte zu vermeiden. Erstellen Sie danach eine eigene Website und verknüpfen Sie diese mit dem Anwendungsverzeichnis. So richten Sie alle Webserver reproduzierbar ein und vermeiden manuelle Nacharbeit.
Listing 2: IIS einspielen
Invoke-LabCommand -ActivityName 'IIS konfigurieren' -ScriptBlock {
# IIS-Rolle installieren
$features = @(
    'Web-Server',
    'Web-WebServer',
    'Web-Common-Http',
    'Web-Default-Doc',
    'Web-Dir-Browsing',
    'Web-Http-Errors',
    'Web-Static-Content',
    'Web-Health',
    'Web-Http-Logging',
    'Web-Performance',
    'Web-Stat-Compression',
    'Web-Security',
    'Web-Filtering',
    'Web-Mgmt-Tools',
    'Web-Mgmt-Console'
)
foreach ($feature in $features) {
    Write-Host "Installiere Feature: $feature"
    Install-WindowsFeature -Name $feature -IncludeManagementTools
}
# Standard-Website stoppen
Import-Module WebAdministration
Stop-Website -Name "Default Web Site"
# Benutzerdefinierte Website erstellen
New-Website -Name "ContosoApp" `
          -PhysicalPath "C:\inetpub\wwwroot" `
          -Port 80 `
          -Force
Write-Host "IIS erfolgreich konfiguriert"
} -ComputerName (Get-LabVM -Role WebServer)
Mehrstufige Konfigurationen sauber automatisieren
In der Praxis konfigurieren Sie Server meist in mehreren aufeinander aufbauenden Schritten. Dazu gehören etwa das Erstellen einer Datenbank, das Anlegen von Benutzern und das anschließende Testen der Verbindung. Auch solche Abläufe lassen sich vollständig und reproduzierbar automatisieren.
Das folgende Beispiel bereitet einen SQL-Server für eine Anwendung vor. Definieren Sie zunächst die Ziel-VM und die benötigten Parameter. Diese Werte übergeben Sie später gezielt an die Remoteskripte:
$sqlServer = Get-LabVM -Role
SQLServer2019
$dbName = "ContosoProduktion"
$dbUser = "ContosoAppUser"
$dbPassword = "P@ssw0rd123!"
Identifizieren Sie den SQL-Server über seine Rolle und definieren Sie die benötigten Verbindungsparameter. Verwenden Sie in produktiven Umgebungen keine Klartextpasswörter, sondern Mechanismen wie "Get-Credential" oder "ConvertTo-SecureString". Um nun die Datenbank mitsamt Tabellen in einem Schritt anzulegen, nutzen Sie Listing 3.
Listing 3: Datenbank und Tabellen anlegen
Invoke-LabCommand -ActivityName 'Datenbank erstellen' -ScriptBlock {
$query = @"
CREATE DATABASE [$dbName];
GO
USE [$dbName];
GO
CREATE TABLE Customers (
    CustomerID INT PRIMARY KEY IDENTITY(1,1),
    Name NVARCHAR(100) NOT NULL,
    Email NVARCHAR(100),
    CreatedDate DATETIME2 DEFAULT GETDATE()
);
CREATE TABLE Orders (
    OrderID INT PRIMARY KEY IDENTITY(1,1),
    CustomerID INT FOREIGN KEY REFERENCES Customers(CustomerID),
    OrderDate DATETIME2 DEFAULT GETDATE(),
    TotalAmount DECIMAL(10,2)
);
"@
Invoke-Sqlcmd -Query $query -ServerInstance $env:COMPUTERNAME
Write-Host "Datenbank $dbName erstellt"
} -ComputerName $sqlServer -Variable (Get-Variable dbName)
Übergeben Sie die Variable "$dbName" wieder mit dem Parameter "-Variable", damit sie im Remotekontext verfügbar ist. Erstellen Sie anschließend den Datenbankbenutzer und vergeben Sie die erforderlichen Berechtigungen (Listing 4). Das Skript prüft zunächst, ob Login und Benutzer bereits existieren. So bleibt der Ablauf wiederholbar und erzeugt bei erneuter Ausführung keine Fehler.
Listing 4: Datenbankbenutzer und Berechtigungen anlegen
Invoke-LabCommand -ActivityName 'Datenbankbenutzer erstellen' -ScriptBlock {
$query = @"
IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = '$dbUser')
BEGIN
CREATE LOGIN [$dbUser] WITH PASSWORD = '$dbPassword';
END
GO
USE [$dbName];
GO
IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = '$dbUser')
BEGIN
    CREATE USER [$dbUser] FOR LOGIN [$dbUser];
END
GO
ALTER ROLE db_datareader ADD MEMBER [$dbUser];
ALTER ROLE db_datawriter ADD MEMBER [$dbUser];
GO
"@
Invoke-Sqlcmd -Query $query -ServerInstance $env:COMPUTERNAME
Write-Host "Benutzer $dbUser mit Berechtigungen erstellt"
} -ComputerName $sqlServer -Variable (Get-Variable dbName, dbUser, dbPassword)
Eine Konfiguration gilt erst als abgeschlossen, wenn Sie sie geprüft haben. Daher folgt im dritten Schritt ein Verbindungstest über eine SQL-Connection. Listing 5 versucht, die Verbindung zu öffnen. Im Erfolgsfall gibt es eine Erfolgsmeldung aus, andernfalls einen Fehler.
Listing 5: Prüfen der Konfiguration
Invoke-LabCommand -ActivityName 'Datenbankverbindung testen' -ScriptBlock {
$connectionString = "Server=$env:COMPUTERNAME;Database=$dbName;User Id=$dbUser;
Password=$dbPassword;"
try {
    $connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
    $connection.Open()
    Write-Host "Datenbankverbindung erfolgreich" -ForegroundColor Green
    $connection.Close()
} catch {
    Write-Error "Verbindung fehlgeschlagen: $_"
}
} -ComputerName $sqlServer -Variable (Get-Variable dbName, dbUser, dbPassword)
PowerShell-Module auf allen VMs konsistent bereitstellen
In vielen Testumgebungen installieren Sie zusätzliche PowerShell-Module, etwa für Azure-Automatisierung, SQL-Administration oder Tests. Definieren Sie dafür zuerst die Module, die auf den Zielsystemen verfügbar sein sollen:
$benoetigteModule = @(
'Az.Accounts',
'Az.Compute',
'SqlServer',
'Pester',
'PSScriptAnalyzer'
)
Installieren Sie die Module anschließend zentral auf allen VMs:
Invoke-LabCommand -ActivityName 'PowerShell-Module installieren' -ScriptBlock {
Das Invoke-LabCommand-Cmdlet erlaubt das parallele Ausführen eines Remotebefehls auf allen VMs der Testumgebung.
Nun müssen Sie TLS 1.2 aktivieren, da die PowerShell Gallery die Verbindung andernfalls ablehnen kann. Installieren Sie die Module per Schleife, um Fortschritt und Fehler pro Modul zu erkennen. Der Try-Catch-Block sorgt dafür, dass die Installation weiterer Module fortgesetzt wird, auch wenn ein einzelnes Modul fehlschlägt. Mit "-Scope AllUsers" stehen die Module systemweit zur Verfügung:
[Net.ServicePointManager]::Security- Protocol = [Net.SecurityProtocol- Type]::Tls12
foreach ($modul in $benoetigteModule) {
  Write-Host "Installiere Modul: $modul"
  try {
    Install-Module -Name $modul
        -Force
        -AllowClobber
        -Scope AllUsers
        -ErrorAction Stop
    Write-Host " $modul installiert" -ForegroundColor Green
  }
  catch {
    Write-Warning " Fehler bei
   $modul : $_"
  }
}
} -ComputerName (Get-LabVM) -Variable (Get-Variable $benoetigteModule)
CredSSP löst das Double-Hop-Problem
In mehrstufigen Umgebungen greifen Server häufig auf weitere Systeme zu, etwa wenn ein Webserver eine Datenbank auf einem SQL-Server abfragt. Dabei tritt das sogenannte Double-Hop-Problem auf: Ein Server kann Anmeldeinformationen nicht automatisch an ein weiteres Zielsystem delegieren. Aktivieren Sie "CredSSP", um dieses Verhalten zu korrigieren. AutomatedLab konfiguriert CredSSP automatisch, wenn Sie nach der Installation des Labs Enable-LabHostRemoting auf dem Host ausführen. Führen Sie diesen Befehl nach Install-Lab aus, sobald alle VMs bereitstehen. AutomatedLab richtet dabei die erforderliche CredSSP-Konfiguration zwischen Host und Lab-VMs ein. Danach funktioniert der Zugriff wie erwartet:
Invoke-LabCommand -ActivityName 'Auf SQL-Server zugreifen' -ScriptBlock {
# Von WebServer auf SQL-Server zugreifen
$version = Invoke-Sqlcmd -ServerInstance "SQL01.contoso.local" -Query "SELECT @@VERSION"
Write-Host "SQL Server Version: $($version.Column1)"
} -ComputerName WebServer1
Der Webserver delegiert nun die Anmeldeinformationen an den SQL-Server und führt die Abfrage erfolgreich aus.
Beachten Sie, dass CredSSP Anmeldeinformationen an Remotesysteme weiterleiten kann. In produktiven Umgebungen sollten Sie diese Funktion nur gezielt einsetzen und auf vertrauenswürdige Systeme beschränken. In isolierten Teststellungen erleichtert sie die Automatisierung erheblich.
Drei-Schichten-Anwendung reproduzierbar bereitstellen
Für das reproduzierbare Bereitstellen kompletter Anwendungsumgebungen kombinieren Sie Softwareinstallation, Dateitransfer und Remotekonfiguration zu einem durchgängigen Deployment-Prozess. Das folgende Beispiel skizziert eine klassische Drei-Schichten-Architektur: ein Webserver für die Benutzeroberfläche, ein Applikationsserver für die Geschäftslogik und ein SQL-Server für die Datenhaltung. Grundlage bildet die ContosoApp-Demoanwendung, bestehend aus Datenbank, .NET-Anwendung und Webkomponente.
Die Laborumgebung definieren Sie vollständig per Skript [1]. Sie erstellen ein internes Netzwerk, provisionieren einen Domänencontroller, einen SQL-Server, einen Anwendungsserver und einen Webserver und integrieren alle Systeme in dieselbe Domäne. Mit Install-Lab starten Sie die automatische Bereitstellung der gesamten Infrastruktur.
Nach der Installation richten Sie die Basissoftware auf allen Servern ein, etwa 7-Zip, Notepad++ und die benötigten .NET-Komponenten. So stellen Sie sicher, dass alle Systeme denselben Ausgangszustand besitzen. Im nächsten Schritt konfigurieren Sie den SQL-Server für die Anwendung. Sie erstellen die Datenbank, legen Tabellen an und richten einen dedizierten Datenbankbenutzer mit den erforderlichen Berechtigungen ein. Damit steht die Grundlage für den Zugriff durch die Anwendung bereit.
Anschließend konfigurieren Sie den Applikationsserver: Sie erstellen das Installationsverzeichnis, kopieren die Anwendungsdateien auf die VM und erzeugen Konfigurationsdateien mit den passenden Verbindungsparametern für den SQL Server. Zum Abschluss richten Sie den Webserver ein. Sie installieren die erforderlichen IIS-Komponenten, übertragen die Webanwendung und konfigurieren eine eigene Website. Gleichzeitig deaktivieren Sie die Default-Site, um Konflikte mit bestehenden Bindings zu vermeiden.
Überprüfen Sie das Deployment mit einfachen Funktionstests. Führen Sie eine SQL-Abfrage aus, um die Datenbankverbindung zu prüfen, und rufen Sie die Webanwendung per HTTP auf. Sind beide Tests erfolgreich, steht eine vollständig konfigurierte und reproduzierbare Anwendungsumgebung bereit.
Fazit
Mit AutomatedLab automatisieren Sie nicht nur die Bereitstellung virtueller Maschinen, sondern den gesamten Aufbau und die Konfiguration komplexer Testumgebungen. Nach der initialen Installation erweitern Sie das Lab gezielt und reproduzierbar um Software, Konfigurationen und vollständige Anwendungsszenarien. Gerade in Test-, Schulungs- und Entwicklungsumgebungen spielt dieser Ansatz seine Stärken aus. Sie stellen Systeme jederzeit im gleichen Zustand bereit, rollen Änderungen kontrolliert aus und testen neue Konfigurationen unter realistischen Bedingungen. Gleichzeitig reduzieren Sie manuellen Aufwand und vermeiden inkonsistente Umgebungen.
(jp)
Links
[1] AutomatedLab GitHub-Repository: https://it-a.eu/q4p52