KVM 还是容器?个人站长单机虚拟化实战:Proxmox VE 部署、磁盘格式、快照备份与网络配置

为什么个人站长该认真考虑虚拟化

很多人对"虚拟化"的印象还停留在机房里的重型设备上,觉得那是企业才用得起的玩意儿。其实恰恰相反,一台 8G 内存的独服或者一台像样的 KVM VPS,用上虚拟化之后能带来的收益,对个人站长来说是立竿见影的。我自己从 2021 年开始把手上几台机器陆续改成 Proxmox VE 单机跑,到今天我可以说:这是我做站长这些年里,投入产出比最高的一次技术改造。

先说最直观的三个好处。第一是**隔离**。以前我把 Nginx、MySQL、Redis、还有几个爬虫脚本全塞在一台机器上,一个脚本写了个死循环把内存吃光,整台机器连 SSH 都进不去,只能去后台发工单重启。现在每个服务一个容器或者虚拟机,哪个炸了都不影响其他人。第二是**快照**。要给 MySQL 做版本升级,以前得先 mysqldump 全量、再停服务、再换版本、再导入,步步惊心。现在一句话:先打快照,升级,不行就回滚,整个过程三分钟。第三是**迁移**。换机房的时候,以前是重新装环境、重新拷数据、重新调配置,一个周末就没了。现在备份成镜像文件传过去恢复,半小时搞定。

这篇文章我会把个人站长用得上的部分讲透:KVM 和容器到底怎么选、Proxmox VE 装完必须做的几件事、虚拟机磁盘格式怎么挑、快照和备份的区别、网络怎么配桥接、以及几个我自己踩过的坑。不涉及集群和高可用,那是另一个量级的话题,单机场景用不上。

KVM、LXC 和 Docker:先搞清楚你需要的隔离级别

很多人一上来就纠结"用 KVM 还是 Docker",其实这两个不是二选一的关系,它们解决的隔离层级完全不同。

KVM 是全虚拟化,它模拟出一整套硬件(CPU 指令、磁盘控制器、网卡),跑的是完整的内核。你在里面装 Ubuntu 还是 CentOS 还是 Windows 都行,别人从外面看不出这是虚拟机。代价是每个虚拟机要吃掉一份完整内核的内存(通常 100-300M 启动开销),而且启动比容器慢,CPU 密集场景还有虚拟化开销。

LXC 是系统级容器,它共享宿主机内核,但给每个容器一套独立的用户空间、独立的进程树、独立的网络栈。你进去之后的感觉和一台独立机器几乎一样,能 systemd、能装软件、能改配置,但它的内核是共用的。所以 LXC 的"发行版"实际上受限于宿主内核——宿主机是 6.1 的内核,你在容器里装 Debian 13 是没问题的,但容器里不能自己换内核。

Docker 是应用级容器,隔离的是单个进程,共享的东西更多,启动是毫秒级,但它默认没有 init 系统,你没法像在 LXC 那样"进去当一台机器用"(虽然能 exec 进去,但思想上是不同的)。

我的选择原则很朴素,你可以直接抄:

需要**跑不同内核**、需要**给别人用(比如朋友的博客)、需要跑 Windows** 的场景,用 KVM。比如我要跑一个老版本的 CentOS 7 来做兼容性测试,或者要跑一个 Windows 环境跑某个只能在 Windows 上跑的工具,那就是 KVM。需要**长期运行的服务**(Nginx、MySQL、Redis、Grafana 这类),但不需要改内核的,用 LXC。需要**一次性任务、无状态服务、快速扩缩**的,用 Docker。在 Proxmox 里 LXC 是原生支持的,你不需要额外装 Docker。

顺便说一个常见的误区:很多人觉得"容器不如虚拟机安全,因为共享内核"。这话在理论层面对,但在实践层面,对个人站长来说,LXC 的隔离已经远远够用了。真正需要担心的安全边界是"不可信用户",而不是"你自己部署的 Nginx"。如果你的场景是自己部署自己的服务,LXC 的安全性不会成为短板。

Proxmox VE 装完之后必须做的七件事

Proxmox VE(简称 PVE)装好之后,那套默认配置是给企业内网环境准备的,直接拿去放公网会有一堆问题。下面这七件事是这个清单里优先级最高的,我按顺序列。

第一,把默认的 enterprise 源换成 no-subscription 源。PVE 装完之后 /etc/apt/sources.list.d/ 下会有一个 pve-enterprise.list,指向企业的仓库。你没有订阅 key,apt update 会一直报错。正确做法是把这个文件注释掉,然后新增一个 /etc/apt/sources.list.d/pve-no-subscription.list,内容写:

deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription

注意 bookworm 这个代号要和你 PVE 版本对应——PVE 8.x 是 bookworm,PVE 7.x 是 bullseye。换完之后再 apt update,就不报错了。

第二,关掉那个烦人的订阅提示。每次登录 PVE 的 Web UI 都会弹一个"你没有有效订阅"的对话框,虽然不点"确定"也能用,但很烦。稳妥的做法不是去改 JS 文件(那个每次 PVE 更新都会被覆盖),而是接受它——或者用社区维护的那套 usr/share/javascript 的替换脚本,但你要清楚升级后会失效。我个人的做法是忍着,反正一天也就看一次。不过我要提醒一句:网上那些教你改 `/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js` 的文章,改完记得升级后重做,否则会失效,也别在生产环境用奇怪的方式来绕过。

第三,配置邮件通知。PVE 默认用 postfix 往 root@localhost 发邮件,也就是发到哪里都收不到。你需要在 Datacenter → Notifications 里面配置一个真实的 SMTP 服务器,或者至少装一个 mail 命令 + 一个中继。这个很重要,因为备份失败、磁盘空间告警、ZFS 池降级这些重要事件都是靠邮件通知的。不配邮件,等于你的告警系统根本不存在。

第四,把 Web UI 的 8006 端口收口。PVE 的 Web UI 监听在 8006,默认对全网开放。如果不做处理,你的 root 密码就是唯一的防线。最稳妥的做法是防火墙只允许你自己的 IP 访问,或者用 SSH 端口转发:`ssh -L 8006:127.0.0.1:8006 user@host`,然后本地浏览器访问 https://127.0.0.1:8006。后者更安全,因为 8006 完全不用对公网开放。我自己是用 WireGuard 连回内网再访问,也是同理。

第五,开启二维验证码。PVE 支持 TOTP(就是 Google Authenticator 那套)。路径是 Datacenter → Permissions → Two Factor。开了之后即使密码泄露,攻击者也进不来。这个功能是免费的,但有大量的人不用,非常可惜。

第六,检查存储配置。PVE 装完之后默认会创建一个 local 存储(放 ISO 和备份)和一个 local-lvm(放虚拟机磁盘)。如果你机器上有多块盘,要在这里把它们加进去。我的建议是:系统盘只放 PVE 本身,虚拟机磁盘放在单独的一块 SSD 上,备份放在一块大容量 HDD 上。这样即使系统盘挂了,你的虚拟机和数据都还在。

第七,规划好 IP 和网关。PVE 装的时候会让你设一个静态 IP,这个 IP 就是管理地址。在 Datacenter → Node → System → Network 里能看到 vmbr0 这个桥接网卡。这个桥接网卡承担了虚拟机和外界通信的任务,后面配置虚拟机网络的时候会用上。默认情况下它绑定物理网卡,配置里通常长这样:

auto vmbr0
iface vmbr0 inet static
    address 192.168.1.10/24
    gateway 192.168.1.1
    bridge-ports enp3s0
    bridge-stp off
    bridge-fd 0

注意这里的 enp3s0 要换成你自己的物理网卡名(用 ip link 查看)。如果你改了这一段,记得用 `ifreload -a` 应用,千万不要直接重启网络,否则可能把自己关在门外。如果是远程操作,建议先写一个 `(sleep 300 && reboot) &` 之类的保命定时任务。

虚拟机磁盘格式:qcow2 和 raw 到底怎么选

这是很多人忽略但影响很大的一个选择。PVE 在创建虚拟机的时候会问你要不要用 qcow2,很多人随手就点了"是",结果性能损失了一截还不知道原因。

raw 格式就是原始的块设备映像,没有元数据开销,读写效率最高。代价是它**不支持快照**(在非 ZFS/LVM-thin 的存储上),而且是预先分配空间的——你建一个 100G 的磁盘,它立刻占 100G。在文件系统上它是稀疏文件(sparse file),所以实际磁盘占用可能一开始很小,但你要清楚这一点。

qcow2 格式支持快照、支持压缩、支持加密,写入的时候有写时复制(COW)的开销。性能上大概比 raw 慢 5% 到 15%,具体取决于工作负载。对磁盘 IO 敏感的服务(比如 MySQL 跑高并发写),这个损失是可以感知的。

我的建议是这样的:如果你用的是 local-lvm(LVM-thin),直接用 raw,因为 LVM-thin 本身支持快照,你不需要 qcow2 也能打快照,白白损失性能不划算。如果你用的存储是普通的目录(dir storage),那 qcow2 更方便,因为快照功能是 PVE 层面提供的,不依赖存储。

另外还有一个更重要的选择:**要不要用 SSD 直通或者 NVMe 直通**。如果你有一整块 NVMe 盘专门给虚拟机用,最理想的做法是用 PCIe Passthrough 把它直通给某个虚拟机,这样虚拟机里看到的就是真实硬件,性能几乎无损。代价是这块盘不能再被其他虚拟机使用。对个人站长来说,这个技巧在跑数据库的虚拟机上特别值。

虚拟机的磁盘缓存模式也要说一句。PVE 里每个磁盘有 cache 选项,常见的有 none、writeback、writethrough、directsync。默认的 none 意味着虚拟机的写入直接到存储层,最安全但最慢。writeback 最快,但在宿主机崩溃的时候存在数据丢失风险(因为写缓存还在宿主机内存里没落盘)。我的取舍是:数据库类的虚拟机用 none 或者 writethrough,追求一致性;普通的 Web 服务可以用 writeback 换性能。

快照不是备份:这个区别值得反复强调

我见过太多人把快照当成备份,然后在真实故障里付出了惨痛代价。这两者的区别,值得单独拿一节来讲清楚。

快照(snapshot)是某一时刻磁盘状态的"引用"。它的实现原理是写时复制:创建快照之后,原本的数据块被标记为只读,任何新的写入都会写到新的块上,快照指向的还是旧块。所以快照非常快、几乎不占额外空间(只要你不改数据)。但是!快照**和原始磁盘存在同一个存储池里**。如果那块盘物理损坏了,快照和原始数据一起灰飞烟灭。而且如果快照链很长,性能会逐渐下降。

备份(backup)是数据的完整副本,存到一个**独立的、可以离线**的位置。PVE 的备份功能(vzdump)生成的是 vma 格式(KVM)或者 tar.lzo/tar.zst(LXC)的文件,你可以存到别的磁盘、NAS、甚至 rsync 到异地。

所以正确的用法是:快照用于"操作前的临时保险",比如升级 MySQL 前打一个,改错了立刻回滚;备份用于"长期的、灾难性的恢复",每天或者每周跑一次,存到异地。快照在事务完成之后就应该删掉,不要留着当备份用。

PVE 的备份计划在 Datacenter → Backup 里配,你可以选存储位置、保留策略(保留最近 N 个、每天一个保留 M 天、每周一个保留 K 周)、压缩方式(zstd 是性能和质量平衡最好的)、以及快照模式(snapshot mode 会先打临时快照再备份,避免停机)。对 MySQL 这类一致性敏感的服务,我强烈建议先用 mysqldump 导出一份逻辑备份到虚拟机内部,再做整机备份,这样粒度更细、恢复更快。

还有一个细节:**备份一定要验证**。你们有没有遇到过那种情况,备份文件每天都在生成,体积也正常,但真到恢复的时候发现是空的或者损坏的?这就是没有做恢复演练。我的做法是每个月挑一个备份文件,在一个临时虚拟机里试着恢复一次,看看能不能起来、数据对不对。这个动作不需要很久,但能救命。

网络配置:桥接、NAT 和 VLAN

PVE 的网络模型其实不复杂,但第一次接触会被"桥接""VLAN aware"这些概念绕晕。

默认的 Linux Bridge(vmbr0) 是最常用的模式。宿主机所有网络接口都桥接到这个虚拟交换机上,虚拟机通过它直接获取 IP,和宿主机在同一个局域网,对外显示为独立的机器。这是最简单也最常用的方式,个人站长 90% 的场景用这个就够了。

如果你想让虚拟机**和宿主机用不同的网段**、或者你有公网 IP 但只有几个、想给虚拟机分 NAT 内网 IP,那就要用 NAT 模式。做法是创建一个虚拟网桥(不绑定物理网卡),然后在宿主机上做 SNAT/DNAT。举例:虚拟网桥 vmbr1 用 10.0.0.0/24 网段,然后:

# 开启转发
sysctl -w net.ipv4.ip_forward=1
# 出站 SNAT
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o vmbr0 -j MASQUERADE
# 入站端口转发(把公网 8080 转到虚拟机 10.0.0.5 的 80)
iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 8080 -j DNAT --to 10.0.0.5:80

注意 MASQUERADE 那条必须放在 FORWARD 链允许之后,否则包会被 FORWARD 链 DROP 掉。而且这些 iptables 规则默认重启就没了,要持久化得用 iptables-persistent 或者写到 /etc/network/interfaces 的 post-up 里。这也是为什么我更推荐桥接——NAT 的规则维护成本高很多。

VLAN aware 是 Proxmox 网桥的一个开关,打开之后你可以在虚拟机网卡上指定 VLAN tag,实现真正的二层隔离。对个人站长来说一般用不上,除非你有很多租户要彻底隔离。但如果你要这么干,注意交换机端口必须配成 trunk,否则 VLAN tag 会被丢弃。这个坑我踩过,当时排查了一晚上。

还有一个很实用的小技巧:**给宿主机和虚拟机都配上 IPv6**。现在很多云厂商和机房都免费给 IPv6,虚拟机通过桥接就能拿到,配置方式和 IPv4 类似,只是多一个 `iface vmbr0 inet6 static`。

几个真实的踩坑记录

最后说几个我自己遇到过的、别人文章里不常提的坑,都是我花了不少时间才搞明白的。

坑一:内存超售(overcommit)导致虚拟机莫名 OOM。PVE 默认允许内存超售,也就是你给 4 个虚拟机每个分 4G,但宿主机只有 8G 内存,PVE 也让你分。这在桌面虚拟化场景下是合理的设计(因为虚拟机不是同时用满内存),但如果你跑的是内存密集型的服务,这个超售就是灾难。表现是:虚拟机里的进程莫名被 OOM Killer 杀掉,但看虚拟机自己的 free 又显示内存充足。因为**宿主机没内存了**,它直接杀了虚拟机里占内存最多的进程。解决办法是在虚拟机的 Memory 设置里勾选 "Ballooning Device" 的同时给一个合适的 min memory,或者干脆给宿主机预留足够内存(Datacenter → Node → System → 有个 "ksm" 和内存分配相关的配置)。更简单粗暴的:别超售,或者至少把关键虚拟机的内存锁住(用 `-lock` 或 PVE 的 "Memory Locking")。

坑二:snapshot 模式下备份导致虚拟机卡顿。vzdump 的 snapshot 模式在备份开始时会创建一个临时快照,然后从快照读数据。如果备份时间很长(比如虚拟机磁盘很大),这个临时快照会累积大量 COW 数据,导致后续的写入变慢,虚拟机响应变卡。表现是:每天凌晨备份的时候,你的博客就变慢。缓解办法是把备份时间避开访问高峰,或者用 stop 模式(代价是短暂停机),或者用更快的存储做备份目标。

坑三:改了宿主机 hostname 之后,PVE 的 cluster 相关服务起不来。PVE 这个系统对 hostname 和 /etc/hosts 的一致性要求很高。如果你只改了一边,重启之后 pve-cluster 服务会失败,Web UI 直接打不开。正确做法是两个地方都改,而且 /etc/hosts 里要有对应的条目,改完重启。如果你已经改坏了,可以在单用户模式下把 /etc/hosts 改回来,或者用 `pmxcfs -l` 这种调试模式启动。

坑四:LXC 容器里装了 Docker,然后容器启动失败。LXC 默认不允许嵌套容器,因为 Docker 需要一些内核特性(比如 cgroup 的某些控制器),而这些特性在 LXC 默认配置下是不开放的。要让容器里跑 Docker,你需要在容器的配置文件(/etc/pve/lxc/<vmid>.conf)里加上 `features: nesting=1`,并且内核需要开启相应的支持。这个配置在 PVE 的 Web UI 里叫 "Features: Nesting"。或者你可以在创建容器的时候选 "unprivileged container",然后把需要的权限打开。这一条我强烈建议:**优先用 KVM 跑 Docker,而不是嵌套在 LXC 里**,省心太多。

坑五:备份文件堆满了 local 存储。PVE 默认保留策略如果不设置,备份会无限累积,直到把 local 存储撑爆。撑爆之后 PVE 可能连 Web UI 都写不进去。所以备份保留策略一定要配,而且定期去 Datacenter → Storage 里看看剩余空间。我建议保留策略设成:每天一个保留 7 天、每周一个保留 4 周、每月一个保留 6 个月,这样三层足够应对大多数场景。

小结:个人站长的虚拟化最佳实践

如果你读到这里,我把整篇文章的结论浓缩成一份可以直接抄的清单:

第一,**单机 Proxmox VE 是个人站长虚拟化的最佳起点**。它免费、功能完整、社区活跃,比 VMware ESXi 更适合个人(ESXi 免费版限制多),比 Windows 的 Hyper-V 更省资源。装一台 PVE,你等于拥有了企业级的虚拟化能力。

第二,**服务分层**。宿主机只跑 PVE 本身,Nginx/PHP/MySQL 这些应用放进 LXC 或 KVM,数据库和需要高性能的放进 KVM 并考虑 NVMe 直通。不要把所有东西塞进宿主机。

第三,**快照和备份分开用**。快照是操作保险,用完即删;备份是灾难恢复,定期做、异地存、要演练。

第四,**网络优先用桥接**,NAT 只在 IP 不够的时候用,VLAN 只在真需要隔离的时候用。

第五,**Web UI 不要暴露公网**,用 SSH 隧道或者 WireGuard,再开个 TOTP。

第六,**备份保留策略必须配置**,否则迟早撑爆磁盘。

虚拟化不是银弹,它有自己的复杂度和学习成本。但对一个长期维护多个服务、经常要折腾升级的个人站长来说,它带来的隔离性、可回滚性、可迁移性,是绝对值得投入的。我用了三年,最大的感受是:以前改配置手抖一下可能要重装,现在手抖一下,回滚就行。这种安全感,是花钱都买不到的。

Last modification:October 1st, 2026 at 12:25 pm

Leave a Comment