Proxmox VE跑网站:装完必改的八个开关

PVE(Proxmox VE)在个人站长圈里几乎是「先用了再说」的软件:一个 ISO 装完,网页后台能开虚拟机,能看监控,能打快照,剩下的默认值一概不动。绝大多数时候这样确实能跑得很好——直到某天你在后台点了「关闭」,网页控制台直接断开,虚拟机的关机过程被硬生生打断;或者你按了 Ctrl+Alt+Del 想重启,结果只是切了个窗口;再或者你给虚拟机配了 64G 内存,开机时宿主报内存不足,可 free -h 明明显示还剩很多。

这三个现象背后是同一件事:PVE 不是一个「装完就没事」的系统,它是 KVM + LXC + 一堆自定义存储与网络抽象的集合,每一层都有几个必须手动设置的开关。这篇只讲跑网站的那台机器上真正需要的配置,不涉及集群、Ceph、HA 这些用不上的部分。

一、源与订阅:把企业源换掉是第一步

PVE 装完默认启用企业仓库,没有订阅的话每次 apt update 都会报 401,于是整台机器长期处于「无法更新」的状态。安全补丁拿不到,这是最容易被忽略的风险。

# 停用企业源
sed -i 's|^deb|# deb|' /etc/apt/sources.list.d/pve-enterprise.list
sed -i 's|^deb|# deb|' /etc/apt/sources.list.d/ceph.list

# 换成免费源(PVE 8.x / Debian 12)
echo "deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription" \
  > /etc/apt/sources.list.d/pve-no-sub.list

apt update && apt full-upgrade -y

顺手把后台那个「没有有效订阅」的弹窗关掉,文件在 /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js,改完刷新浏览器即可。这是纯前端的事,不影响任何功能,但升级 PVE 后可能被覆盖,需要重做。

升级节奏上有一条铁律:不要跟着 full-upgrade 升内核到不需要的大版本。PVE 的内核是定制版,换到不匹配的版本可能导致网络驱动失效、机器失联。稳妥做法是把内核包 pin 住,只升用户态:

apt-mark hold proxmox-kernel-6.8 pve-kernel-6.8

每半年主动评估一次是否要解 pin、升到新内核,并且先在一台不重要的机器上验证过再动生产机。

二、三个必须改的开关:关机、重启、QEMU Agent

这三条是 PVE 上最影响日常操作体验的设置,都在虚拟机的「选项」里,默认状态都不理想。

第一,关闭「使用 ACPI 关机」以外的硬关机倾向。PVE 后台点「关闭」时,如果客机里没装 QEMU Guest Agent,PVE 只能发 ACPI 信号;很多 Linux 发行版的 ACPI 默认行为是「忽略」,于是虚拟机会一直挂在那里,五分钟后 PVE 强制断电。文件系统损坏的风险就从这里来。正确做法是两步:装 agent,并且在虚拟机选项里把 QEMU guest agent 设为「启用」。

apt install qemu-guest-agent
systemctl enable --now qemu-guest-agent

装完之后,后台的「关闭」「重启」「关机」才会走正常的 guest 内部流程,而不是断电。

第二,把「启动时自动启动」打开,并设一个启动顺序。很多人在这里只勾了「开机自启」却没设顺序,结果宿主重启后所有虚拟机并发启动,IO 打满,数据库那台反而最后一个才起来。合理的顺序是:网关/反向代理 → 数据库 → 应用。每个间隔 30 到 60 秒,PVE 的启动延迟参数就是干这个的。

第三,把显示从 Default 改成 Serial terminal(或反过来)。如果你遇到过「后台控制台黑屏、键盘输入没反应」,通常是显示设备与客机不匹配。NoVNC 走的是虚拟 VGA,如果客机配置成纯串口控制台,画面就永远是黑的。反过来,纯文本服务器也可以走串口省资源。判据很简单:网页控制台能看到画面就行,看不到就换一个显示类型试试,改完需要完全关掉虚拟机再开,热重启不生效。

三、内存:ballooning 的代价与什么时候该关

PVE 的虚拟机默认开启 ballooning(内存气球),意思是宿主动态回收客机里不用的内存。听着很美,实际有两个代价:

  • 数据库、缓存类服务对 ballooning 很不友好。Redis、MySQL 的 buffer pool 会被内核认为「可用」从而被气球压走,表现为周期性的性能抖动,且现象极难归因。
  • 实际可分配内存永远小于宿主的物理内存。因为 PVE 需要保留一部分给 zfs ARC 或宿主机自身。

我的做法是分类处理:

虚拟机类型ballooning内存设置
数据库 / 缓存关闭等于实际需求,预留固定
Web 应用开启最小值 + 最大值差 2G
构建 / 测试机开启按需

如果宿主用了 ZFS 做存储,还要记得给 ARC 设上限。arc_max 不设的话,ZFS 会一直吃内存,最后 OOM Killer 干掉的是你的虚拟机进程:

# /etc/modprobe.d/zfs.conf
options zfs zfs_arc_max=4294967296

4G 上限对 32G 内存的机器是合理起点,改完 update-initramfs -u 并重启生效。

四、存储:local-lvm 与 thin provision 的空间陷阱

PVE 默认把磁盘放在 local-lvm(LVM-thin)。优点是快照和克隆几乎瞬间完成,缺点是磁盘「已分配」不等于「已占用」,而且薄池写满之后所有虚拟机一起挂掉。

这是 PVE 上最惨的一类事故:薄池到 100% 时 LVM-thin 进入只读状态,所有写操作失败,PVE 后台也起不来新进程,你需要把人从控制台里挖出来手工 lvextend。所以必须设监控:

# 薄池使用率,超过 80% 就该动手
lvs -a -o lv_name,lv_size,data_percent | grep data

# 一条命令看清楚谁占了多少
pct list; qm list

监控之外还有两个实用设置:一是给虚拟机的磁盘预留(preallocation=metadata),避免写入时才分配碎片;二是把「快照」当临时手段而不是备份——快照引用的是同一份数据,宿主的磁盘坏了,快照和原盘一起丢。

顺便说一个很常见的误判:删掉虚拟机之后空间没回来。因为 thin 池不会自动回收,需要 fstrim(虚拟机内)加 discard 选项,或者干脆重建。这是正常行为,不是 bug。

五、网络:一个网桥就够了,但要多加一层

家用/小规模环境里,vmbr0 一个网桥足够所有虚拟机上网。真正需要额外注意的是「内网隔离」和「防误暴露」两件事。

第一,不要给虚拟机分配公网 IP 直连,除非你确实要跑独立服务。更安全的模式是宿主做 NAT:所有虚拟机在 10.10.0.0/24 网段,对外只暴露宿主的 80/443,由宿主上的 Nginx 反代到内网。这样虚拟机的 SSH 端口不会出现在扫描器眼里,安全边界只在一台机器上。

第二,给 PVE 自己的 8006 管理端口加一层限制。默认它是全网可访问的,等于把整个宿主的控制权挂在公网上:

# /etc/network/interfaces 或 iptables-persistent
iptables -A INPUT -p tcp --dport 8006 -s 你的办公IP -j ACCEPT
iptables -A INPUT -p tcp --dport 8006 -j DROP

没有固定 IP 的话,至少把它挡在 WireGuard/Tailscale 内网之后,或者改成一个非默认端口再加 fail2ban。8006 被爆破是 PVE 机器最常见的入侵入口。

六、快照不是备份:三次真实的教训

PVE 的快照太好用,导致很多人以为有了快照就万事大吉。这三个场景每个都真实发生过:

  1. 改了配置要回滚,发现快照是三天前的——因为快照需要磁盘空间,你不敢每天打,于是快照成了「季度性」的东西。真正需要的是每日备份到另一块磁盘或对象存储。
  2. 写坏了数据库,回滚快照——快照能恢复文件,但无法保证 InnoDB 的崩溃一致性。回滚后 MySQL 报「table is corrupted」,因为快照是在运行中打的,页写了一半。正确做法是快照前 FLUSH TABLES WITH READ LOCK,或者用 mysqldump/xtrabackup 做逻辑备份。
  3. 宿主盘坏了,快照跟着没了——local-lvm 上的快照与原盘在同一块物理盘。宿主盘挂了就是全丢。备份必须离机。

所以最小的可靠组合是:PVE 的 vzdump 每日备份到一块独立磁盘(local-backup),再用 rclone 或 restic 同步到对象存储(加密 + 版本)。PVE 的备份计划在后台的「数据中心 → 备份」里配,注意打开 zstd 压缩,以及设置保留策略(保留 7 天日备 + 4 周周备)。

七、日志与温度:小机器特有的问题

PVE 会写一堆东西到 /var/log/pve,其中 tasks/ 目录的内容增长最快——每次备份、每次迁移、每次修改配置都会生成一个任务日志。个人站机器上见过 /var/log/pve/tasks 涨到 20G 的。

du -sh /var/log/pve/tasks
find /var/log/pve/tasks -type f -mtime +60 -delete

另一件事是温度。PVE 后台默认不开温度传感器显示,小机箱或者被动散热的小主机,夏天会悄悄降频甚至关机。装一个 lm-sensors 并在 PVE 的节点摘要里加温度显示,是本系列里性价比最高的一步:

apt install lm-sensors
sensors-detect --auto
sensors    # 看 Package id 的温度

如果这里读出 80 度以上,你所有的性能调优都会变成徒劳——CPU 一直在降频。

八、上线检查清单

把上面这些压缩成一份可以照着勾的清单,装完一台新的 PVE 之后走一遍:

  • 企业源已停用,免费源已启用,apt full-upgrade 跑通
  • 内核已 pin,升级策略写进自己的运维笔记
  • 每台虚拟机已装 QEMU Guest Agent,且选项里已启用
  • 自动启动已开,启动顺序与延迟已验证过一次宿主重启
  • 数据库类虚拟机已关 ballooning;ZFS ARC 上限已设
  • 薄池使用率有监控,80% 告警
  • 8006 端口不对公网开放
  • 每日备份到独立磁盘 + 异地同步,且真的恢复过一次
  • /var/log/pve/tasks 有清理策略
  • 温度能读出来,且低于 70 度

这份清单里最容易被跳过的是「真的恢复过一次」。备份有任务成功记录、有文件大小、有校验和,都不等于它能还原。找一台机器,把备份拉回来,启动,访问首页——这件事每半年做一次,比多做十份备份都有用。

九、小结

PVE 的复杂度来自它把一台物理机拆成了多个抽象层。个人站长不需要理解每一层,但需要知道每一层上有一个开关会咬人:源和内核决定能不能安全更新,Guest Agent 决定能不能优雅关机,ballooning 和 ARC 决定内存会不会互相挤,薄池决定磁盘会不会一起死,快照决定你丢的是几小时还是几天,温度决定前面的努力有没有意义。

把它们一次性配好,之后这台机器可以几年不用管;不配,问题会在最不方便的时候同时爆发。

Last modification:November 6th, 2026 at 09:27 pm

Leave a Comment