我日常在WSL+VMware Workstation环境中发现,虽然当前环境已经解决了多品牌虚拟化的问题,但还是经常会出现CPU飙升、内核报错的问题。最后,还是决定全盘Hyper-V化。

Hyper-V

功能启用

帮助文档

  1. Microsoft Learn站点:Windows Server Hyper-V 和虚拟化
  2. 官方文档:Windows上的Hyper-V
  3. 常用命令:Hyper-V Commands
  4. WSL使用帮助:适用于 Linux 的 Windows 子系统文档
  5. Windows命令行:命令行博客

功能开启

1
2
3
4
5
6
# 使用管理员权限开启powershell
Install-WindowsFeature -Name Hyper-V -ComputerName $Env:COMPUTERNAME -IncludeManagementTools
Enable-WindowsOptionalFeature -FeatureName 'Microsoft-Hyper-V-Tools-All' -Online

# 重启主机之后进行校验
Get-WindowsFeature -ComputerName $Env:COMPUTERNAME

网络配置

由于Windows 10 上默认的Default Switch不可管理和卸载,同时默认交换机的IP地址是一直变化的,所以需要创建一个内部网络,搭配自定义路由来实现网络管理。

1
New-VMSwitch -Name PublicSwtich -SwitchType Internal

另外,我们创建的内部网络PublicSwitch默认是没有DHCP并且在宿主机上添加的网卡是没有IP地址,所以可以使用ikuai之类的软路由进行管理。

虚机管理

示例来源:Manage Hyper-V Virtual Machines with PowerShell

基本命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 创建一个名为MyVM,内存为4GB、60GB硬盘使用External Virtual Switch交换机的二代虚机,即BIOS主机
New-VM -Name "MyVM" -MemoryStartupBytes 4GB -Generation 2 -Path "C:\VMS\" -NewVHDPath "C:\VMS\MyVM\disk.vhdx" -NewVHDSizeBytes 60GB -SwitchName "External Virtual Switch"

# 同上,创建同配置的一代虚机,也即使用UEFI的虚机
New-VM -Name "MyVM" -MemoryStartupBytes 4GB -Generation 1 -Path "C:\VMS\" -NewVHDPath "C:\VMS\MyVM\disk.vhdx" -NewVHDSizeBytes 60GB -SwitchName "External Virtual Switch"

# 创建指定hyper-v版本虚机,当前版本为9.0,下例指定为8.0版本
New-VM -Name "MyVM" -MemoryStartupBytes 4GB -Generation 2 -Version 8.0 -Path "C:\VMS\" -NewVHDPath "C:\VMS\MyVM\disk.vhdx" -NewVHDSizeBytes 60GB -SwitchName "External Virtual Switch"

# 配置CPU核心数量,Hyper-V只能指定CPU个数,不同于VMware可以指定CPU个数和核数
Set-VM -Name "MyVM" -ProcessorCount 2

# 配置虚机的内存
Set-VM -Name "MyVM" -MemoryStartupBytes 8GB

# 重命名虚机,磁盘文件不会变更名字
Set-VM -Name "MyVM" -NewVMName "MyNewVM"

# 虚机开机
Start-VM -VMName "MyVM"

# 正常关机
Stop-VM -VMName "MyVM"

# 直接断电
Stop-VM -VMName "MyVM" -TurnOff

# 重启虚机
Restart-VM -VMName "MyVM"

# 删除虚机
Remove-VM -Name "MyVM"

# 删除虚机的同时删除配置文件和磁盘文件
$vm = get-vm "MyVM"; $vmpath = $vm.path; Remove-Item $vm.HardDrives.path -Force ; Remove-VM $vm -Force ; Remove-Item $vmpath -Recurse -Force

进阶管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 附加ISO文件,作为DVD驱动器
Set-VMDvdDrive Name "MyVM" -ControllerNumber 1 -ControllerLocation 0 -Path "C:\ISO\Windowsserver2022.iso"

# 附加完成ISO之后,指定使用ISO文件来启动主机
$vmDVDDrive = Get-VMDvdDrive -VMName "MyVM"; Set-VMFirmware -VMName "MyVM" -FirstBootDevice $vmDVDDrive

# 分离虚机和ISO
Get-VMDvdDrive -VMName "MyVM" | Set-VMDvdDrive -Path $null

# 迁移虚机存储位置
Move-VMStorage "MyVM" -DestinationStoragePath D:\MyVM

# 导出虚机
Export-VM -Name "MyVM" -Path "C:\VMS\"

# 创建虚机的检查点,也即VMware的快照点
Checkpoint-VM -Name "MyVM" -SnapshotName "Before applying .NET updates"

# 应用快照点
Restore-VMCheckpoint -Name "Before applying .NET updates" -VMName "MyVM" -Confirm:$false

# 重命名快照点
Rename-VMCheckpoint -VMName "MyVM" -Name "Before applying .NET updates" -NewName "MyNewCheckpointName"

# 删除指定快照点
Remove-VMCheckpoint -VMName "MyVM" -Name "MyNewCheckpointName"

# 删除所有检查点
Get-VMSnapshot -VMName "MyVM" | Remove-VMSnapshot

# 附加新硬盘
Add-VMHardDiskDrive -VMName "MyVM" -Path "C:\VMS\MyVM\data_disk_02.vhdx"

# 删除其他硬盘
Remove-VMHardDiskDrive -VMName "MyVM" -ControllerType "SCSI" -ControllerNumber 0 -ControllerLocation 2

# 拓展虚机硬盘大小
$vm = get-vm "MyVM"; Resize-VHD -Path $vm.HardDrives.path -SizeBytes 150GB

# 显示虚机属性
Get-VM -VMName "MyVM" | Select * | Out-GridView

高阶命令

1
2
3
4
5
6
7
8
9
10
11
# 在powershell控制台中进入虚机
Enter-PSSession -VMName "MyVM" -Credential (Get-Credential)

# 开启虚机的嵌套虚拟化
Set-VMProcessor -VMName "MyVM" -ExposeVirtualizationExtensions $true; Set-VMNetworkAdapter -VMName "MyVM" -MacAddressSpoofing On

# 宿主机上被挂载的所有ISO文件
Get-VMDvdDrive -VMName * | Where-Object {$_.DvdMediaType -eq 'ISO'}

# 获得创建虚机的时间戳
Get-VM * | Select-Object VMName,CreationTime | Sort-Object CreationTime

虚机部署

图形化部署

脚本部署

开启脚本执行权限

1
2
# 使用管理员权限开始powershell
Set-ExecutionPolicy AllSigned

创建部署脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#部署虚机
Write-Host -NoNewline -ForegroundColor Magenta '请输入要创建的虚机名称(如:Master***)'
[String]$VM_Name = Read-Host
Write-Host -NoNewline -ForegroundColor Magenta '请输入需要放在哪台宿主机上(如:T14GEN4)'
[String]$VM_HostName= Read-Host
Write-Host -NoNewline -ForegroundColor Magenta '请输入虚机vCPU核数?直接回车默认是2vCPU(如:2 回车 )'
[int16]$VM_CpuCount= Read-Host
Write-Host -NoNewline -ForegroundColor Magenta '请输入虚机Memory大小?直接回车默认是4GB(如:4 回车 )'
[int64]$VM_Memory= Read-Host

#要求Hyper-V上显示虚机名称为大写字母
$VM_Name=$VM_Name.toUpper()
$VM_HostName=$VM_HostName.toUpper()

#判断虚机vCPU是否为默认值
if ([int16]$VM_CpuCount -eq '0')
{$VM_CpuCount=2}
Else
{ }

#判断虚机Memory是否为默认值
if ($VM_Memory -eq ' ')
{$VM_Memory=4
$VM_Memory=$VM_Memory*1GB
}
Else
{$VM_Memory=$VM_Memory*1GB}

$Template_VHDX = "SERVICE.vhdx"
$VM_HostName = $Env:COMPUTERNAME

#以下命令受限于在Hyper-V Platform上执行。
$NetworkSwitch=(Get-VMSwitch | Where-Object {$_.Name -match 'PublicSwitch'}).Name
$Template_VHDX_FilePath = "D:\Virtual_Disks\"

#设置磁盘路径
$VM_Path = 'D:\Virtual_Machines'
$VM_RemotePath = "D:\Virtual_Machines"
$VM_VHDPath = $VM_Path + '\' + $VM_Name + '\Virtual Hard Disks\'+ $VM_Name + '.vhdx'
$VM_VHDRemotePath = $VM_RemotePath + '\' + $VM_Name + '\Virtual Hard Disks\' + $VM_Name + '.vhdx'

#新建新虚机硬盘目录,并将目标硬盘Copy到新虚拟硬盘目录下
New-item -path $VM_RemotePath\$VM_Name -name "Virtual Hard Disks" -type directory |Out-Null
Copy-Item -Path $Template_VHDX_FilePath\$Template_VHDX -Destination $VM_VHDRemotePath |Out-Null

#新建虚机 备注:如果提示New-VM报错,很可能是有别名导致的,可以先取消别名。
$VM_Mem=$VM_Memory/1GB
Write-Host -ForegroundColor White "Gather info VMName: $VM_Name,HostName: $VM_HostName,Memory:$VM_Mem GB,vCPU:$VM_CpuCount,OSVersion:RockyLinux9"
New-VM –Name $VM_Name -ComputerName $VM_HostName –Generation 1 -MemoryStartupBytes $VM_Memory -BootDevice VHD -SwitchName $NetworkSwitch –Path $VM_Path -VHDPath $VM_VHDPath |Out-Null

#设置CPU核数
Set-VM -Name $VM_Name -ComputerName $VM_HostName -ProcessorCount $VM_CpuCount

# 启动来宾服务(中文环境下这个名字就似乎中文的,需要通过中文来配置)
Enable-VMIntegrationService -Name "来宾服务接口" -VMName $VM_Name

#禁用动态内存
Set-VMMemory -VMName $VM_Name -ComputerName $VM_HostName -DynamicMemoryEnabled $False

# 关闭自动创建检查点
Set-VM -VMName $VM_Name -AutomaticCheckpointsEnabled $False

#启动虚机
Start-VM -Name $VM_Name -ComputerName $VM_HostName

使用技巧

WSL

部署

1
2
wsl --install
wsl --update

重启

1
wsl --shutdown

关闭/etc/hosts自动刷新

1
2
3
4
5
# 添加如下代码
cat >>/etc/hosts <<EOF
[network]
generateHosts = false
EOF

部署ALmaLinux9

使用微软Store来部署 Microsoft|Store

激活

Hyper-V主机能够不依赖网络KMS来实现自动激活宿主机的虚机。

前提

  1. 使用数据中心版的Windows Server(2012、2016、2019、2022)
  2. 启动了Hyper-V的角色

AVMA Key

AVMA (Automatic Virtual Machine Activation) 自动实现虚机批量自动激活的特定机制,就是该宿主机配置AVMA key之后,该主机上的所有Hyper-V虚机自动激活,无需额外配置。

使用方法:

1
slmgr /ipk "AVMA Key"

常用Key

  • AVMA keys for Windows Server 2019.
Edition AVMA key
Datacenter H3RNG-8C32Q-Q8FRX-6TDXV-WMBMW
Standard TNK62-RXVTB-4P47B-2D623-4GF74
Essentials 2CTP7-NHT64-BP62M-FV6GG-HFV28
  • AVMA keys for Windows Server version 1809.
Edition AVMA key
Datacenter H3RNG-8C32Q-Q8FRX-6TDXV-WMBMW
Standard TNK62-RXVTB-4P47B-2D623-4GF74
  • AVMA keys for Windows Server 2016.
Edition AVMA key
Datacenter TMJ3Y-NTRTM-FJYXT-T22BY-CWG3J
Standard C3RCX-M6NRP-6CXC9-TW2F2-4RHYD
Essentials B4YNW-62DX9-W8V6M-82649-MHBKQ
  • AVMA keys for Windows Server 2012R2.
Edition AVMA key
Datacenter Y4TGP-NPTV9-HTC2H-7MGQ3-DV4TW
Standard DBGBW-NPF86-BJVTX-K3WKJ-MTB6V
Essentials K2XGM-NMBT3-2R6Q8-WF2FK-P36R2

其他

以下是两个写的很好的Hyper-V MVP的blog:

  1. GEORGE MARKOU
  2. THOMAS MAURER (这位是Azure混合云的老大)
  3. Charbelnemom