外观
快照、克隆与模板
这三个功能经常被混为一谈,实际上解决的是完全不同的问题。用错了轻则浪费空间,重则丢数据。
| 功能 | 一句话 | 典型用途 |
|---|---|---|
| 快照 (Snapshot) | 给同一台虚拟机留一个可回退的时间点 | 升级前留后路 |
| 克隆 (Clone) | 复制出另一台虚拟机 | 批量部署、做测试副本 |
| 模板 (Template) | 把虚拟机冻结成只读的「母版」 | 反复快速开新机 |
快照
它做了什么
快照记录虚拟机在某一时刻的磁盘状态(可选地还包括内存状态)。之后你可以回滚到这个时刻。
创建
虚拟机 → Snapshots → Take Snapshot:
| 字段 | 说明 |
|---|---|
| Name | 用有意义的名字,比如 before-upgrade-20260922 |
| Description | 写清为什么打这个快照 |
| Include RAM | 见下文 |
Include RAM 勾不勾:
- 勾上:连内存一起保存,回滚后虚拟机继续运行在当时的状态,像什么都没发生。代价是快照占用增加(等于内存大小),创建时虚拟机会短暂暂停。
- 不勾:只存磁盘,回滚后虚拟机处于关机状态,开机相当于一次非正常关机后的启动。
一般情况不用勾 RAM
升级前打快照,不勾 RAM 就够了:出问题回滚、开机、系统自己会处理。勾 RAM 主要用于「我要保留这个正在运行的调试现场」。
回滚
Snapshots → 选中快照 → Rollback。
回滚会丢掉快照之后的所有改动
回滚到 T 时刻的快照,意味着 T 之后写入的所有数据全部消失。如果这台虚拟机上跑着数据库或者有人在用,那些数据就没了。
回滚之前:
- 确认没有人正在使用这台虚拟机。
- 如果 T 之后有值得保留的数据,先把它拷出来。
- 拿不准的话,先对当前状态再打一个快照,这样回滚之后还能再回来。
快照的代价
忘记删除的快照是空间黑洞
快照持有旧的数据块,源虚拟机写入越多,快照占用越大。「打了快照就忘了」是 local-lvm 或 ZFS 池被慢慢写满的头号原因。
给自己定个规矩:打快照的时候就想好什么时候删。 升级验证完成,立刻删掉。
查看快照占用(ZFS):
sh
zfs list -t snapshot -o name,used -s usedLVM-Thin 上看整体池占用:
sh
lvs -a哪些存储支持快照
不是所有存储都能打快照,见存储模型:
| 存储 | 快照 |
|---|---|
| LVM-Thin | 支持 |
| ZFS | 支持 |
| Ceph RBD | 支持 |
| 目录存储 + qcow2 | 支持 |
| 目录存储 + raw | 不支持 |
| 普通 LVM | 不支持 |
快照按钮是灰的,多半就是这个原因。另外,虚拟机上挂了直通设备(PCI passthrough)时通常无法打快照,这是直通的固有代价之一。
克隆
虚拟机 → 右键 → Clone。
两种模式
| 模式 | 机制 | 优点 | 缺点 |
|---|---|---|---|
| Linked Clone(链接克隆) | 只记录和源的差异 | 创建瞬间完成,几乎不占空间 | 依赖源,源不能删;性能略低 |
| Full Clone(完整克隆) | 完整复制一份磁盘 | 独立,源可以删 | 创建慢,占完整空间 |
链接克隆的依赖关系是隐性的
链接克隆必须依赖源虚拟机(或模板)的磁盘。源被删除,所有链接克隆全部损坏。 PVE 会阻止你直接删掉还有克隆依赖的模板,但如果你绕过界面在存储层操作,就没人拦着了。
链接克隆只能在支持快照的存储上创建,且源通常需要先转成模板。
一般建议:长期使用的虚拟机用完整克隆,临时测试副本用链接克隆。
克隆之后必须改的东西
克隆出来的虚拟机和源完全一样,包括客户机内部的这些:
| 项目 | 问题 | 怎么处理 |
|---|---|---|
| MAC 地址 | PVE 会自动重新生成,这项一般没问题 | 确认一下即可 |
| 主机名 | 两台同名机器会让 DNS 和日志混乱 | 进客户机改 /etc/hostname 和 /etc/hosts |
| SSH 主机密钥 | 两台机器同一个密钥,是安全问题 | 重新生成,见下文 |
| machine-id | 某些 DHCP 服务器据此分配 IP,会冲突 | 重新生成 |
| 静态 IP | 直接冲突 | 改掉 |
在克隆出来的客户机内部执行(Debian/Ubuntu):
sh
# 在克隆的虚拟机内部执行
hostnamectl set-hostname <新主机名>
# 重新生成 SSH 主机密钥
rm -f /etc/ssh/ssh_host_*
dpkg-reconfigure openssh-server
# 重新生成 machine-id
rm -f /etc/machine-id
systemd-machine-id-setup改完重启。
这就是 Cloud-Init 存在的理由
上面这套手工操作,正是 Cloud-Init 要自动化的东西。用 Cloud-Init 模板克隆时,主机名、IP、SSH 密钥、用户账号都能在首次启动时自动配好。属于自动化的内容。
模板
模板是转成只读的虚拟机,专门用来当克隆的母版。
虚拟机 → 右键 → Convert to template。
转换是单向的
虚拟机一旦转成模板,不能再改回普通虚拟机,也不能再开机。想改模板内容,标准流程是:从模板完整克隆一台 → 开机修改 → 再转成新模板。
所以转换之前,确认这台虚拟机里该装的都装了、该清的都清了。
做一个好模板
在转换之前,在客户机里做这些清理:
sh
# 在要转成模板的虚拟机内部执行
# 1. 更新到最新
apt update && apt full-upgrade -y
# 2. 装好 guest agent
apt install -y qemu-guest-agent
systemctl enable qemu-guest-agent
# 3. 清理 SSH 主机密钥(克隆后会重新生成)
rm -f /etc/ssh/ssh_host_*
# 4. 清理 machine-id
truncate -s 0 /etc/machine-id
# 5. 清理日志和 APT 缓存,让模板更小
journalctl --vacuum-time=1s
apt clean
rm -rf /tmp/* /var/tmp/*
# 6. 清理 shell 历史
history -c && rm -f ~/.bash_history然后关机,再转模板。
模板里不要留凭据
模板会被克隆很多次。里面留着的 SSH 私钥、API Token、密码文件,会随着每一次克隆扩散出去。转模板前检查一遍 /root/.ssh/、~/.bash_history 和任何配置文件里的密码。
三者怎么配合
一个典型的工作流:
- 建一台干净的 Debian,装好 agent 和常用工具 → 转成模板。
- 需要新机器时 → 从模板完整克隆 → 改主机名和 IP。
- 给新机器升级软件之前 → 打快照。
- 升级验证没问题 → 删掉快照。
- 不管做没做快照 → 定期备份到另一台机器上。
第 5 条是唯一能救「硬盘坏了」的。前四条都救不了。
检查结果
练习一遍完整流程:
- 给测试虚拟机打一个快照,在客户机里建个文件
touch /root/after-snapshot。 - 回滚到快照,确认那个文件消失了。
- 把这台虚拟机转成模板。
- 从模板完整克隆一台新的,改好主机名,开机确认能用。
- 删掉练习用的快照,确认
lvs -a或zfs list -t snapshot里空间回收了。
跑完这五步,你对这三个功能的理解就够用了。