A.19.3. 客户机失败的 PXE 引导(或 DHCP)
- 症状
- 客户机虚拟机可以成功启动,但随后无法从 DHCP 获取 IP 地址或使用 PXE 协议引导。此错误有两个常见原因:为网桥设置了很长时间,当 iptables 软件包和内核不支持 checksum mangling 规则时。
- 网桥上的 forward 延迟时间
- 正在调查
- 这是此错误的最常见原因。如果客户机网络接口连接到启用了 STP(Spanning Tree 协议)的桥接设备,并且设置了长的延时,则网桥将不会将网络数据包从客户机虚拟机转发到网桥,直到在客户机连接到网桥以来至少经过转发延迟秒数。此延迟允许网桥时间监控来自接口的流量,并确定其后面的 MAC 地址,并阻止网络拓扑中的转发循环。如果转发延迟比客户机的 PXE 或 DHCP 客户端的超时时间更长,客户端的操作将失败,并且客户机将无法引导(如果是 PXE),或者无法获取 IP 地址(如果是 DHCP)。
- 解决方案
- 如果是这种情况,请将网桥的转发延迟更改为 0,在网桥中禁用 STP,或者同时更改这两者。注意只有网桥不使用多个网络来连接多个网络,但只是将多个端点连接到一个网络(由 libvirt使用的网桥,最常见的用例)才适用。如果客户机具有连接到 libvirt- 管理的虚拟网络的接口,请编辑网络的定义,然后重新启动它。例如,使用以下命令编辑默认网络:
# virsh net-edit default
在<bridge>
元素中添加以下属性:<name_of_bridge='virbr0'
delay='0' stp='on'
/>注意delay='0'
和stp='on'
是虚拟网络的默认设置,因此仅当从默认修改配置时才需要这个步骤。如果客户机接口连接到在 libvirt 之外配置的主机网桥,请更改延迟设置。在/etc/sysconfig/network-scripts/ifcfg-name_of_bridge
文件中添加或编辑以下行,以使用 0 秒打开 STP:STP=on DELAY=0
更改配置文件后,重启网桥设备:/usr/sbin/ifdown name_of_bridge /usr/sbin/ifup name_of_bridge
注意如果 name_of_bridge 不是网络中的 root 网桥,则该网桥的延迟最终会重置为 root 网桥的延时。要防止这种情况的发生,请在 name_of_bridge 上禁用 STP。
- iptables 软件包和内核不支持 checksum mangling 规则
- 正在调查
- 只有当所有四个条件都为 true 时,这个信息才会出现问题:
- 客户机使用 virtio 网络设备。如果是这样,配置文件将包含
model type='virtio'
- 主机已加载
vhost-net
模块。如果ls
没有返回空结果,则会出现这种情况。/dev/vhost-net
- 客户机尝试从主机上直接运行的 DHCP 服务器获取 IP 地址。
- 主机上的 iptables 版本早于 1.4.10。iptables 1.4.10 是第一个版本,用来添加
libxt_CHECKSUM
扩展。如果 libvirtd 日志中出现以下信息,会出现这种情况:warning: Could not add rule to fixup DHCP response checksums on network default warning: May need to update iptables package and kernel to support CHECKSUM rule.
重要除非此列表中的所有其他条件也是 true,否则上述警告消息可以忽略,并且不是任何其他问题的指示符。
当出现这些条件时,从主机发送到客户机的 UDP 数据包具有取消计算的校验和。这使得主机的 UDP 数据包在客户机的网络堆栈看起来无效。 - 解决方案
- 要解决这个问题,使上述任何四点无效。最佳解决方案是将主机 iptables 和内核更新至 iptables-1.4.10 或更新版本。否则,最具体的修复是禁用这个特定虚拟机的
vhost-net
驱动程序。要做到这一点,使用以下命令编辑客户机配置:virsh edit name_of_guest
在<driver>
部分更改或添加<interface>
行:<interface type='network'> <model type='virtio'/> <driver name='qemu'/> ... </interface>
保存更改,关闭 guest,然后重新启动它。如果问题仍未解决,则问题可能是 firewalld 和默认的 libvirt 网络之间的冲突。要解决这个问题,使用 service firewalld stop 命令停止 firewalld,然后使用 服务 libvirtd restart 命令重启 libvirt。
注意另外,如果正确配置了/etc/sysconfig/network-scripts/ifcfg-network_name
文件,您可以确保客户机使用 dhclient 命令作为 root 用户获取 IP 地址。