用 QEMU 踩的一些坑
在做项目的过程中,需要在虚拟机内进行测试,由于需要可备份与灵活性,在与学长商讨之后最终决定使用 qemu,在此记录一些使用 qemu 过程中碰到的问题和解决方案
创建虚拟机
首先,需要创建一个虚拟机,并且进行基础的配置,例如静态 IP,ssh 登录等
新建磁盘
首先创建一个 qcow2 文件,这种格式是 QEMU 支持的一种磁盘镜像格式,具有动态扩容、压缩和快照功能
1 | qemu-img create -f qcow2 ubuntu.qcow2 50G |
安装 OS
在有了磁盘镜像之后,需要给这个虚拟机装上操作系统,我选择的是 ubuntu 22.04,首先从官网下载镜像:
1 | wget https://releases.ubuntu.com/jammy/ubuntu-22.04.5-live-server-amd64.iso |
之后,由于磁盘是空的,且服务器上是无图形界面的,所以需要通过 -kernel 与 -initrd 参数来指定启动虚拟机的过程中使用的内核与初始内存磁盘,而不能直接从下载的 ISO 文件引导
所需要的文件可以从下载下来的 ISO 文件中提取:
1 | mkdir -p /tmp/iso_mount |
之后使用以下命令启动虚拟机并安装操作系统:
1 | qemu-system-x86_64 -m 4096 -smp 4 -hda k8s-c.qcow2 -enable-kvm -cpu host -nographic -cdrom ./ubuntu-22.04.5-live-server-amd64.iso -boot d -kernel ./iso/casper/vmlinuz -initrd ./iso/casper/initrd -append 'console=ttyS0' |
之后再安装过程中,会有一堆一堆的选项要我们选,基本可以全用默认选择,一路选 Done 即可,到最后会提示我们 reboot,注意这个时候如果直接 enter 去重启的话会报错:
1 | Please remove the installation medium, then press ENTER: |
这个意思是让我们把光盘拔出来,因为我们的启动命令中 -boot d 指定了从光盘启动,但是启动的光盘是通过 -cdrom 指定的虚拟光驱,所以没办法“拔”出来,解决方法是直接 ctrl+A, X 关闭 qemu,下一次手动重启即可
配网
为了保证虚拟机里面的服务能够在后台运行,并且能够在有需要的时候 ssh 上去,同时不用 tmux,我需要给虚拟机分配一个静态 IP,并且配置一个网桥,让其能够接入外网
第一步是配置网桥,过程是:
1 | # 新建网桥 |
其中 <INTERFACE> 可以是本机任何能够访问外网的网卡名
有了网桥之后,我们首先需要前台运行虚拟机,在里面配置好静态 IP,具体来说,根据如下命令启动:
1 | sudo qemu-system-x86_64 -m 4096 -smp 4 -hda http-server.qcow2 -enable-kvm -cpu host -nographic -netdev bridge,br=httpbr,id=n2 |
等到 ubuntu 长长的启动 log 结束之后(注意,这个过程中会有一个 FAILED 信息,不过问题不大,这是因为虚拟机的网络还未配置),登录 os 安装时配置的用户,然后使用 netplan 来配一下网
在 /etc/netplan/ 目录下,会有一个 50-cloud-init.yaml 文件,这是 netplan 的默认配置文件(数字代表优先级,字典序越大越靠后加载),但注意,这个是由 cloud-init 自动生成的,并且在每次重启的时候都会被覆盖!!
想要持久化配置静态 IP,我们需要禁用 cloud-init 服务,并在 50-cloud-init.yaml 里面配置,具体来说
首先将 50-cloud-init.yaml 里面的内容改成:
1 | network: |
然后通过以下命令来禁用 cloud-init 服务:
1 | echo "network: {config: disabled}" | sudo tee /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg |
之后 sudo reboot 即可
在配好之后,可以尝试一下互 ping 与 ssh,如果都可以的话,就可以通过 sudo poweroff 关闭虚拟机了
后台启动
后台启动命令是:
1 | sudo qemu-system-x86_64 -m 4096 -smp 4 -hda http-server.qcow2 -enable-kvm -cpu host -nographic -netdev bridge,br=httpbr,id=n2 -device virtio-net,netdev=n2,mac=52:54:00:12:34:58 -monitor none -serial none & |
但是 -nographic -monitor none -serial none 似乎不一定能够保证 qemu 完全不监听 stdin,所以有的时候放在后台跑的时候会被挂起,这种时候可以重定向一下:
1 | sudo qemu-system-x86_64 -m 4096 -smp 4 -hda http-server.qcow2 -enable-kvm -cpu host -nographic -netdev bridge,br=httpbr,id=n2 -device virtio-net,netdev=n2,mac=52:54:00:12:34:58 -monitor none -serial none < /dev/null & |
当我们启动之后,可以使用 jobs 命令来查看命令状态,正常情况下应该是 Running,并且可以 ping 192.168.10.2 查看,如果发现进程状态是 Stopped,可以注意一下是不是还是有某些操作需要读取 stdin,例如可能是 sudo 需要用户输入密码