Jarvis's Blog

白帽子、全栈、IoT安全专家、嵌入式系统专家

ProxmoxVE(PVE)踩坑记录

  之前入了一个四网口H310的工控板,装上了i3 8100T cpu弄了一个ITX主机来做一个高端软路由,刚开始用的是esxi上面跑了一个Openwrt,一直用得挺稳定,没啥问题。当然,esxi是基于red hat深度定制的,使用的是vmware自家的虚拟化技术,因此对于硬件要求比较苛刻,装在民用主板上,会有很多功能模块没有驱动用不了,就比如最开始连最常见的Intel I211网卡的驱动都不支持,而且竟然不支持温度监控,所以,这么不自由的系统,还是决定弃坑了,转战PVE,而PVE是基于debian开发的,虚拟化技术支持openVZ和KVM,前端用的是qemu,都是开源软件,比较自由。当然,自由带来的代价就是,一如既往,坑非常多,所以,本文总结一下我所遇到的一些烦死人的坑吧。

一、如何让管理端通过虚拟机上网

由于我用这台机器来做软路由,所以我期望的网络拓扑如下图:

其中enp1s0~enp4s0是四个物理网口,其中enp1s0~enp3s0三个网口分别连接到vmbr0~vmbr2这三个虚拟桥接网络中,这三个vmbr作为oepnwrt虚拟机的三个LAN口,其中物理网口enp4s0直通openwrt虚拟机,作为WAN口使用。

pve管理界面的网络设置如下图:

虚拟机网卡直通教程网上有很多,我这里就不再赘述了,直接上图:

即添加一个PCI设备就行,其中只要前面的设备位置04:00.0这个要对应你想要直通的网卡在系统中的位置编号才行。

然后,按照这样设置,虚拟机里WAN口应该就能正常PPPOE拨号获得IP地址了,而插在LAN口上的网线也能自动获取IP地址。

那么关键问题来了,如何让主机自动获得一个IP地址呢?我尝试过修改/etc/network/interfaces中的内容,因为在这个文件中,vmbr0~vmbr2均被配置成manual,也就是说手动设置:

auto lo
iface lo inet loopback

iface enp1s0 inet manual

iface enp2s0 inet manual

iface enp3s0 inet manual

iface enp4s0 inet manual

auto vmbr0
iface vmbr0 inet manual
        bridge-ports enp1s0 
        bridge-stp off
        bridge-fd 0

auto vmbr1
iface vmbr1 inet manual
        bridge-ports enp2s0
        bridge-stp off
        bridge-fd 0

auto vmbr2
iface vmbr2 inet manual
        bridge-ports enp3s0
        bridge-stp off
        bridge-fd 0

我本来尝试把iface vmbr0 inet manal改成iface vmbr0 inet dhcp,结果发现并不能在开机时获取一个IP,后来经过查看日志发现,系统启动的过程,是会先去请求DHCP,当所有网络接口初始化完毕后才会启动虚拟机,因此由于主机vmbr0在请求DHCP的时候,虚拟机还没启动,所以自然无法获得IP。那怎么办呢?

  后来我想了个办法,就是弄个计划任务,每隔1分钟检查vmbr0是否有IP,如果没有就去请求一个,这样就能解决问题了,脚本如下:

#!/bin/sh

vmbr0_ip=$(/usr/sbin/ifconfig vmbr0 | grep "inet " | awk '{print $2}')

if [ -z "$vmbr0_ip" ]
then
        echo "vmbr0 has no IP,get a IP"
        /usr/sbin/dhclient -4 vmbr0
else
        echo "vmbr0 already has an IP,skip.."
fi

文件命名为getip.sh,然后再crontab里面加下面一行就行:

* * * * * /root/getip.sh

注意,脚本要赋予执行权限,即chmod +x getip.sh,并且你们应该也注意到了,脚本里面的程序要写绝对路径,即/usr/bin/ifconfig,如果只写ifconfig就会因为环境变量有问题而找不到这个程序,这个是个大坑。

  保存后,每次启动系统,crontab都会去执行这个脚本,这样vmbr0就能自动获得一个IP了:

二、关于无法使用pve关闭虚拟机

  这是个大坑,因为每次重启主机,系统都会先等待所有虚拟机关闭才会执行,而我一开始不知道怎么回事,关机的qmshutdown命令一直卡死,虚拟机一点反应都没有,感觉虚拟机没有正确响应关机命令。

  后来查了一些资料才发现,这是因为QEMU设置里面开启了QEMU代理引起的:

如果一开始不知道这个设置是什么玩意开了的话,那就容易碰到这个坑。

  QEMU代理即qemu-guest-agent,是一个运行在虚拟机里面的程序,主机可以直接通过qemu-guest-agent获取虚拟机的运行状态,比如IP地址,进程列表之类的,还可以直接在虚拟机里执行命令,如果开启了这个功能,虚拟机中必须安装相对应的qemu-ga才行。然而,我实际测试,编译内核的时候把qemu-ga一起编译进去,qemu-ga可以正常运行,主机也可以正确获得虚拟机的信息。然而还是无法关机。经过分析发现,TMD竟然关机只是在虚拟机里执行/sbin/shutdown,而openwrt里面没这个命令,取而代之的叫做/sbin/poweroff。由于我的openwrt编译的是squashfs版本,所以没法修改/sbin目录,重启就会恢复原始状态,所以决定放弃QEMU代理这个设定了。

  如果关闭了qemu代理的话,主机控制虚拟机的方式就会使用最底层的ACPI信号来发送关机命令,这样就没有问题了。

P.S. 竟然QEMU agent关机的时候竟然只是执行/sbin/shutdown,一点都不智能啊,这也太sb了吧。。

SATA硬盘win10不重装迁移到nvme ssd的方法

上一篇

OpenWRT状态页面在最新Chrome中排版错乱的解决办法

下一篇
评论
发表评论 说点什么
  • kvm guest关机是个问题。不过网络方面,建议还是看看官方的pve admin guide比较好。 不需要把网卡直通给vm的,除非是host没驱动,识别不了的特殊型号。但看你用e1000,也不是什么罕见型号。网卡由host负责,每个端口指派一个vmbr[n],全部manual, pppoe那些不指定任何ip,然后你爱openwrt几个网卡就虚拟几个virtio网卡,一个或者多个(如果你打算多拨汇聚)接管pppoe的物理端口所在vmbr[n],另一堆接lan,host管理口给指定一个静态ip,接lan所在vmbr[n]即可。要分多少个vlan管虚拟机,要么就多几张虚拟网卡接剩下的vmbr[n],要么就vlan tag解决,virtio-net性能杠杠的。 我家openwrt就是这么跑的。autostart简单直接。host局域网管理,和通过openwrt上网apt-get upgrade轻松自如。proxmox ve比较多坑,集中在多节点ha上,这种单机跑linux vm,没什么问题。

  • vmbr0直接指定一个和OpenWRT同LAN段的静态IP,网关指向OpenWRT的LAN IP

    • 这样也可以的,不过就是如果以后LAN IP要改的话就得接显示器了。

  • 你好,请问两块网卡直通任一一块后开启vm guest都会导致网络断开有遇到过吗

    • 好吧,我试了一个早上都直通不了,一添加pci网卡开机就导致主机都连接不上了

  • 我是所有口都直通了,但凡有直通网卡的口每次开机就会寻找dhcp,这个怎么解决嘞?开机好慢!?

  • 原来是这样!遇到的那些问题似乎都明白了。话说能不能让它自动获取ipv6地址?slaac和dhcpv6都想要,dhcpv6只需要把dhcp改掉就行了吧

浙公网安备 33011002014706号