网上看到的很多教程为PVE创建的模板,基本上是
直接下载
genericcloud类型的qcow2镜像然后导入到PVE很难直接和PVE形成完美配合,比如由于VM没有安装
qemu-guest-agent且在VM的配置中勾选了QEMU Guest Agent选项,会导致重启、关机指令等无法被VM响应进而失败的问题。而且也无法直接在PVE web UI上查看IP地址等信息;使用
libguestfs-tools的virt-customize命令定制镜像虽然这样可以实现高度的自定义并和PVE紧密配合,但是由于会修改镜像文件本身,如果genericcloud镜像更新了,就需要重新运行一遍定制指令,非常繁琐。
我感觉这些方法都不太好。和AI交流中发现,由于PVE支持snippets功能,可用于存储和引用cloud-init配置。通过使用cloudinit声明式配置,可以在不修改基础镜像的前提下,通过PVE的cloudinit配置盘,在实例首次初始化时完成系统定制。这样既可以满足定制需要,又不会对镜像文件本身产生依赖。
下载镜像并创建虚拟机
访问https://cloud.debian.org/images/clouod/下载目标镜像。我选择的镜像为trixie/latest/debian-13-genericcloud-amd64.qcow2
我跳过了创建虚拟机并将镜像导入为其磁盘的过程。并假设完成导入的虚拟机的ID为1000。值得一提的是,我选择的镜像似乎不需要新建serial0也可以正常在PVE的console中显示和操作,可能debian的兼容性做的比较好。
启用snippets功能
我计划将snippets存储在local,因此需要让local存储允许snippets,需要执行less /etc/pve/storage.cfg查看。
1 | |
发现目前支持iso,backup,vztmpl,确实没有snippets支持。为了再添加snippets支持,执行pvesm set local --content iso,vztmpl,backup,snippets。
自定义cloudinit配置
目前我需要以下功能:
- 设置时区为
Asia/Shanghai - 采用中科大镜像源
- 安装
qemu-guest-agent并在初次启动时立刻启动服务
默认情况下,在第一次安装qemu-guest-agent似乎并不会立即启动,但在重启后会被systemd识别并自动拉起。为了实现初次启动即可直接和PVE配合使用,需要在初次启动时手动运行一次服务。
因此我在/var/lib/vz/snippets/debian-13.yaml编写以下内容:
1 | |
第一行的#cloud-config是必要的,AI告诉我说这是为了声明下面的内容是声明式的Cloud Config而非普通shell脚本。
apt.generate_mirrorlists = false是用于禁止cloudinit在初次启动时生成mirrorlists。因为之前测试发现当不把这项配置覆盖为false时,会导致写入的debian.list和debian-security.list在初次启动被覆盖为默认文件内容。而我这里网不好,有时候访问不了debian的站点,只能手动设置镜像源。
配置虚拟机加载自定义cloudinit配置
执行qm set 1000 --cicustom "vendor=local:snippets/debian-13.yaml"即可。这个指令会向/etc/pve/qemu-server/1000.conf写入cicustom: vendor=local:snippets/debian-13.yaml。表示设置cloudinit自定义配置vendor=local:snippets/debian-13.yaml,也就是指定vendor-data配置来源于local存储的snippets/debian-13.yaml这个文件。