Linux Libvirt (KVM) 虚拟机有IP无网络连接
·
在Linux宿主机通过libvirt安装的kvm虚拟机,能看到IP,但是却不能联网。我碰到这种情况是因为有docker在运行。是 Docker 和 Libvirt (KVM) 在 iptables 规则上的冲突。
简单来说:Docker 启动时会重写防火墙规则,它通常会默认拦截所有非 Docker 管理的转发流量。因为你的虚拟机(通过 virbr0 网卡)发出的流量属于“非 Docker 流量”,所以被 Docker 的防火墙规则丢弃了,导致无法连网。
虽然 DHCP(分配 IP)工作正常(因为这是在虚拟机内部或 Libvirt 的 dnsmasq 层面处理的),但数据包一旦要跨出虚拟机访问外网,就会被拦截。
为了让规则在 Docker 重启后依然有效,最优雅的方法是利用 Libvirt Hook 脚本。每当 Libvirt 启动虚拟机或网络时,自动插入这些规则。
创建 Hook 脚本目录:
sudo mkdir -p /etc/libvirt/hooks
创建脚本文件:
sudo vim /etc/libvirt/hooks/qemu
(注:如果该文件已存在,请将内容追加进去)
写入以下内容:
#!/bin/bash
# Fix for Docker + Libvirt network conflict
if [ "${1}" = "prepare" ]; then
# 允许 virbr0 的流量转发
if ! iptables -C FORWARD -i virbr0 -j ACCEPT 2>/dev/null; then
iptables -I FORWARD 1 -i virbr0 -j ACCEPT
fi
if ! iptables -C FORWARD -o virbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null; then
iptables -I FORWARD 1 -o virbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT
fi
# 确保 NAT 规则存在
if ! iptables -t nat -C POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE 2>/dev/null; then
iptables -t nat -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE
fi
fi
这是一个 Bash 脚本,它会检测虚拟机是否在准备启动,并修补 iptables 规则。
赋予执行权限:
sudo chmod +x /etc/libvirt/hooks/qemu
重启 Libvirt 守护进程:
sudo systemctl restart libvirtd
更多推荐



所有评论(0)