如何在libvirt网络中自动分配合适的IP地址?
嘿,我完全懂你的需求——不想手动硬编码IP子网,让主机自己找个没被占用的范围来配置路由模式的虚拟网络,尤其是IPv6那边,ISP给的全局前缀没准儿哪天就变了,手动配置实在闹心对吧?咱们来唠唠可行的解决办法:
IPv4 自动选子网的路子
其实libvirt本身就有省心的办法,或者你也可以自己写个小脚本搞定:
依赖libvirt自动分配:你在定义网络XML的时候,不用手动指定
<ip>标签里的address和netmask,直接写DHCP范围就行,比如:<network> <name>auto-route-v4</name> <forward mode='route'/> <ip> <dhcp> <range start='192.168.122.2' end='192.168.122.254'/> </dhcp> </ip> </network>要是默认的192.168.122.0/24子网被主机其他接口占用了,libvirt会自动探测并选用下一个可用的私有子网(比如192.168.123.0/24这类),很省心。
自定义脚本扫描:如果你想更精准控制,写个简单的脚本用
ip addr或者nmcli扫一遍主机所有接口的子网,从私有IP段(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16)里挑个没人用的,然后动态生成libvirt的XML配置,再用virsh net-define加载就行,适合自动化部署的场景。
IPv6 应对动态前缀的方案
IPv6这边确实棘手,毕竟ISP给的全局前缀没个准儿,不过也有几个靠谱的办法:
1. 用SLAAC+前缀委派
如果你的主机已经通过SLAAC拿到了全局IPv6前缀,那可以让libvirt的虚拟网络也用上这个机制,不用手动写死前缀。XML配置大概是这样:
<network> <name>auto-route-v6</name> <forward mode='route'/> <ip family="ipv6"> <dhcp> <range start='2001:db8::2' end='2001:db8::ffff'/> </dhcp> <prefix delegation="yes"/> </ip> </network>
这里的关键是开启前缀委派,让libvirt自动获取主机的全局前缀。要是ISP更新了前缀,你可能得写个小脚本监听主机的IPv6前缀变化,然后重启虚拟网络来同步新前缀。
2. ULA地址+NAT变通
要是全局前缀实在不稳定,你可以给VM分配本地唯一地址(ULA,也就是fc00::/7范围内的地址),然后在主机上配置IPv6 NAT规则,把VM的ULA地址转换成主机的全局IPv6地址。虽然这和你原本想用的route模式有点不一样,但胜在不用依赖ISP的前缀,稳定性拉满。
3. 动态生成XML脚本
和IPv4的思路类似,写个脚本定期检查主机当前的全局IPv6前缀(用ip addr show就能查到),然后自动生成对应的libvirt网络XML,再重启虚拟网络。这样不管ISP怎么换前缀,你的VM都能正常联网。
最后总结下
- IPv4:要么直接用libvirt的自动子网分配,省事儿;要么写脚本自定义扫描,灵活。
- IPv6:优先试试SLAAC+前缀委派,贴合你要的路由模式;不行就用ULA+NAT兜底,或者脚本动态跟进前缀变化。
备注:内容来源于stack exchange,提问作者Nik Tedig

