Hyper-V Server Installation/Konfiguration

Nachdem ich meine eigene Infrastruktur lange Jahre auf VMware ESXi betrieben habe, komme ich immer häufiger zu dem Punkt, dass bei Updates teilweise Treiber entfernt werden und irgendeine Hardware-Komponente dann nicht mehr funktioniert. Daher bleibt nichts anderes übrig, als Alternativen zu prüfen. Eine davon ist Microsoft Hyper-V, den ich in diesem Beitrag installiere und konfiguriere.

Dabei verwende ich folgendes Szenario.

  • Workgroup Hyper-V Server 2019 mit 4 NICs (2 NICs für Management und VM-Netzwerk als NIC-Team, 1 NIC für VMs in einem DMZ-Netzwerk und 1 NIC für den Host zur optionalen Anbindung an ein SMB- oder iSCSI-Storage) und als VM Datastore eine lokale Disk oder eine iSCSI Disk.
Installation: Hyper-V Server

Die Basisinstallation von Hyper-V Server entspricht in weiten Teilen einer Standard Windows Server Installation. Ein Video dazu findet ihr nachfolgend:

Elevated PowerShell

Die meisten der folgenden Befehle müssen in einer Admin-Shell ausgeführt werden. Diese wird bei Bedarf wie folgt gestartet:

powershell.exe -Command "Start-Process -Name powershell -Verb RunAs"
Konfiguration: Server System

Nach Abschluss der Installation konfiguriert man nun das System. Viele Konfigurationen kann man natürlich über die Server Core Konfiguration (sconfig.cmd) oder über die nachinstallierten Features-On-Demand (sieh unten) vornehmen, allerdings möchte ich in diesem Beitrag die Konfiguration möglichst per PowerShell durchführen.

Hostname / DNS-Suffix

Als ersten Schritt konfiguriere ich Standardeinstellungen wie Hostname, Workgroup und DNS-Suffix.

Rename-Computer -NewName HYPERV
Add-Computer -WorkGroupName LAB
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -Name "Domain" -Value "lab.local"
Restart-Computer

Zeitserver

Nun sorge ich für eine korrekte Zeitsynchronisation des Hosts.

Set-TimeZone -Id "W. Europe Standard Time" -PassThru
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DateTime\Servers" -Name "0" -Value "de.pool.ntp.org"
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DateTime\Servers" -Name "(Default)" -Value "0"
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\Parameters" -Name "NtpServer" -Value "de.pool.ntp.org"
Restart-Service w32time

Remote Desktop

Danach aktiviere ich RDP, um darüber einen Remote Zugang zum Hyper-V Host zu ermöglichen.

Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "fDenyTSConnections" -Value "0"
Enable-NetFirewallRule -DisplayGroup "Remote Desktop"

Netzwerk

Automatic IP Adressing (APIPA)

Im ersten Schritt möchte ich verhindern, dass die NICs eine 169.x.x.x IP Adresse aus dem IP-Adressbereich der Autokonfiguration erhalten, falls sie kein DHCP-Adresse bekommen und keine statische IP haben. Dies ist hilfreich für Adapter, die lediglich VM-Traffic verarbeiten und keinen Host-Traffic.

New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -Name "IPAutoconfigurationEnabled" -Value "0" -Type DWord

Interface Name

Um die NICs später einfacher indentifizieren zu können, ändere ich ihre Namen so ab, dass sich ihr Konnektivität erkennen lässt.

Rename-NetAdapter -Name "Ethernet0" -NewName "NIC-LAN1"
Rename-NetAdapter -Name "Ethernet1" -NewName "NIC-LAN2"
Rename-NetAdapter -Name "Ethernet2" -NewName "NIC-DMZ"
Rename-NetAdapter -Name "Ethernet3" -NewName "NIC-SAN"

NIC Team

Danach erstelle ich das NIC-Team aus NIC-LAN1 und NIC-LAN2 und benenne dies auch entsprechend eindeutig.

New-NetLbfoTeam -Name "NIC-LAN-Team" -TeamNicName "NIC-LAN-Team" -TeamMembers "NIC-LAN1","NIC-LAN2" -TeamingMode SwitchIndependant -LoadBalancingAlgorithm Dynamic -Confirm:$false

IPv4 Konfiguration

Server sollten vorzugsweise eine statische IP-Konfiguration erhalten. Auf Grund der Vorgaben werden folgende Parameter konfiguriert:

  • Eine DNS-Suffix Suchliste wird global konfiguriert.
  • DHCP wird für alle NICS deaktiviert
  • NIC-LAN-Team ist die primäre NIC für das Host-Management und VMs im internen Netzwerk. Das NIC-Team erhält daher IP/Subnet im Management LAN, sowie ein Default Gateway und die DNS-Konfiguration (DNS-Server, DNS-Suffix Suchliste, DNS-Registrierungsparameter).
  • NIC-DMZ ist ausschließlich für VMs im DMZ Netzwerk. Der Host soll in diesem Netzwerk keine eigene IP-Adresse erhalten.
  • NIC-SAN ist die NIC für für die Host-Verbindung zum SAN (SMB und iSCSI). Die NIC erhält daher IP/Subnetz im SAN IP-Bereich ohne Gateway und DNS.
# Globale DNS-Suffix Suchliste
Set-DnsClientGlobalSetting -SuffixSearchList @("lab.local")
# Deaktivieren von DHCP für alle NICs
Get-NetIPInterface | where {$_.Dhcp -eq "Enabled"} | Set-NetIPInterface -Dhcp Disabled
# IP/DNS Konfiguration: NIC-LAN-Team
New-NetIPAddress -InterfaceAlias "NIC-LAN-Team" -AddressFamily IPv4 -IPAddress "192.168.0.51" -PrefixLength 24 -DefaultGateway "192.168.0.1"
Set-DnsClientServerAddress -InterfaceAlias "NIC-LAN-Team" -ServerAddresses ("192.168.0.11","192.168.0.12")
Set-DnsClient -InterfaceAlias "NIC-LAN-Team" -ConnectionSpecificSuffix "lab.local" -RegisterThisConnectionsAddress $true -UseSuffixWhenRegistering $true
# IP/DNS Konfiguration: NIC-DMZ
Set-DnsClient -InterfaceAlias "NIC-DMZ" -RegisterThisConnectionsAddress $false -UseSuffixWhenRegistering $false
# IP/DNS Konfiguration: NIC-SAN
New-NetIPAddress -InterfaceAlias "NIC-SAN" -AddressFamily IPv4 -IPAddress "10.0.0.51" -PrefixLength 24
Set-DnsClient -InterfaceAlias "NIC-SAN" -RegisterThisConnectionsAddress $false -UseSuffixWhenRegistering $false

IPv6 Konfiguration

IPv6 benutze ich in meinem Beispiel nicht. Zwar könnte man IPv6 komplett deaktivieren, allerdings führt dies dazu, dass über sconfig.cmd keine IP mehr konfiguriert werden kann. Daher konfiguriere ich lediglich, dass IPv4 gegenüber IPv6 bevorzugt wird (möchte man IPv6 trotzdem komplett deaktivieren, ist der Wert 0x20 durch 0xFF zu ersetzen).

New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters" -Name "DisabledComponents" -Value 0x20 -PropertyType "DWord"

Netzwerk Profil

Standardmäßig haben alle NICs nach der Installation das Public Netzwerk-Profil. Mit folgenden Befehlen ändere ich das Profil für alle NICs auf Private.

$NetConProf = Get-NetConnectionProfile | where {$_.NetworkCategory -eq "Public"}
ForEach ($Nic in $NetConProf) {Set-NetConnectionProfile -NetworkCategory "Private"}

Windows Firewall

Um Remote Verbindungen zu erlauben, schalte ich folgende Firewall Regeln frei:

# ICMP/Ping
Set-NetFirewallRule -DisplayName "File and Printer Sharing (Echo Request - ICMPv4-In)" -Enabled True
# Windows Remote Management (WinRM) / Web Services for Management (WSMan)
Set-NetFirewallRule -DisplayGroup "Windows Remote Management" -Enabled True
# Windows Management Instrumentation (WMI)
Set-NetFirewallRule -DisplayGroup "Windows Management Instrumentation (WMI)" -Enabled True
# Remote Volume Management
Set-NetFirewallRule -DisplayGroup "Remote Volume Management" -Enabled True
# Remote Event Log Management
Set-NetFirewallRule -DisplayGroup "Remote Event Log Management" -Enabled True

Statt einzelne Regeln zu aktivieren, kann optional eine any/any Regel angelegt werden oder die Windows Firewall auch komplett deaktiviert werden:

# any/any-Regel
New-NetFirewallRule -DisplayName "any/any Rule (any/any-In)" -Direction Inbound -Protocol Any -Profile Any -Action Allow -Enabled True
# Firewall deaktivieren
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False

Remote Management

Server

# PowerShell Remoting aktivieren
Enable-PSRemoting
# Remote-Zugriff für WinRM/WSMan mit CredSSP aktivieren inkl. Firewall-Konfiguration
Enable-WSManCredSSP -Role server

Client

Die Client-Konfiguration für Zugriffe auf Workgroup Hyper-V Server findet ihr in einem anderen Beitrag separat, da je nach Client Typ (Workgroup Client, Domain-joined Client) die Konfiguration unterschiedlich und umfangreich ist.

Laufwerke/Speicher

Damit ich meinen Festplatten fortlaufende Laufwerksbuchstaben zuweisen kann, ändere ich den Laufwerksbuchstaben für das optische Laufwerk auf Z:\.

$Optical = Get-WMIObject -Class Win32_CDROMDrive
Get-WmiObject -Class Win32_volume | where {$_.DriveLetter -eq $Optical.Drive} | Set-WmiInstance -Arguments @{DriveLetter="Z:"}

Danach richte ich die Disk(s) für die VMs ein.

SAS/SATA

Die einfachste Option ist eine lokale Disk, die per SAS oder SATA angeschossen ist. Sofern keine Treiber für die Controller benötigte werden sind die Disks direkt nach der Installation verfügbar und können eingerichtet werden.

Mit dem folgenden Befehl ermittle ich alle Disks, die uninitialisiert (RAW) sind und die per SAS- oder SATA-Bus angeschlossen sind, initialisiere die Disks mit Partition-Style GPT für UEFI Systeme, erstelle eine Partition pro Disk mit dem kompletten Speicherplatz und formatiere die erstellten Volumes.

Get-Disk | where {$_.PartitionStyle -eq "RAW" -and ($_.BusType -eq "SAS" -or $_.BusType -eq "SATA")} | Initialize-Disk -PartitionStyle GPT -PassThru | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem NTFS

iSCSI

Eine weitere Option ist die Nutzung von iSCSI. Insbesondere in Lab-Umgebungen mit einer kleinen NAS ist dies ein einfacher Weg, seine VMs dezentral weg vom Hyper-V Server zu speichern. Zuerst starte ich dazu den Microsoft iSCSI Initiator Service und ändere den Start-Typ, damit der Dienst beim Reboot automatisch wieder startet.

Start-Service MSiSCSI
Set-Service -Name MSiSCSI -StartupType Automatic

Danach kann ich mich zum iSCSI Target Portal Server verbinden und das dort verfügbare iSCSI Target (LUN) verbinden. Im folgenden Beispiel lege ich ein neues iSCSI Target Portal für meine NAS (IP 10.0.0.21) über das dedizierte SAN-Interface an. Die NAS ist so konfiguriert, dass sich der Initiator authentifizieren muss. Anschließend verbinde ich alle iSCSI Targets, deren IQN den Namen des Hyper-V Hosts enthält (die IQNs habe ich entsprechen benannt) und die nicht schon verbunden sind. Danach frage ich alle Disks ab, die uninitialisiert (RAW) sind und die per iSCSI-Bus angeschlossen sind. Die Disks initialisiere ich mit Partition-Style GPT für UEFI Systeme, erstelle eine Partition pro Disk mit dem kompletten Speicherplatz und formatiere die erstellten Volumes.

# iSCSI Target Portal (Server) anlegen
New-iSCSITargetPortal -TargetPortalAddress "10.0.0.21" -AuthenticationType ONEWAYCHAP -ChapUsername <CHAP-Username> -ChapPassword <CHAP-Password>
# iSCSI Targets (LUNs) verbinden
$Target = Get-iSCSITarget | where {$_.NodeAddress -like "*:hyperv.lab.local" AND $_.IsConnected -eq $False}
Connect-iSCSITarget -NodeAddress $Target.NodeAddress -IsPersistent $true
# Partition/Volume erstellen
Get-Disk | Where {$_.PartitionStyle -eq "RAW" -and $_.BusType -eq "iSCSI"} | Initialize-Disk -PartitionStyle GPT -PassThru | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem NTFS

Windows Updates

Abschließend installiere ich fehlende Windows Update und bringe das System auf den aktuellen Stand. Dazu wird nach nicht installieren Updates gescannt, installiert und im Anschluss der Server neu gestartet, falls ein Reboot erforderlich ist.

$WUUpdates = Start-WUScan -SearchCriteria "Type='Software' AND IsInstalled=0"
Install-WUUpdates -Updates $WUUpdates
$WUPendingReboot = Get-WUIsPendingReboot
if ($WUPendingReboot -eq $true) {Restart-Computer}

Optional: Installation von Server Core Features on Demand (FOD)

Microsoft bietet ja seit geraumer Zeit die Variante des Windows Server ohne GUI zu Installation an, auf der auch Hyper-V Server basiert. Allerdings fehlen in der Core Variante einige wichtige Libraries, wenn man Programme oder Services darauf ausführen möchte. Daher hat Microsoft nun begonnen, verschiedene fehlende Libraries auf Server Core zu portieren. Dadurch lassen sich mit FOD nun auch die MMC, verschiedene MMC-Snapins und einige Management-Tools auf Server Core ausführen. Bisher war die FOD Installation allerdings nur „richtigen“ Windows Server Core Installationen vorbehalten. Hyper-V Server war von der Installation ausgeschlossen. Hyper-V Server 2019 erlaubt nun auch die Installation von FOD.

Folgende Komponenten sind nun verfügbar:

  • Microsoft Management Console (mmc.exe)
  • Event Viewer (eventvwr.msc)
  • Performance Monitor (perfmon.exe)
  • Resource Monitor (resmon.exe)
  • Device Manager (devmgmt.msc)
  • File Explorer (explorer.exe)
  • Windows PowerShell ISE (powershell_ise.exe)
  • Disk Management (diskmgmt.msc)
  • Failover Cluster Manager (cluadmin.msc)

Leider ist ausgerechnet die Hyper-V Manager Konsole (virtmgmt.msc) in FOD für Windows Server 2019 Core und Hyper-V Server 2019 noch nicht enthalten, d.h. man ist weiterhin auf Remote Administration angewiesen.

Installation per Internet-Download

Add-WindowsCapability -Online -Name ServerCore.AppCompatibility~~~~0.0.1.0

Installation per Installationsmedium

Add-WindowsCapability -Online -Name ServerCore.AppCompatibility~~~~0.0.1.0 -Source <Mounted_FOD_Drive> -LimitAccess
Konfiguration: Hyper-V

Nachdem das Betriebssystem soweit fertig konfiguriert ist, mache ich mich an die Hyper-V Konfiguration.

Hyper-V Settings

Im ersten Schritt konfiguriere ich die Hyper-V Systemeinstellungen.

# Enhanced Session Mode Policy aktivieren
Set-VMHost -EnableEnhancedSessionMode $true
# Live Migration aktivieren und konfigurieren
Enable-VMMigration
Add-VMMigrationNetwork 10.0.0.0/24
Set-VMHost -VirtualMachineMigrationAuthenticationType CredSSP -VirtualMachineMigrationPerformanceOption Compression -UseAnyNetworkForMigration $false
# Maximale Live / Storage Migration Tasks konfigurieren auf 5 parallele Tasks
Set-VMHost -MaximumVirtualMachineMigrations 5 -MaximumStorageMigrations 5
# Speicherpfade für Virtuelle Disks und Virtuelle Maschinen (inkl. Checkpoints/Snapshots) anlegen und konfigurieren
New-Item -Path "D:\Snapshots" -ItemType Directory -Force
New-Item -Path "D:\Virtual Hard Disks" -ItemType Directory -Force
New-Item -Path "D:\Virtual Machines" -ItemType Directory -Force
Set-VMHost -VirtualMachinePath "D:" -VirtualHardDiskPath "D:\Virtual Hard Disks"

Virtual Switch Manager

Danach konfiguriere ich die virtuellen Switches und Netzwerkeinstellungen.

New-VMSwitch -Name "vSwitch-Extern-LAN -NetAdapterName "NIC-LAN-Team" -EnableEmbeddedTeaming $true -AllowManagementOS $true
testen: New-VMSwitch -Name "vSwitch-Extern-LAN -NetAdapterName "NIC-LAN1","NIC-LAN2" -EnableEmbeddedTeaming $true -AllowManagementOS $true
New-VMSwitch -Name "vSwitch-Extern-DMZ -NetAdapterName "NIC-DMZ" -EnableEmbeddedTeaming $true -AllowManagementOS $false
New-VMSwitch -Name "vSwitch-Private-LAB -SwitchType Private -AllowManagementOS $false

VMs erstellen

Danach kann ich meine erste VM erstellen. Die VM bekommt folgende Einstellungen:

  • Disk: 40 GB dynamisch
  • RAM: 4 GB
  • CPUs: 2
  • Netzwerk Adapter: 1 (VLAN 2)
$VM = <VM-Name>
New-VHD -Path "D:\Virtual Disks\$VM.vhdx -SizeBytes 40GB -Dynamic
New-VM -Name $VM -Path "D:\Virtual Machines" -Generation 2 -MemoryStartupBytes 4GB  -VHDPath "D:\Virtual Disks\$VM.vhdx"
Set-VMProcessor -Name $VM -Count 2
Set-VM -Name $VM -AutomaticCheckpointsEnabled $false 
Set-VMBios -VMName $VM -StartupOrder @("Floppy", "LegacyNetworkAdapter", "CD", "IDE")
Set-VMNetworkAdapterVLAN -VMName $VM -Access -VlanId 2

4 Antworten

  1. Henning Uhle sagt:

    Hallo Andreas,

    wunderbar beschrieben. Vielleicht kann man so eine Anleitung ja nochmal brauchen, wenn man nochmal Hyper-V aufbaut. Ich habe es immer bedauert, dass das Microsoft nicht so richtig platziert bekommen hat. Denn eigentlich ist Hyper-V nicht unbedingt schlechter als ESX.

    Ich speichere mir diese Anleitung jedenfalls mal in meinen Notizen. Man weiß ja nie. 🙂

  2. Hristo Hristov sagt:

    Hallo Andreas,
    die Anleitung finde ich Klasse! Genau was man in all täglichem Umfeld braucht. Danke!

  3. Sebastian sagt:

    Also ich habe mal wieder  nach längerer Zeit r ein Windows Server 2019 aufgesetzt, auf diesen wollte ich einen HyperV installieren.

    Wenn ich die Rolle versuche zu installieren, läuft alles ganz normal durch.. Der Server startet neu, installiert weiter und startet noch ein letztes Mal neu.. Wenn er dann wieder bootet kommt das Windows Logo und es startet entweder die automatische Reparatur und es kommt ein Blackscreen oder es kommt sofort ein Blackscreen.

    Was könnte das sein? 

  4. Markus Berger sagt:

    Gute Anleitung, eventuell noch ein Hinweis einfügen dass die Anleitung nur mit der Englischen Installation funktioniert.
    Mit einem Deutschsprachigen Installationsmedium hat man das Problem dass auch viele Registry und Firewall Einträge „eingedeutscht“ sind und die obigen befehle zu Fehler führen.

    Viele Grüße aus dem Süden

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.