外观
Cloud-Init:十秒钟开一台配好的虚拟机
快照、克隆与模板里提到过:克隆出来的虚拟机主机名、SSH 密钥、IP 都和源一模一样,得进去手动改。Cloud-Init 就是用来自动化这一步的——虚拟机第一次开机时,自己完成这些配置。
为什么需要它
普通模板克隆出来是「复制粘贴」,Cloud-Init 模板克隆出来是「按需定制」。装一次 Cloud-Init 模板,之后每次克隆只需要填几个字段(主机名、IP、SSH 公钥),虚拟机开机时自己把这些写好,不用再手动进去改 /etc/hostname、重新生成 SSH 主机密钥。
它的代价是:不能拿普通 ISO 装的系统直接用,必须从各发行版官方提供的云镜像 (cloud image) 开始——这类镜像里已经预装了 cloud-init。
开始之前
- 已理解快照、克隆与模板,尤其是链接克隆和模板的关系。
- 准备一个官方云镜像,通常是
.qcow2文件:- Debian:
https://cloud.debian.org/images/cloud/,选对应版本代号(Trixie 对应 PVE 9)的generic或genericcloud镜像。 - Ubuntu:
https://cloud-images.ubuntu.com/。
- Debian:
云镜像和安装 ISO 不是一回事
云镜像是一个已经装好系统的磁盘镜像,不需要走安装向导,直接当磁盘导入虚拟机就能启动。具体文件名随版本更新,去官方目录里找当前 Trixie(Debian 13)对应的最新镜像,不要用别处转存的文件。
操作步骤
第一步:下载云镜像到宿主机
sh
# 在宿主机 shell 执行
cd /var/lib/vz/template/iso/
wget <云镜像下载地址>第二步:建一台空虚拟机
不挂 ISO,只搭骨架:
sh
# 在宿主机 shell 执行
qm create 9000 --name cloudinit-template --memory 2048 --net0 virtio,bridge=vmbr0 --scsihw virtio-scsi-single9000 只是示例 VMID,选一个还没用过的编号。
第三步:把云镜像导入成磁盘
sh
# 在宿主机 shell 执行
qm set 9000 --scsi0 local-lvm:0,import-from=/var/lib/vz/template/iso/<下载的镜像文件名>import-from 直接把云镜像文件转换成这台虚拟机的 scsi0 磁盘,存储换成你自己的(ZFS、LVM-Thin 都行,参考存储模型)。
第四步:加上 Cloud-Init 驱动
sh
# 在宿主机 shell 执行
qm set 9000 --ide2 local-lvm:cloudinit这会生成一张小容量的 CD-ROM,PVE 每次按配置生成 Cloud-Init 数据(主机名、网络、密钥)写进去,虚拟机开机时读取它完成配置。每台 Cloud-Init 虚拟机都必须挂这张盘。
第五步:设置启动顺序、可选串口控制台
sh
# 在宿主机 shell 执行
qm set 9000 --boot order=scsi0
# 可选:不少云镜像默认走串口输出,接上更容易看到开机日志
qm set 9000 --serial0 socket --vga serial0第六步:转成模板
sh
# 在宿主机 shell 执行
qm template 9000转完之后这台「虚拟机」变成只读模板,用法见快照、克隆与模板。
第七步:克隆并填 Cloud-Init 参数
先克隆:
sh
# 在宿主机 shell 执行
qm clone 9000 101 --name web01 --full再到 虚拟机 101 → Cloud-Init 标签页填参数,或用命令行:
| 字段 / 选项 | 作用 |
|---|---|
ciuser | 覆盖镜像默认账号的用户名 |
sshkeys | 追加的 SSH 公钥(OpenSSH 格式),优先用它而不是密码 |
cipassword | 设置密码。多数发行版的旧版 Cloud-Init 不支持存哈希后的密码,稳妥起见还是用密钥 |
ipconfig0 | 网络配置,例如 ip=192.168.1.101/24,gw=192.168.1.1;填 ip=dhcp 走 DHCP |
nameserver / searchdomain | 不填则继承宿主机的 DNS 设置 |
cicustom | 用自己写的 user-data / network-data / meta-data 文件整个替换掉自动生成的部分,文件放在支持 snippets 的存储上 |
命令行示例:
sh
# 在宿主机 shell 执行
qm set 101 --ciuser debian --sshkeys ~/.ssh/id_rsa.pub --ipconfig0 ip=192.168.1.101/24,gw=192.168.1.1改完参数别忘了让它生效
虚拟机第一次冷启动时会自动生成 Cloud-Init 镜像并应用配置。如果虚拟机已经启动过、你又改了 Cloud-Init 参数,需要在 Cloud-Init 标签页点 Regenerate Image(或执行 qm cloudinit update 101),再重启,新配置才会生效——尤其是用 cicustom 自定义文件时,PVE 不会自动侦测文件内容变化,必须手动点一次。
开机:
sh
# 在宿主机 shell 执行
qm start 101检查结果
虚拟机 101 → Summary能看到你设置的 IP,说明网络配置生效(同时也说明 guest agent 在工作,见 VirtIO 驱动与 QEMU Guest Agent)。- SSH 用设置的密钥能直接登录,不需要密码。
- 容器内确认主机名:
sh
# 在虚拟机内部执行
hostnamectl应该显示你在克隆时填的名字,而不是模板的名字。
- 想看 PVE 实际生成了什么,在宿主机执行:
sh
# 在宿主机 shell 执行
qm cloudinit dump 101 user
qm cloudinit dump 101 network常见问题
开机后卡住,看不到任何输出。 检查是否接了 --serial0 socket --vga serial0,很多云镜像默认把控制台输出到串口而不是显示器。
改了 IP、密钥之后不生效。 虚拟机已经启动过一次,需要点 Regenerate Image(或 qm cloudinit update <vmid>)后重启,见上文。
装系统时认不到 VirtIO 磁盘 / 网卡。 云镜像内核已经内置 VirtIO 驱动,通常不会有这个问题;如果确实认不到,检查磁盘总线是否用了 virtio-scsi-single / virtio-scsi-pci 这一类 VirtIO 控制器。
cipassword 登录不了。 一些发行版的 cloud-init 版本不支持哈希密码,PVE 会存一份加密后的密码,旧版 cloud-init 可能读不懂。稳妥做法是只用 sshkeys,不设密码登录。