在 Proxmox VE (PVE) 环境下,LXC (Linux Containers) 和 KVM (Kernel-based Virtual Machine) 就像是你工具箱里的“手术刀”和“大铁锤”。
一、 LXC vs KVM:如何选对“容器”?
1. LXC (系统级容器)
LXC 与宿主机共享内核,极其轻量。
-
适用任务:
-
基础网络服务: 像你感兴趣的 Cloudflare Tunnel、Caddy、rclone 同步任务、或者简单的 Web 服务器。
-
轻量化自建应用: Vaultwarden (你已经在用了)、Ghost 博客、小型数据库 (Redis/MariaDB)。
-
资源敏感型任务: 尤其在你的 ThinkPad 上,如果你想省下内存给其他任务,LXC 是首选。
-
优势: 启动秒开,内存占用几乎可以忽略不计(几十 MB),可以直接访问宿主机的文件系统(Bind Mount)。
2. KVM (完全虚拟化虚拟机)
KVM 模拟完整的硬件,拥有独立的内核。
-
适用任务:
-
非 Linux 系统: 比如 Windows Server(你关注过)或其它发行版。
-
复杂/重量级应用: Mastodon、Discourse 等这类对系统环境依赖深、容易把内核搞乱【备注】的应用。
-
隔离性要求高: 如果你要跑一些不安全或需要深度定制内核参数的服务。
-
直通 (Passthrough): 既然是 AMD 平台,如果你需要把核显直通给虚拟机做视频转码(如 MediaCMS),KVM 的隔离性让直通更稳定。
-
优势: 彻底隔离,安全性最高,支持快照(Snapshot)和迁移更彻底。
二、 在 PVE 上运行 Docker 的避坑指南
在 PVE 里跑 Docker 并没有“一键点击”的官方原生支持(虽然 PVE 9.1 开始支持 OCI 镜像转换),通常有以下两种主流方案及注意事项:
方案 A:在虚拟机 (KVM) 里跑 Docker (官方推荐)
这是最稳的方案,也是 CasaOS 最理想的家。
- 注意事项:
- 开启 QEMU Agent: 务必在虚拟机设置里开启并在 Guest OS 里安装
qemu-guest-agent,否则 PVE 无法正确显示 IP 和控制开关。 - 磁盘类型: 建议使用
VirtIO Block驱动以获得最佳 I/O 性能。 - 数据挂载: 建议将 Docker 的
/var/lib/docker或 Compose 配置文件放在独立的虚拟磁盘上,方便以后重装系统。
方案 B:在 LXC 里跑 Docker (极客首选)
为了节省你那台 ThinkPad 的内存,你可能会想在 LXC 里“套娃”跑 Docker。
- 注意事项:
- 必须开启 Nesting(嵌套): 在 LXC 的“设置 → 功能”里勾选
Nesting。 - 不建议用特权容器: 尽量使用
Unprivileged(非特权)容器,虽然配置 UID 映射比较麻烦,但安全性更高。 - 存储驱动冲突: Docker 默认的
overlay2在某些 LXC 存储后端(如 ZFS)上会有性能问题,可能需要修改 Docker 的daemon.json使用fuse-overlayfs。
小贴士: 对于你提到的 CasaOS,建议直接给它一个独立的 Debian VM。因为它会接管很多系统配置,放在 LXC 里可能会因为权限问题导致某些功能(如磁盘管理)失效。
【备注】
所谓“把内核搞乱”,更多是指它们对内核参数(Kernel Parameters)、系统调用(System Calls)以及共享资源的侵略性需求。在 LXC(共享内核)和 KVM(独立内核)的对比背景下,这种“乱”主要体现在以下几个维度:
1. 共享内核参数的“拔河” (Sysctl Conflicts)
LXC 容器与宿主机共享同一个内核。很多高性能应用(尤其是像 Mastodon 这种包含 Redis、PostgreSQL 和大量 Sidekiq 异步任务的架构)为了跑得稳,通常会要求修改内核参数:
- 内存管理: Redis 强烈建议将
vm.overcommit_memory设置为1。 - 网络连接: 为了处理高并发,应用可能要求调大
net.core.somaxconn(监听队列长度)。 - 文件句柄: 调高
fs.file-max。
问题在于: 在 LXC 中,这些参数很多是全域生效的。如果你在容器 A 里为了跑 Mastodon 修改了内核参数,它会直接影响到宿主机和其他所有容器。如果参数设置不当,可能导致整个宿主机网络栈不稳定或内存分配逻辑异常。
2. 内核模块与文件系统的依赖 (Kernel Modules)
复杂应用往往不仅仅是代码,还涉及底层的支撑技术:
- 存储驱动: 比如 Docker 在容器内运行时,可能需要特定的
overlay2或aufs支持。 - 虚拟网桥: 某些复杂的应用集群(如 K8s 环境下)需要加载特殊的内核模块(如
br_netfilter或特定的iptables模块)。 - 权限限制: LXC 为了安全,默认禁止容器加载/卸载内核模块。如果 Mastodon 的某个组件(或它依赖的 Docker 镜像)试图执行
modprobe操作,就会报错,甚至导致应用反复重启,在宿主机日志中刷出大量错误。
3. OOM Killer(内存溢出杀手)的连锁反应
这是最容易“搞乱”系统稳定性的地方:
- KVM 模式: 虚拟机有固定的内存边界。如果 Mastodon 内存泄露了,只会导致虚拟机内部触发 OOM,把自己的进程杀了,或者虚拟机直接挂掉,宿主机稳如泰山。
- LXC 模式: 虽然可以设置资源上限,但由于内存是由宿主机内核统一调度的,当容器内发生剧烈的内存波动时,宿主机的内核 OOM Killer 可能会介入。在极端情况下,内核可能会误杀宿主机上的重要进程,或者导致宿主机因频繁的页交换(Paging)而陷入长时间的卡顿(Kernel Panic 的前兆)。
4. 系统库的“环境污染” (Dependency Hell)
虽然这不直接属于“内核”范畴,但它是“搞乱系统”的主因:
Mastodon 和 Discourse 依赖极其复杂的运行环境(特定的 Ruby 版本、Node.js 版本、ImageMagick 的编译参数等)。
- 如果你不使用 Docker,直接在 LXC 系统上安装,它们的脚本可能会尝试升级你的系统基础库(如
libc或openssl)。 - 在 LXC 中,一旦这些基础库和宿主机的内核版本出现兼容性细微偏差(例如某些新的系统调用在旧内核上不存在),整个容器就会陷入无法启动的境地。
总结:为什么要用 KVM 跑它们?
| 维度 | LXC (共享内核) | KVM (独立内核) |
|---|---|---|
| 内核参数 | 牵一发而动全身,容易冲突 | 随便改,仅在 VM 内部生效 |
| 故障隔离 | 应用崩了可能拖慢宿主机 | 应用崩了只烂在 VM 内部 |
| 环境要求 | 必须适配宿主机的内核版本 | 自带内核,想用什么版本都行 |
| 安全性 | 存在容器逃逸风险 | 硬件级隔离,安全性极高 |
一句话建议:
如果你是在进行生产级部署(比如打算正式运营一个 Mastodon 实例),用 KVM 虚拟机。它就像一个防弹玻璃罩,无论里面的应用怎么折腾内核,外面都是安全的。
如果你只是想在本机低成本测试,或者你的内存实在吃紧,可以考虑在 LXC 里跑 Docker,但这需要你对 nesting 权限和 fuse-overlayfs 有较深的了解。