KVM建虚拟机网络连不上,绝大多数问题出在网卡配置、虚拟网络桥接、DHCP分配以及防火墙拦截上,按顺序排查即可快速定位。
kvm虚拟机无法获取ip?先检查这四处
出现kvm虚拟机无法获取ip的情况,通常不是系统坏了,而是虚拟机和宿主机之间的网络通道没有打通,我遇到过不少朋友,装完系统发现没网,第一反应是重装,其实只要按下面顺序看一遍就能解决。
检查libvirtd服务和默认虚拟网络是否正常运行
KVM的虚拟网络由libvirtd统一管理,如果这个服务没起来,虚拟机里的网卡就是空转,先确认服务状态:
systemctl status libvirtd
如果显示inactive,就启动它:
sudo systemctl enable --now libvirtd
接着看默认的NAT网络virbr0还在不在:
virsh net-list --all
正常情况下能看到一个叫default的网络,状态为active,如果是inactive,启动并设置开机自启:
virsh net-start default virsh net-autostart default
很多情况下,kvm虚拟机无法获取ip,就是因为这个default网络没有启动,虚拟机里只显示一个无人认领的eth0。
确认虚拟机网卡连接到了正确的网络
用编辑器打开虚拟机配置文件,或者直接用virsh dumpxml查看:
virsh dumpxml vm-name
重点关注<interface>部分,常见配置有两种:type=network连到虚拟网络,type=bridge连到物理桥接,如果你打算用NAT,但配置成了bridge而且宿主机没建过桥,那虚拟机肯定上不了网,反之,桥接模式却连到virbr0,也只能拿到内网地址,无法和宿主机物理局域网互通。
如果你用的是virt-manager图形界面,在虚拟机设置里打开“网络接口选择”,确认“网络源”选择的是default,还是你已经创建的桥接名称。
在虚拟机内部查看网卡状态和ip分配
登录虚拟机终端(可以使用virsh console),执行:
ip addr
看有没有类似168.122.x的地址,这个网段是KVM默认NAT分配的,如果没有,检查网卡是否被激活:
ip link set eth0 up
如果网卡是ens3、ens4这类名称,可能需要同时检查配置文件,对于Debian系,编辑/etc/network/interfaces,设置auto eth0和dhcp;对于CentOS系,编辑/etc/sysconfig/network-scripts/ifcfg-eth0,设置ONBOOT=yes、BOOTPROTO=dhcp。
这里有个容易踩的坑:虚拟机里跑的Linux发行版如果较老,可能没有现代网卡驱动,如果你在virt-manager里给虚拟机选了virtio网卡,但镜像本身没有virtio驱动,那么网卡根本不会出现,遇到这种情况,可以临时把网卡模型改为e1000,先让它识别出来,再装对应驱动。
检查宿主机防火墙和内核转发规则
NAT模式下,宿主机需要开启ip转发,否则虚拟机就算拿到地址也出不去,查看:
cat /proc/sys/net/ipv4/ip_forward
如果输出是0,临时开启:
sysctl -w net.ipv4.ip_forward=1
永久生效就修改/etc/sysctl.conf,同时查看防火墙是否放行了libvirtd的网段,在CentOS上,可能还需要:
firewall-cmd --add-service=libvirt firewall-cmd --add-service=libvirt --permanent
这是kvm虚拟机网络连接不上最为隐蔽的原因。
kvm桥接网络配置失败怎么办
很多场景下你不想用NAT,而是想让虚拟机直接暴露在局域网里,和宿主机同网段,这样就能被其他机器直接访问,但kvm桥接网络配置失败的问题也最让人头疼,因为一个不小心,宿主机自己都会掉线。
先看硬件平台和宿主机网络管理方式
不同Linux发行版配置桥接的命令不一样,Debian和Ubuntu用/etc/network/interfaces,CentOS和Rocky用nmcli或者network-scripts,在动手前,一定要先搞清楚宿主机是通过什么方式管理网络的,是用NetworkManager还是ifupdown。
如果你用的是NetworkManager,推荐直接用nmcli创建桥接:
nmcli con add type bridge ifname br0 con-name br0 nmcli con add type ethernet ifname eth0 con-name bridge-slave-eth0 master br0 nmcli con up br0
注意,执行完这条命令后,物理网卡eth0会被桥接接管,ssh连接会瞬间断开,建议你提前打开宿主机本地的终端,或者在远程操作之前把这两条命令写成脚本,在控制台执行,别在ssh窗口里直接跑。
从virt-manager界面配置桥接的细节
在virt-manager里创建虚拟机时,网络选择“桥接br0”,但虚拟机启动后仍然上不了网,这类问题多见于桥本身没建好,检查宿主机上br0是否存在、是否处于UP状态:
ip addr show br0
如果br0有ip,虚拟机网卡也选的是br0,但虚拟机内还是ping不通网关,那就把物理网卡和虚拟网卡的混杂模式打开,大多数情况下是因为没有开启混杂模式:
ip link set br0 promisc on
部分交换机还需设置允许trunk或混杂帧,这个在物理网络层面也要配合。
桥接后虚拟机内无法使用静态ip的排查
kvm桥接网络配置失败还有一个常见场景:虚拟机内手动配置了静态ip,但局域网里根本看不到它,先看ip和网关是否和宿主机在同一网段,再看DNS是否缺失,比如宿主机是192.168.1.10,虚拟机写成了192.168.10.40,那肯定不通,用arp -a在宿主机或另一台机器上看看有没有虚拟机mac地址的回应,如果没有,多半是ip冲突或者网卡没起来。
我把这些可能情况对比一下,方便你快速判断:
| 现象 | 可能原因 | 处理方向 |
|---|---|---|
| 虚拟机内网卡有ip,但ping不通网关 | 防火墙拦截或ip转发未开启 | 检查宿主机iptables、firewalld |
| 虚拟机内网卡无ip | dhcp服务没分配,或者网卡未激活 | 查看 default 网络和网卡配置文件 |
| 桥接模式下宿主机掉线 | 物理网卡配置错误,导致桥接未生效 | 恢复原配置,改用nmcli重建桥 |
| 虚拟机内能网,但只有宿主机能访问外部 | NAT模式缺少MASQUERADE规则 | 检查iptables libvirt链规则 |
kvm创建虚拟机网络不通时,用最短路径解决
如果你不想深究原理,kvm创建虚拟机网络不通时,可以直接按这套逻辑来,先确认虚拟机能不能四层握手,再看是不是网关丢了。
从虚拟机往外ping的测试顺序
在虚拟机内执行:
ping 127.0.0.1 # 自身协议栈 ping <宿主机ip> # 虚拟网络链路 ping <网关ip> # 默认网关和转发 ping www.baidu.com # 域名解析和外网
哪一步不通,就卡在哪一步,大多数情况下,卡在宿主机这一层,说明宿主机NAT或桥接配置有问题;卡在网关或外网,说明虚拟机的路由表和DNS没配好。
如何快速重置KVM网络环境
如果你改乱了多个配置,不如直接恢复默认网络:
virsh net-destroy default virsh net-undefine default systemctl restart libvirtd
这样会重新生成一个干净的virbr0,然后把虚拟机xml里interface改成type=network,source default,再启动虚拟机,大概率就能连上,这个方法我在很多kvm虚拟机网络连接不上的案例里验证过,简单粗暴有效。
为什么有时候重启宿主机才能解决
部分情况下是因为内核模块或者dnsmasq缓存出了问题,KVM的default网络依赖dnsmasq分配ip,如果dnsmasq进程异常,虚拟机内网卡能看到链路,但始终获取不到地址,这时重启一下libvirtd比重启整台宿主机更快:
systemctl restart libvirtd dnsmasq
很多网友反应重启一次宿主机后才正常,其实就是因为libvirtd服务重启的同时重置了dnsmasq,建议遇到此类问题先重启服务,别急着重启物理机。
从nat切换到桥接后网络不通的解决思路
kvm桥接和nat的切换是高频操作,一个典型场景是,你之前用默认NAT,虚拟机可以上网,然后为了搭建服务或者做端口映射,改成桥接模式,结果虚拟机立刻失联,这种情况不是配置错了,而是虚拟机内部的网络参数还停留在NAT网段里。
清除虚拟机内旧的DHCP租约
如果你用的是DHCP,桥接网络分配的ip段和NAT完全不同,虚拟机内可能存在旧的租约缓存,尤其是systemd-networkd或dhclient保存的/var/lib/dhcp/dhclient.leases,最简单的办法是在虚拟机内:
ip addr flush eth0 dhclient -r eth0 dhclient eth0
或者直接重启虚拟机的网络服务。
检查虚拟机网关是否还是virbr0的ip
桥接模式下,虚拟机网关应该是物理局域网的路由器,比如192.168.1.1,而不再是192.168.122.1,很多人在虚拟机内手动把网关写成原来的地址,导致出口报文找不到回包路径,用ip route查看当前路由,如果默认路由是192.168.122.1,就把它改掉:
ip route del default ip route add default via 192.168.1.1 dev eth0
然后再测试外网连通性。
宿主机防火墙不要忽略
从NAT切换到桥接后,宿主机上的防火墙策略也需要调整,NAT模式下libvirtd会插入iptables规则做地址转换,而桥接模式直接走二层协议,不依赖这些规则,但宿主机自身的firewalld或ufw仍然可能拦截来自虚拟机物理网口的流量,如果你在宿主机开了防火墙,需要在对应区域放行物理网卡接口的流量,否则虚拟机网卡明明拿到了IP,但业务依旧不通。
几个常见问题快问快答
kvm虚拟机网络连接不上,但宿主机正常,该从哪里开始查?
先执行virsh net-list --all确认default网络在不在,然后virsh console进虚拟机看ip addr,如果两者都正常就测试双向ping,如果虚拟机ping不通宿主机,检查iptables的FORWARD链,这条链默认可能被设置为DROP。
kvm桥接网络配置失败和NAT有什么区别?
NAT模式下,虚拟机通过宿主机转发对外通信,外网无法直接访问虚拟机,适合个人测试;桥接模式下,虚拟机就像局域网里的另一台物理机,直接占用一个普通IP,适合需要对外提供服务的场景,如果你用桥接连不上网,优先查物理网卡是否正常工作,再查交换机端口配置。
kvm虚拟机无法获取ip,会不会是虚拟机系统镜像的问题?
可能性较低,但老兄你也别排除,部分精简过的镜像没有带通用网卡驱动,尤其是你选择virtio网卡时,可以先换用e1000网卡模型测试,如果换了就拿到ip,说明是驱动缺失,而不是网络配置问题,等确认网络通了,再换回virtio并安装对应的virtio-win或内核驱动。