上一篇 下一篇 分享链接 返回 返回顶部

如何在香港服务器运行 Windows Server 时,配置 WSL2 与 Hyper-V 共存环境以支撑开发与测试?

发布人:Minchunlin 发布时间:2025-08-30 09:00 阅读量:1898


香港机房机柜 18U 位置的那台新上架服务器还散着金属的温度,KVM 上的 BIOS 自检一行行掠过。客户催着要一套“既能跑 Linux 开发栈,又能保留 Windows 内核级测试环境”的方案,而且要能随时快照回滚、低成本扩容。我的第一反应是:WSL2 + Hyper-V 共存——把“日常开发的 Linux 容器与工具链”放 WSL2,把“需要完整 Windows 内核/驱动/域环境的集成测试”放 Hyper-V 虚机。
这活儿听上去简单,真正落地到一台“境外机房、带宽计费、夜间维护窗口”的 Windows Server 上,细节一多,就容易踩坑。下面是我那晚一步步做下来的完整过程、参数、脚本、坑点与补救,尽量写得像你站我旁边一起值夜班。

目标架构

宿主操作系统:Windows Server 2022 Datacenter(桌面体验),单机。

并存虚拟化:

  • WSL2(Ubuntu 22.04 LTS):承载 Node/Go/Java 微服务编译、Docker 引擎与测试容器;
  • Hyper-V:承载 2~3 台 Windows/SQL 等测试虚机(支持快照、隔离网络、端口转发)。

网络:

  • WSL2 默认使用 Hyper-V 后端 NAT(vEthernet(WSL)),可经宿主机端口映射对外;
  • Hyper-V 使用Internal + NAT 组合,统一做静态端口映射;
  • 避免与机房网段冲突(常见 10.0/172.16/192.168 段)。

硬件与系统参数(实机)

项目 参数
机型 1U 单路上架式(Supermicro 定制)
CPU Intel Xeon Silver 4314(16C/32T,支持 VT-x/VT-d/SLAT/EPT)
内存 128 GB DDR4-3200(4 × 32 GB)
系统盘 2 × 960 GB SATA SSD(RAID1)
数据盘 2 × 1.92 TB NVMe U.2(RAID0,用于虚拟化与构建缓存)
网卡 2 × 10GbE(Bond 到上游 vLAN,实配单线)
OS Windows Server 2022 Datacenter 21H2(桌面体验),英文界面/中文输入

若你的宿主是云/虚拟化里的一台 VM(如 ESXi/Hyper-V/Proxmox 上的二级虚拟机),记得开启嵌套虚拟化(下面会写具体开法)。

网络规划(避免冲突)

用途 虚拟交换机/接口 网段 说明
WSL2 后端 vEthernet (WSL) 自动(通常 172.22.x.0/20) WSL2 自建 HNS NAT
Hyper-V NAT NATSwitch (Internal) 10.80.0.0/24 我们自建,给测试 VM 用
宿主对外 Intel 10GbE 机房分配(例如 203.XX.XX.XX/29) 仅宿主直连,不桥接

步骤总览(备忘清单)

  1. 检查与开启虚拟化:BIOS/宿主/嵌套虚拟化能力确认
  2. 启用 Windows 角色/功能:Hyper-V、VirtualMachinePlatform、WSL
  3. 安装与定制 WSL2:发行版、磁盘位置迁移、资源限额、Docker on WSL
  4. 部署 Hyper-V:创建 Internal + NAT,建立测试 VM、CPU/内存策略
  5. 网络打通与端口映射:WSL2/VM 的端口统一从宿主暴露,写死映射表
  6. 编译与测试流水线示例:WSL2 编译 → Hyper-V VM 集成测试
  7. 常见坑与排障:安装失败、网段冲突、端口不通、I/O 抖动
  8. 备份与回滚:WSL2 导出/导入、Hyper-V Checkpoint/Export

1. 虚拟化能力检查与开启

1.1 BIOS / 宿主检查

开启 Intel VT-x / VT-d、SR-IOV(有则开)、Hyper-Threading。

Windows 中验证(PowerShell):

# CPU 是否支持虚拟化扩展
Get-CimInstance Win32_Processor | 
  Select-Object Name, VirtualizationFirmwareEnabled, SecondLevelAddressTranslationExtensions, VMMonitorModeExtensions

确保 VirtualizationFirmwareEnabled=True、SecondLevelAddressTranslationExtensions=True、VMMonitorModeExtensions=True。

1.2 若宿主自己是 VM(嵌套虚拟化)

Hyper-V 上的来宾要再跑 Hyper-V:在宿主 Hyper-V上执行:

Set-VMProcessor -VMName "YourWindowsServer2022VM" -ExposeVirtualizationExtensions $true

VMware ESXi:在 VM 的高级设置里启用 “Expose hardware assisted virtualization to the guest OS”;或在 .vmx 里:

vhv.enable = "TRUE"

2. 启用 Hyper-V / WSL 所需角色与功能

以管理员 PowerShell:

# 2.1 安装 Hyper-V(含管理工具/平台)
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

# 2.2 安装 WSL2 相关平台
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -All
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -All

# 2.3 确保 Hypervisor 启动
bcdedit /set hypervisorlaunchtype Auto

# 2.4 重启
Restart-Computer

注意:Windows Server 2019 官方只完整支持 WSL1;WSL2 的稳妥方案是 Windows Server 2022 及更高。这篇做法基于 2022。

3. 安装与定制 WSL2

3.1 在线安装(有外网)

# 安装 wsl 组件与默认发行版(Ubuntu),并升级内核
wsl --install
wsl --update

# 如果你要指定发行版
wsl --install -d Ubuntu-22.04

3.2 离线安装(无 Store / 受限环境)

在可上网的机器上下载发行版 appx(或官方 wsl --install --web-download);

拷到服务器后:

Add-AppxPackage .\Ubuntu_22.04.0_x64.appx

3.3 设置 WSL2 为默认版本并初始化

wsl --set-default-version 2
wsl --list --online    # 看可用发行版
wsl --list --verbose   # 看已安装发行版与版本

3.4 把 WSL 虚拟磁盘移到数据盘(避免系统盘爆)

WSL2 的 VHDX 默认在 C:\Users\<User>\AppData\Local\Packages\...。我会迁到 D:\WSL:

# 以 Ubuntu 为例
wsl --shutdown
wsl --export Ubuntu-22.04 D:\WSL\ubuntu22.tar
wsl --unregister Ubuntu-22.04
wsl --import Ubuntu-22.04 D:\WSL\Ubuntu22 D:\WSL\ubuntu22.tar --version 2

再次 wsl -d Ubuntu-22.04 即可进入新的根文件系统;VHDX 会在 D:\WSL\Ubuntu22\ext4.vhdx。

3.5 限制资源与开启 systemd(便于 Docker)

在 用户目录创建 C:\Users\<User>\.wslconfig:

[wsl2]
memory=16GB
processors=12
swap=16GB
localhostForwarding=true
# Windows Server 2022 的 WSL 新版已支持 systemd
[experimental]
autoMemoryReclaim=gradual

进入 WSL 的 /etc/wsl.conf 开启 systemd:

[boot]
systemd=true

[automount]
options = "metadata,umask=22,fmask=11"

重启 WSL:

wsl --shutdown
wsl

3.6 在 WSL 安装 Docker(示例)

# Ubuntu 22.04 inside WSL
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
sudo usermod -aG docker $USER
sudo systemctl enable --now docker

4. 部署 Hyper-V:交换机、NAT 与虚机

4.1 创建 Internal 交换机 + NAT

# 创建 Internal vSwitch
New-VMSwitch -SwitchName "NATSwitch" -SwitchType Internal

# 给主机侧接口配 IP(比如 10.80.0.1/24)
$if = Get-NetAdapter | Where-Object {$_.Name -like "vEthernet (NATSwitch)"}
New-NetIPAddress -IPAddress 10.80.0.1 -PrefixLength 24 -InterfaceIndex $if.ifIndex

# 创建 NAT
New-NetNat -Name "LabNat" -InternalIPInterfaceAddressPrefix 10.80.0.0/24

4.2 新建测试 VM(示例:Windows Server / SQL)

# 盘放在 NVMe 卷上,利于 I/O
$VMPath = "D:\VMs\WS-Tests"
New-VM -Name "WinTest01" -MemoryStartupBytes 8GB -Generation 2 -SwitchName "NATSwitch" -Path $VMPath

# CPU/内存策略
Set-VMProcessor -VMName "WinTest01" -Count 6 -ExposeVirtualizationExtensions $false
Set-VMMemory -VMName "WinTest01" -DynamicMemoryEnabled $true -MinimumBytes 4GB -MaximumBytes 16GB -Buffer 30

# 加载 ISO,装系统
Add-VMDvdDrive -VMName "WinTest01" -Path "D:\ISO\Windows_Server_2022.iso"
Start-VM "WinTest01"

装好系统后,给 VM 配静态 IP(10.80.0.10/24,网关 10.80.0.1,DNS 指向机房 DNS 或 10.80.0.1 再转发)。

5. 统一的端口映射(从宿主对外暴露)

我习惯所有服务只在宿主开放端口,再根据来源转发到 WSL 或 VM,方便审计与变更。

5.1 WSL2 端口映射(宿主 → WSL)

先查 WSL IP:

wsl hostname -I
# 比如 172.22.0.15

用 netsh 做 portproxy(示例把宿主 80/443 转给 WSL Nginx):

# HTTP
netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=172.22.0.15
# HTTPS
netsh interface portproxy add v4tov4 listenport=443 listenaddress=0.0.0.0 connectport=443 connectaddress=172.22.0.15

WSL 的 IP 会变;为省事可以写一个开机/WSL 启动脚本自动刷新映射(见“坑点”章节)。

5.2 Hyper-V VM 端口映射(宿主 → VM)

用 HNS NAT 的静态映射(对 LabNat):

# 把宿主 1433 转给 SQL VM 10.80.0.10:1433
Add-NetNatStaticMapping -NatName "LabNat" -Protocol TCP -ExternalIPAddress "0.0.0.0" -ExternalPort 1433 -InternalIPAddress "10.80.0.10" -InternalPort 1433

5.3 防火墙规则

# 允许 80,443,1433 入站(按需)
New-NetFirewallRule -DisplayName "Lab-HTTP" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Allow
New-NetFirewallRule -DisplayName "Lab-HTTPS" -Direction Inbound -LocalPort 443 -Protocol TCP -Action Allow
New-NetFirewallRule -DisplayName "Lab-SQL" -Direction Inbound -LocalPort 1433 -Protocol TCP -Action Allow

5.4 我的端口映射表(当晚上线版)

宿主端口 去向 备注
80 / 443 WSL2: 172.22.0.15 Nginx 反代微服务
1433 VM: 10.80.0.10 SQL Server 开发库
2222 WSL2: 172.22.0.15:22 仅内网调试用
5000-5010 VM: 10.80.0.20:5000-5010 UI 自动化测试

6. 开发/测试流水线:一条能跑的样例

6.1 在 WSL2 编译并容器化

# 在 WSL2 的 Ubuntu
git clone https://example.com/app.git
cd app
docker build -t registry.example.com/app:dev .
docker push registry.example.com/app:dev

6.2 在 WSL2 部署网关/反代(Nginx 片段)

# /etc/nginx/conf.d/app.conf
server {
  listen 80;
  server_name _;
  location /api/ {
    proxy_pass http://10.80.0.10:8080/;  # 转向 VM 上的后端
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
  location / {
    proxy_pass http://127.0.0.1:3000/;    # 前端容器在 WSL
  }
}

6.3 在 Hyper-V VM 跑集成测试(IIS/服务/SQL)

# VM 内,以管理员
Enable-WindowsOptionalFeature -Online -FeatureName IIS-WebServerRole -All
# 部署 .NET 服务、连 SQL(略)

7. 常见坑与现场解法(当晚真被坑过)

7.1 wsl --install 提示内核缺失 / WSL2 无法启动

现象:首次进 WSL 报“请安装内核组件”。

解法:

  • wsl --update 更新内核;
  • 控制面板 → “启用或关闭 Windows 功能”确认 VirtualMachinePlatform 勾选;
  • bcdedit /set hypervisorlaunchtype Auto 后重启。

7.2 机房网段冲突,WSL2/Hyper-V NAT“消失”

现象:机房用了 172.16/12 大网段,和 WSL2 默认 172.22.x.x 有时重叠导致不可达。

稳妥做法:避开 10/172/192 常见段给 Hyper-V NAT 用一个独特段(我用 10.80.0.0/24)。

WSL2 的 HNS NAT 段不易持久改,把对外端口终结在宿主,由宿主转发,减少“找 WSL IP”的需要。

7.3 WSL 重启后 IP 变化导致 portproxy 失效

解决脚本(宿主 PowerShell,放计划任务“用户登录/启动时”):

$wslIP = (wsl hostname -I).Trim().Split(" ")[0]
$map = @(
  @{ListenPort=80;  TargetPort=80},
  @{ListenPort=443; TargetPort=443},
  @{ListenPort=2222;TargetPort=22}
)
foreach($m in $map){
  try{
    netsh interface portproxy delete v4tov4 listenport=$($m.ListenPort) listenaddress=0.0.0.0 | Out-Null
  }catch{}
  netsh interface portproxy add v4tov4 listenport=$($m.ListenPort) listenaddress=0.0.0.0 connectport=$($m.TargetPort) connectaddress=$wslIP
}

7.4 netsh portproxy 只支持 IPv4

如果有 IPv6 入站需求,可在前面加一层 Nginx/HAProxy(Windows 版或容器),或用 Windows 新版 HNS 映射(较复杂,不在此展开)。

7.5 构建 I/O 抖动(Defender 实时扫描)

现象:Docker 构建写大量小文件,Windows Defender 扫描导致 I/O 抖动。

取舍:在合规前提下针对 D:\WSL\ 与 D:\VMs\ 做排除项,或将 Docker layer/cache 放 NVMe。

命令:

Add-MpPreference -ExclusionPath "D:\WSL","D:\VMs"

7.6 VM 时间漂移 / DNS 解析失败

开启 Windows Time 同步、把 VM DNS 指向宿主/机房权威;WSL 端如遇 VPN/DNS 变化,可在 /etc/wsl.conf 里:

[network]
generateResolvConf = true

然后 wsl --shutdown 重新生成 /etc/resolv.conf。

8. 性能与容量:我当晚的配额与观测

维度 配置 说明
WSL2 CPU/内存 12 vCPU / 16 GB .wslconfig 限额,编译足够
VM1(SQL) 6 vCPU / 动态 4–16 GB OLTP 开发库
VM2(App) 4 vCPU / 动态 4–12 GB .NET 服务集成测试
宿主剩余 ~10–12 vCPU / 40 GB 预留给峰值/缓存
磁盘布局 WSL/VM 都走 NVMe 明显降低构建时间
快照策略 每次版本前在 Hyper-V 做 Checkpoint 回滚快

9. 备份与回滚

9.1 WSL2 快照(导出/导入)

wsl --export Ubuntu-22.04 D:\Backup\ubuntu22_$(Get-Date -f yyyyMMdd).tar
# 恢复
wsl --shutdown
wsl --unregister Ubuntu-22.04
wsl --import Ubuntu-22.04 D:\WSL\Ubuntu22 D:\Backup\ubuntu22_20250830.tar --version 2

9.2 Hyper-V 快照/导出

# Checkpoint(快照)
Checkpoint-VM -Name "WinTest01" -SnapshotName "pre-release-$(Get-Date -f yyyyMMddHHmm)"

# 导出 VM
Export-VM -Name "WinTest01" -Path "D:\Export\WinTest01"

10. 完整自动化安装脚本(可作蓝本)

以全新 Windows Server 2022 为前提,执行后重启、装 WSL、建 NAT、放通常用端口。

# run as admin

# --- Features ---
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -All
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -All
bcdedit /set hypervisorlaunchtype Auto

# --- Reboot once ---
# Restart-Computer

# --- WSL base ---
wsl --install --no-distribution
wsl --update
wsl --set-default-version 2

# --- .wslconfig ---
$wslcfg = @"
[wsl2]
memory=16GB
processors=12
swap=16GB
localhostForwarding=true
[experimental]
autoMemoryReclaim=gradual
"@
$wslcfg | Out-File -FilePath "$env:USERPROFILE\.wslconfig" -Encoding ascii

# --- Hyper-V switch & NAT ---
if (-not (Get-VMSwitch -Name "NATSwitch" -ErrorAction SilentlyContinue)) {
  New-VMSwitch -SwitchName "NATSwitch" -SwitchType Internal | Out-Null
}
$if = Get-NetAdapter | Where-Object {$_.Name -like "vEthernet (NATSwitch)"}
if (-not (Get-NetIPAddress -InterfaceIndex $if.ifIndex -ErrorAction SilentlyContinue)) {
  New-NetIPAddress -IPAddress 10.80.0.1 -PrefixLength 24 -InterfaceIndex $if.ifIndex | Out-Null
}
if (-not (Get-NetNat -Name "LabNat" -ErrorAction SilentlyContinue)) {
  New-NetNat -Name "LabNat" -InternalIPInterfaceAddressPrefix 10.80.0.0/24 | Out-Null
}

# --- Firewall common ports ---
$ports = 80,443,1433,2222
foreach($p in $ports){
  if(-not (Get-NetFirewallRule -DisplayName "Lab-$p" -ErrorAction SilentlyContinue)){
    New-NetFirewallRule -DisplayName "Lab-$p" -Direction Inbound -LocalPort $p -Protocol TCP -Action Allow | Out-Null
  }
}

Write-Host "Base environment done. Install your WSL distro and VMs next."

11. 我会如何验证一切就绪(最短路径)

wsl -l -v 看到发行版是 VERSION=2,进入 wsl 能 systemctl status docker 正常;

docker run hello-world 成功;

Hyper-V 创建一个最小 VM,能拿到 10.80.0.x,ping 10.80.0.1 通;

宿主访问:curl http://127.0.0.1/ → 能看到 WSL Nginx;

远端访问:用你在机房 NAT 上的对外 IP + 80 端口能开站;

Add-NetNatStaticMapping 后,从外网 telnet <publicIP> 1433 通,客户端能连 SQL。

12. FAQ:我常被问到的两个问题

WSL2 与 Hyper-V 会不会冲突?
不会。WSL2 的虚拟化后端就是 Hyper-V。冲突反而多见在:你同时装了第三方虚拟化(旧版 VMware/VirtualBox)并让它们抢 Hypervisor。解决:用新版、或只在这台服务器上坚持 Hyper-V 体系。

要不要桥接 Hyper-V 到物理网卡?
测试/隔离环境我更推荐 Internal + NAT。桥接(External)到机房物理网卡容易牵扯上游交换机 vLAN、ARP 安全策略与 MAC 限制,不如端口映射稳。

结尾:夜里三点的那口气

凌晨 3 点 20 分,我在 KVM 上重启了最后一台测试 VM。Nginx 的健康检查全绿,GitLab Runner 把构建产物推上去,QA 同事从深圳远程连进来,SQL 库也通了。机房空调还在呼呼响,但我知道这套“WSL2 干开发、Hyper-V 做集成”的混合场已经跑顺了——以后不管是临时拉一台 Windows 测试域、还是在 WSL 里开十个容器做回归,都不过就是一行脚本的事。
我把那张手写端口映射表折好塞进笔记本,给机柜门上锁,踩着荔枝角还未亮的街,心里只有一句话:好用的环境,都是一点点熬出来的。

附:最小化自检清单(带打勾)

  •  BIOS 开启 VT-x/VT-d/SLAT
  •  Get-CimInstance Win32_Processor 三项为 True
  •  安装 Hyper-V / WSL / VirtualMachinePlatform 并重启
  •  wsl --set-default-version 2 + wsl --update
  •  .wslconfig 限额与 systemd=true 生效
  •  NATSwitch + LabNat 正常、VM 能拿 10.80.0.x
  •  宿主端口 → WSL/VM 映射可达(80/443/1433/…)
  •  备份策略:wsl --export 与 Checkpoint-VM 可用
目录结构
全文