让我们演练新 NAT 网络的设置。
以管理员身份打开 PowerShell 控制台。
创建内部交换机。
PowerShell 复制New-VMSwitch -SwitchName "SwitchName" -SwitchType Internal
查找刚创建的虚拟交换机的接口索引。
你可以通过运行以下命令查找接口索引
Get-NetAdapter
你的输出应类似下面的形式:
复制PS C:\> Get-NetAdapter Name InterfaceDescription ifIndex Status MacAddress LinkSpeed ---- -------------------- ------- ------ ---------- --------- vEthernet (intSwitch) Hyper-V Virtual Ethernet Adapter 24 Up 00-15-5D-00-6A-01 10 Gbps Wi-Fi Marvell AVASTAR Wireless-AC Net... 18 Up 98-5F-D3-34-0C-D3 300 Mbps Bluetooth Network ... Bluetooth Device (Personal Area... 21 Disconnected 98-5F-D3-34-0C-D4 3 Mbps
内部交换机的名称将类似于
vEthernet (SwitchName)
,接口描述将为Hyper-V Virtual Ethernet Adapter
。 请记下其ifIndex
以便在下一步中使用。使用 New-NetIPAddress 配置 NAT 网关。
下面是常规命令:
PowerShell 复制New-NetIPAddress -IPAddress <NAT Gateway IP> -PrefixLength <NAT Subnet Prefix Length> -InterfaceIndex <ifIndex>
若要配置网关,你将需要一些有关你的网络的信息:
IPAddress - NAT 网关 IP 指定要用作 NAT 网关 IP 的 IPv4 或 IPv6 地址。
常规形式将为 a.b.c.1(例如 172.16.0.1)。 尽管最后一个位置不一定必须是.1,但通常是(基于前缀长度)通用网关 IP 为 192.168.0.1
PrefixLength - NAT 子网前缀长度定义的 NAT 本地子网大小(子网掩码)。子网前缀长度将为 0 到 32 之间的整数值。
0 将映射整个 Internet,32 将只允许一个映射的 IP。 常用值的范围为 24 到 12,具体取决于需要附加到 NAT 的 IP 数。
常用 PrefixLength 为 24 -- 这是子网掩码 255.255.255.0
InterfaceIndex -- ifIndex 是你在上一步中确定的虚拟交换机的接口索引。
运行以下内容来创建 NAT 网关:
PowerShell 复制New-NetIPAddress -IPAddress 192.168.0.1 -PrefixLength 24 -InterfaceIndex 24
使用 New-NetNat 配置 NAT 网络。
下面是常规命令:
PowerShell 复制New-NetNat -Name <NATOutsideName> -InternalIPInterfaceAddressPrefix <NAT subnet prefix>
若要配置网关,你将需要提供一些有关网络和 NAT 网关的信息:
Name - NATOutsideName 描述 NAT 网络的名称。 将使用此参数删除 NAT 网络。
InternalIPInterfaceAddressPrefix - NAT 子网前缀同时描述上述 NAT 网关 IP 前缀和上述 NAT 子网前缀长度。
常规形式将为 a.b.c.0/NAT 子网前缀长度
综上所述,对于本示例,我们将使用 192.168.0.0/24
对于我们的示例,运行以下命令以设置 NAT 网络:
PowerShell 复制New-NetNat -Name MyNATnetwork -InternalIPInterfaceAddressPrefix 192.168.0.0/24
多个应用程序使用相同的 NAT
某些情况下需要多个应用程序或服务使用同一个 NAT。 在这种情况下,必须遵循以下工作流,以便多个应用程序/服务可以使用更大的 NAT 内部子网前缀
我们将以与 Windows 容器功能共存于同一主机上的 Docker 4 Windows - Docker Beta - Linux VM 作为示例,对其进行详细介绍。 此工作流可能会随时发生变化
- C:> net stop docker
- 停止 Docker4Windows MobyLinux VM
- PS C:> Get-ContainerNetwork | Remove-ContainerNetwork -force
PS C:> Get-NetNat | Remove-NetNat
删除任何先前存在的容器网络(即删除 vSwitch、删除 NetNat、清理)New-ContainerNetwork -Name nat -Mode NAT –subnetprefix 10.0.76.0/24(此子网将用于 Windows 容器功能)创建名为 nat 的内部 vSwitch
创建名为“nat”、IP 前缀为 10.0.76.0/24 的 NAT 网络Remove-NetNAT
删除 DockerNAT 和 nat NAT 网络(保留内部 vSwitch)New-NetNat -Name DockerNAT -InternalIPInterfaceAddressPrefix 10.0.0.0/17(这将创建较大的 NAT 网络,以供 D4W 和容器共享)
创建名为“DockerNAT”的 NAT 网络,且该网络采用较大的前缀 10.0.0.0/17运行 Docker4Windows (MobyLinux.ps1)
创建内部 vSwitch DockerNAT
创建名为“DockerNAT”、IP 前缀为 10.0.75.0/24 的 NAT 网络Net start docker
Docker 将使用用户定义的 NAT 网络作为默认网络连接到 Windows 容器
最终,你将具有两个内部 vSwitch – 一个名为 DockerNAT,另一个名为 nat。 你仅将拥有一个 NAT 网络 (10.0.0.0/17),可通过运行 Get-NetNat 确认。 Windows 容器的 IP 地址将由 Windows 主机网络服务 (HNS) 从 10.0.76.0/24 子网分配。 基于现有 MobyLinux.ps1 脚本,将从 10.0.75.0/24 子网分配 Docker 4 Windows 的 IP 地址。
疑难解答
不支持多个 NAT 网络
本指南假设主机上没有其他 NAT。 但是,应用程序或服务将要求使用一个 NAT,并且有可能创建一个 NAT,使之作为安装的一部分。 由于 Windows (WinNAT) 仅支持一个内部 NAT 子网前缀,因此尝试创建多个 NAT 将使系统处于未知状态。
若想知道这是否是个问题,请确保你只有一个 NAT:
Get-NetNat
如果已存在一个 NAT,请将其删除
Get-NetNat | Remove-NetNat
请确保应用程序或功能(例如 Windows 容器)仅有一个“内部”vmSwitch。 记录 vSwitch 的名称
Get-VMSwitch
检查是否仍存在从旧 NAT 向适配器分配的专用 IP 地址(例如 NAT 默认网关 IP 地址 – 通常为 *.1)
Get-NetIPAddress -InterfaceAlias "vEthernet (<name of vSwitch>)"
如果旧专用 IP 地址仍在使用中,请将其删除
Remove-NetIPAddress -InterfaceAlias "vEthernet (<name of vSwitch>)" -IPAddress <IPAddress>
删除多个 NAT
我们看到无意中创建了多个 NAT 网络的报告。 这是由于最近的版本(包括 Windows Server 2016 Technical Preview 5 和 Windows 10 Insider Preview 版本)存在一个 bug。 如果你看到多个 NAT 网络,在运行 docker network ls 或 Get-ContainerNetwork 之后,请在提升的 PowerShell 中执行以下操作:
PS> $KeyPath = "HKLM:\SYSTEM\CurrentControlSet\Services\vmsmp\parameters\SwitchList"
PS> $keys = get-childitem $KeyPath
PS> foreach($key in $keys)
PS> {
PS> if ($key.GetValue("FriendlyName") -eq 'nat')
PS> {
PS> $newKeyPath = $KeyPath+"\"+$key.PSChildName
PS> Remove-Item -Path $newKeyPath -Recurse
PS> }
PS> }
PS> remove-netnat -Confirm:$false
PS> Get-ContainerNetwork | Remove-ContainerNetwork
PS> Get-VmSwitch -Name nat | Remove-VmSwitch (_failure is expected_)
PS> Stop-Service docker
PS> Set-Service docker -StartupType Disabled
Reboot Host
PS> Get-NetNat | Remove-NetNat
PS> Set-Service docker -StartupType automaticac
PS> Start-Service docker