我正在将 Laravel Homestead 与 Vagrant 结合使用,并且我认为使用 Hyper-V 而不是 Virtual Box 更有意义,因为它与 Windows 集成。
这是我的问题。我的 Hyper-v 虚拟机时不时会获得一个新 IP,通常是 172.20.83.X。当我将 IP 分配给测试域时,这会弄乱我的主机文件。因此,每次我的 Hyper-v 服务器获得新 IP 时,我都必须重新输入新 IP,这很快就会变得非常繁琐。
我想知道是否有办法将 IP 设置为在我的计算机上始终保持不变。
我尝试修改服务器的虚拟交换机管理器,但最终却导致完全失去互联网连接。
答案1
背景
提问者以及任何有类似用例的人都可能在工作站(非 Windows Server 版本)上进行操作,用于本地开发目的,并且不愿意运行 DHCP 服务器,只是为了防止 Hyper-V每次主机重启时更改 IP 地址分配。
在配置后,需要在虚拟机的网络配置中“手动”硬编码静态 IP 地址,这很麻烦,而且会阻碍自动化。为了符合“一次性”开发虚拟机和免提配置工作流程的精神,自动化整个过程不是更可取吗?当然可以!
所有这些步骤都是必要的,因为 Vagrant 还不能为 Hyper-V 机器设置静态 IP 地址。请参阅:
- https://www.vagrantup.com/docs/hyperv/limitations.html
- https://github.com/hashicorp/vagrant/issues/8384
概述
简而言之,实现这一目标的事件顺序如下:
- 为 Hyper-V 创建 NAT 交换机。(这是一个仅供内部使用的交换机,任何数量的具有静态 IP 地址的虚拟机以及 Hyper-V 主机都可以在此交换机后面相互通信。此交换机后面的客户端可以出站访问主机可以访问的任何网络资源,例如 Internet 或 LAN。)
- 配置一个 Vagrant Trigger,利用
vagrant-reload
重新加载前事件中的插件来按需更改给定 VM 的网络交换机。 vagrant up
,但在初始规定时选择Default Switch
(不是新的)。NATSwitch
- 在配置过程开始时,在虚拟机的操作系统中配置一个在
NATSwitch
范围内的静态 IP(此步骤特定于操作系统)。 - 调用
config.vm.provision :reload
,这将 a) 触发步骤 2 中定义的触发器,从而将 VM 的网络交换机更改为新的NATSwitch
;以及 b)vagrant reload
在 VM 重启后发出并继续配置过程。 - 当虚拟机重新启动时,它将从中获取静态 IP 地址
NATSwitch
并无限期地使用它。
1. 创建 NAT 交换机
虽然这一步当然可以手动完成一次,但将命令嵌入到可以在配置期间调用的脚本中效果更佳Vagrantfile
。这样的脚本可能如下所示:
./scripts/create-nat-hyperv-switch.ps1
:
# See: https://www.petri.com/using-nat-virtual-switch-hyper-v
If ("NATSwitch" -in (Get-VMSwitch | Select-Object -ExpandProperty Name) -eq $FALSE) {
'Creating Internal-only switch named "NATSwitch" on Windows Hyper-V host...'
New-VMSwitch -SwitchName "NATSwitch" -SwitchType Internal
New-NetIPAddress -IPAddress 192.168.0.1 -PrefixLength 24 -InterfaceAlias "vEthernet (NATSwitch)"
New-NetNAT -Name "NATNetwork" -InternalIPInterfaceAddressPrefix 192.168.0.0/24
}
else {
'"NATSwitch" for static IP configuration already exists; skipping'
}
If ("192.168.0.1" -in (Get-NetIPAddress | Select-Object -ExpandProperty IPAddress) -eq $FALSE) {
'Registering new IP address 192.168.0.1 on Windows Hyper-V host...'
New-NetIPAddress -IPAddress 192.168.0.1 -PrefixLength 24 -InterfaceAlias "vEthernet (NATSwitch)"
}
else {
'"192.168.0.1" for static IP configuration already registered; skipping'
}
If ("192.168.0.0/24" -in (Get-NetNAT | Select-Object -ExpandProperty InternalIPInterfaceAddressPrefix) -eq $FALSE) {
'Registering new NAT adapter for 192.168.0.0/24 on Windows Hyper-V host...'
New-NetNAT -Name "NATNetwork" -InternalIPInterfaceAddressPrefix 192.168.0.0/24
}
else {
'"192.168.0.0/24" for static IP configuration already registered; skipping'
}
然后,在配置部分的顶部添加一个适当的触发器Vagrantfile
,这将确保配置始终正确vagrant up
:
config.trigger.before :up do |trigger|
trigger.info = "Creating 'NATSwitch' Hyper-V switch if it does not exist..."
trigger.run = {privileged: "true", powershell_elevated_interactive: "true", path: "./scripts/create-nat-hyperv-switch.ps1"}
end
2.配置 Vagrant Reload 触发器
在配置过程中重新启动(重新加载)虚拟机,以便切换到静态 IP 地址,需要https://github.com/aidanns/vagrant-reload插件,因此先安装它:
vagrant plugin install vagrant-reload
触发器将调用的脚本非常简单:
./scripts/set-hyperv-switch.ps1
:
# See: https://www.thomasmaurer.ch/2016/01/change-hyper-v-vm-switch-of-virtual-machines-using-powershell/
Get-VM "homestead" | Get-VMNetworkAdapter | Connect-VMNetworkAdapter -SwitchName "NATSwitch"
接下来,在配置部分添加适当的触发器Vagrantfile
(即,在上一步添加的触发器下方):
config.trigger.before :reload do |trigger|
trigger.info = "Setting Hyper-V switch to 'NATSwitch' to allow for static IP..."
trigger.run = {privileged: "true", powershell_elevated_interactive: "true", path: "./scripts/set-hyperv-switch.ps1"}
end
3. 在客户虚拟机内配置静态 IP
配置静态 IP 是特定于操作系统的任务,因此应调整此过程以适应特定的客户操作系统。以下是两个示例。
笔记:如果在公司网络上,请务必使用公司的 DNS 服务器,因为 Google 的服务器(如这些示例中所示)可能无法访问。
Ubuntu 18.04 LTS 示例
在 Ubuntu 18.04 LTS 上,这个方法很好用:
./scripts/configure-static-ip.sh
:
#!/bin/sh
echo 'Setting static IP address for Hyper-V...'
cat << EOF > /etc/netplan/01-netcfg.yaml
network:
version: 2
ethernets:
eth0:
dhcp4: no
addresses: [192.168.0.2/24]
gateway4: 192.168.0.1
nameservers:
addresses: [8.8.8.8,8.8.4.4]
EOF
# Be sure NOT to execute "netplan apply" here, so the changes take effect on
# reboot instead of immediately, which would disconnect the provisioner.
RedHat、CentOS 和 Oracle Linux 示例
./scripts/configure-static-ip.sh
:
#!/bin/sh
echo 'Setting static IP address for Hyper-V...'
cat << EOF > /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=none
ONBOOT=yes
PREFIX=24
IPADDR=192.168.0.2
GATEWAY=192.168.0.1
DNS1=8.8.8.8
EOF
# Be sure NOT to execute "systemctl restart network" here, so the changes take
# effect on reboot instead of immediately, which would disconnect the provisioner.
使用上述脚本后,在我们之前添加的触发器定义下方添加类似这样的内容:
config.vm.provision "shell", path: "./scripts/configure-static-ip.sh"
config.vm.provision :reload
4. 配置虚拟机
vagrant up
并Default Switch
在提示时进行选择;这会导致 VM 获取一个动态 IPv4 地址,该地址足以让 Vagrant 通过 SSH 连接到 VM、挂载共享文件夹并开始配置。
现在,将设置静态 IP 地址并在继续配置之前重新加载 VM。
示例输出:
homestead: Setting static IP address for Hyper-V...
==> homestead: Running provisioner: reload...
==> homestead: Running action triggers before reload ...
==> homestead: Running trigger...
==> homestead: Setting Hyper-V switch to 'NATSwitch' to allow for static IP...
homestead: Running local script: ./scripts/set-hyperv-switch.ps1
==> homestead: Attempting graceful shutdown of VM...
==> homestead: Stopping the machine...
homestead: Configuring the VM...
==> homestead: Starting the machine...
==> homestead: Waiting for the machine to report its IP address...
homestead: Timeout: 120 seconds
homestead: IP: 192.168.0.2
==> homestead: Waiting for machine to boot. This may take a few minutes...
==> homestead: Machine booted and ready!
5. 其他想法
Default Switch
在初始之后,需要手动输入来选择vagrant up
;找到解决这个问题的方法是理想的。- vagrant-reload 配置程序无法正常关闭机器,必须强制停止;鉴于这种情况只发生一次(在初始配置期间),因此这并不是什么大问题。发生这种情况的原因是,必须在重新加载之前事件期间将 VM 的 Hyper-V 交换机从 更改为
Default Switch
,NATSwitch
这实际上类似于将以太网线从物理插孔拔出并将其连接到另一个交换机。
答案2
答案3
如果您想设置开关,有一种解决方法:
config.vm.network "public_network", bridge: "VirtualSwitchName"