跳转到内容

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/。

云镜像和安装 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-single

9000 只是示例 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

检查结果 ​

  1. 虚拟机 101 → Summary 能看到你设置的 IP,说明网络配置生效(同时也说明 guest agent 在工作,见 VirtIO 驱动与 QEMU Guest Agent)。
  2. SSH 用设置的密钥能直接登录,不需要密码。
  3. 容器内确认主机名:
sh
# 在虚拟机内部执行
hostnamectl

应该显示你在克隆时填的名字,而不是模板的名字。

  1. 想看 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,不设密码登录。

参考资料 ​

延伸阅读 ​

Proxmox VE 非官方中文使用指南,与 Proxmox Server Solutions GmbH 无隶属关系。