Chapter 03 · Host System Administration

第 3 章 主机系统管理

本章体量极大(原文 138 标题 / 153 代码块 / 65 告示) , 分三个批次交付 :批次 3A(本页) 已完成 §3.1 软件包仓库、 §3.2 系统软件更新、 §3.3 固件更新 ; 3B 将覆盖 §3.4-§3.7(网络、时间同步、外部指标、磁盘健康); 3C 将覆盖 §3.8-§3.14(LVM / ZFS / BTRFS / 节点管理 / 证书 / 引导 / KSM)。

3.主机系统管理 Host System Administration

以下各节将聚焦于常见的虚拟化任务 , 并介绍 Proxmox VE 主机的运维与管理细节。

Proxmox VE 基于 Debian GNU/Linux , 并通过额外的仓库提供 Proxmox VE 相关软件包。这意味着您可以使用完整的 Debian 软件包生态 , 包括其安全更新与 bug 修复。 Proxmox VE 自带一个基于 Ubuntu 内核的 Linux 内核 , 已启用所有必要的虚拟化与容器特性 , 并集成 ZFS 与若干额外硬件驱动。

本章未涵盖的其他主题 , 请参见 Debian 文档。Debian 管理员手册(Debian Administrator's Handbook) 可在线阅读 , 提供对 Debian 操作系统的全面介绍(参见 [Hertzog13])。

3.1.软件包仓库 Package Repositories

Proxmox VE 与其他基于 Debian 的系统一样 , 使用 APT 作为包管理工具。

Proxmox VE 每天自动检查一次可用的软件包更新 , 并通过邮件通知 root@pam 用户。在 GUI 中可使用 Changelog 按钮查看所选更新的详细说明。

3.1.1.Proxmox VE 中的仓库 Repositories in Proxmox VE

仓库是一系列软件包的集合 , 用于安装新软件 , 同时对获取新更新也至关重要。

NOTE

需要有效的 Debian 与 Proxmox 仓库 , 才能获取最新的安全更新、 bug 修复与新特性。

APT 仓库可以定义在 /etc/apt/sources.list 文件中(旧版单行格式) , 或放在 /etc/apt/sources.list.d/ 下的 .sources 文件中(现代 deb822 多行格式)。详见 仓库格式

仓库管理 Repository Management
节点仓库管理面板
图 3.1 :节点 → 仓库(Repository)管理面板

自 Proxmox VE 7 起 , 您可以在 Web 界面中查看仓库状态。节点概览面板提供一个高层状态总览 ; 独立的 Repository 面板则显示详细状态以及所有已配置仓库的列表。

基本的仓库管理操作(例如启用或禁用某个仓库)也同样被支持。

仓库中可用的软件包通过运行 apt update 获取。更新既可以直接使用 apt 安装 , 也可通过 GUI(节点 → 更新)安装。

仓库格式 Repository Formats

软件包仓库可以在源列表 /etc/apt/sources.list/etc/apt/sources.list.d/ 下的文件中进行配置。

支持两种格式:

单行格式 single line

在单行 sources.list 文件中 , 每一行定义一个软件包仓库。空行被忽略。 # 字符起至行尾视为注释。这是旧版格式。自 Debian 13 Trixie 起 , apt 会对使用此格式发出告警。可使用 apt modernize-sources 命令自动迁移大多数仓库。

deb822 多行格式 deb822

在多行 repo.sources 文件中 , 每个条目由若干行 key-value 对组成 , 条目之间以空行分隔。这是现代格式。

可用仓库 Available Repositories

除了基础的 Debian 仓库外 , Proxmox VE 还提供三种不同的软件包仓库。

3.1.2.Debian 基础仓库 Debian Base Repositories

文件 /etc/apt/sources.list.d/debian.sources

Types: deb deb-src
URIs: http://deb.debian.org/debian/
Suites: trixie trixie-updates
Components: main non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

Types: deb deb-src
URIs: http://security.debian.org/debian-security/
Suites: trixie-security
Components: main non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

3.1.3.Proxmox VE 企业版仓库 Proxmox VE Enterprise Repository

这是推荐使用的仓库 , 对所有 Proxmox VE 订阅用户开放。它包含最稳定的软件包 , 适用于生产环境。 pve-enterprise 仓库默认启用:

文件 /etc/apt/sources.list.d/pve-enterprise.sources

Types: deb
URIs: https://enterprise.proxmox.com/debian/pve
Suites: trixie
Components: pve-enterprise
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg

请注意 , 访问 pve-enterprise 仓库需要有效的订阅密钥。我们提供多种支持等级 , 详情见 https://proxmox.com/en/proxmox-virtual-environment/pricing

NOTE

您可以在对应条目中添加一行 Enabled: no 来禁用此仓库。此举可避免主机没有订阅密钥时产生错误提示。在这种情况下 , 请改为配置 pve-no-subscription 仓库。

3.1.4.Proxmox VE 无订阅仓库 Proxmox VE No-Subscription Repository

顾名思义 , 访问此仓库不需要订阅密钥。它可用于测试与非生产用途。不建议在生产服务器上使用 , 因为这些软件包的测试与验证深度不及企业版。

推荐在 /etc/apt/sources.list.d/proxmox.sources 中配置此仓库。

文件 /etc/apt/sources.list.d/proxmox.sources

Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: trixie
Components: pve-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
NOTE

请记住 , 除了任一 Proxmox VE 仓库之外 , 您始终需要同时配置基础 Debian 仓库。

3.1.5.Proxmox VE 测试仓库 Proxmox VE Test Repository

该仓库包含最新的软件包 , 主要供开发者测试新特性使用。要配置该仓库 , 请在 /etc/apt/sources.list.d/proxmox.sources 中追加以下段落:

文件 /etc/apt/sources.list.d/proxmox.sources

Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: trixie
Components: pve-test
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
WARN

pve-test 仓库(正如其名)仅应用于测试新特性或 bug 修复。

3.1.6.Ceph 仓库 Ceph Repositories

Ceph 相关软件包通过一个预配置的 Ceph 企业仓库保持最新。预装软件包可用于连接外部 Ceph 集群 , 并将其 RBDCephFS 池作为存储加入。您也可以通过在 Proxmox VE 集群上运行 Ceph 来构建 超融合基础设施(HCI)

本节信息适用于以下场景:

安装 Ceph 构建 HCI

从下文所列仓库中选定一个 , 并选择较新的 Ceph 发行版 , 然后在 基于 Web 的向导或 CLI 工具 中选用。

已在运行 HCI 并希望升级到下一个 Ceph 大版本

请遵循 Ceph 升级指南

已在运行 HCI 并希望升级到下一个 Proxmox VE 大版本

在 HCI 中 , Proxmox VE 每个大版本都需要对应的最低 Ceph 大版本 , 请遵循 Proxmox VE 升级指南

未运行 HCI, 但使用外部 Ceph 集群

若要安装用于连接 Ceph 的新版软件包 , 请先应用可用的系统更新 , 然后从下表中选定仓库与 Ceph 版本 , 通过 Repository 面板将其添加到节点 , 再次应用系统更新 , 运行 ceph --version 验证结果 , 最后禁用旧的 Ceph 仓库。

Proxmox VE 9 中可用的 Ceph 发行版 Ceph releases available in Proxmox VE 9
Release 预计 End-of-Life enterprise no-subscription test
ceph-squid 2026-09 (v19.2) recommended available available
Proxmox VE 9 的 Ceph 仓库 Ceph repositories for Proxmox VE 9

下文 ceph.sources 文件的内容仅供参考(Proxmox VE 9 之前使用 ceph.list 文件)。如需修改 , 请按本小节开头所描述的场景选择操作。若您已在 Web UI 中禁用了某仓库并希望将其从清单中彻底移除 , 可以手动从文件中删除对应条目。

enterprise

此仓库推荐用于生产环境 , 包含最稳定的软件包版本。持有任意级别的 Proxmox VE 订阅的节点均可访问。关于订阅等级与客户支持详情 , 请访问 :https://proxmox.com/en/proxmox-virtual-environment/pricing

文件 /etc/apt/sources.list.d/ceph.sources

Types: deb
URIs: https://enterprise.proxmox.com/debian/ceph-squid
Suites: trixie
Components: enterprise
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
no-sub

此仓库适用于测试与非生产用途 , 可免费访问 , 不需要订阅。其软件包版本过一段时间后也会进入企业仓库。

文件 /etc/apt/sources.list.d/ceph.sources

Types: deb
URIs: http://download.proxmox.com/debian/ceph-squid
Suites: trixie
Components: no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
test

此仓库包含最新的软件包版本 , 主要供开发者测试新特性与 bug 修复。

文件 /etc/apt/sources.list.d/ceph.sources

Types: deb
URIs: http://download.proxmox.com/debian/ceph-squid
Suites: trixie
Components: test
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
WARN

Ceph test 仓库(正如其名)仅应用于测试新特性或 bug 修复。

3.1.7.Debian 固件仓库 Debian Firmware Repository

自 Debian Bookworm(Proxmox VE 8)起 , 非自由固件(按 DFSG 定义)被迁移到了新增的 Debian 仓库组件 non-free-firmware 中。

自 Proxmox VE 9 起 , 新装系统默认启用此仓库 , 以便能及时获得 早期 OS 微码更新(Early OS Microcode Updates)

您还可以额外获取未包含在预装包 pve-firmware 中的 运行时固件文件(Runtime Firmware Files)

若要从此组件安装软件包 , 运行 editor /etc/apt/sources.list , 在每一行 .debian.org 仓库末尾追加 non-free-firmware , 然后运行 apt update

如果您是从较早版本的 Proxmox VE 升级到 Proxmox VE 9 , 并且已将软件包仓库现代化为新的 deb822 风格 , 则需要改为修改 /etc/apt/sources.list.d/debian.sources。运行 editor /etc/apt/sources.list.d/debian.sources , 在每个条目以 Components: 开头的行尾追加 non-free-firmware

NOTE

推荐将软件包仓库进行现代化(modernize) , 否则 Debian Trixie 上的 apt 会发出告警。可运行 apt modernize-sources 来完成这项工作。

3.1.8.SecureApt SecureApt

仓库中的 Release 文件使用 GnuPG 签名。 APT 利用这些签名来校验所有软件包是否来自受信来源。

若您从官方 ISO 镜像安装 Proxmox VE , 校验所需的密钥已经预装。

若您是在 Debian 上叠加安装 Proxmox VE , 请用以下命令下载并安装密钥:

 # wget https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg -O /usr/share/keyrings/proxmox-archive-keyring.gpg
NOTE

上方 wget 命令添加的是基于 Debian Trixie 的 Proxmox 发布密钥环。一旦安装了 proxmox-archive-keyring 软件包 , 该包会接管此文件的管理 ; 此时下面列出的哈希值可能与实际文件的哈希值不再匹配 , 因为新增或移除了其他 Proxmox 发行版的密钥。这是预期行为 , apt 会确保仅使用受信任的密钥。安装 proxmox-archive-keyring 之后 , 不建议再手动修改此文件。

随后使用 sha512sum(原文如此 , 实际命令为 sha256sum)CLI 工具验证校验和:

# sha256sum /usr/share/keyrings/proxmox-archive-keyring.gpg
 136673be77aba35dcce385b28737689ad64fd785a797e57897589aed08db6e45 /usr/share/keyrings/proxmox-archive-keyring.gpg

或者使用 md5sum CLI 工具:

# md5sum /usr/share/keyrings/proxmox-archive-keyring.gpg
77c8b1166d15ce8350102ab1bca2fcbf /usr/share/keyrings/proxmox-archive-keyring.gpg
NOTE

请确保密钥的安装路径与仓库条目中 Signed-By: 行所写路径保持一致。

3.2.系统软件更新 System Software Updates

Proxmox 为所有仓库定期提供更新。可通过 Web GUI 或以下 CLI 命令来安装更新:

# apt-get update
# apt-get dist-upgrade

关于偶尔对 Ceph 进行大版本升级 , 请参见 Ceph 仓库

NOTE

APT 包管理系统非常灵活 , 功能众多。更多信息请参见 man apt-get , 或 [Hertzog13]

TIP

定期更新对于获得最新补丁与安全修复至关重要。重大系统升级会在 Proxmox VE 社区论坛 公告。

3.3.固件更新 Firmware Updates

本章所涉及的固件更新 , 适用于在裸金属服务器上运行 Proxmox VE 的场景。在客户机内是否需要配置固件更新(例如使用设备直通时)与您的具体部署强相关 , 因此不在本文范围。

除了常规的软件更新外 , 固件更新对于可靠、安全的运行同样重要。

在获取和应用固件更新时 , 建议结合多种可用方式 , 以尽早或尽可能获取更新。

术语上 , 「固件」通常又细分为微码(microcode , 针对 CPU)与固件(针对其他设备)。

3.3.1.持久化固件 Persistent Firmware

本节方法适用于所有设备。更新后的微码通常随 BIOS/UEFI 更新一并提供 , 存储在主板上 ; 其他固件则存储在各自设备中。此种持久化方式对 CPU 尤为重要 , 因为它能让更新后的微码在引导最早期就被常规加载。

CAUT

在某些更新中(例如 BIOS/UEFI 或存储控制器更新) , 设备配置可能被重置。请认真遵循厂商指引 , 并先备份当前配置。

请咨询您的厂商了解可用的更新方式。

  • 便捷的服务器更新方式包括 Dell 的 Lifecycle Manager、 HPE 的 Service Packs 等。
  • 有时也会提供 Linux 工具。例如 NVIDIA ConnectX 的 mlxup , 或 Broadcom 网卡的 bnxtnvm / niccli
  • 若与 硬件厂商 有合作且使用 受支持硬件 , 还可以使用 LVFS。技术前提是 :系统为 2014 年后生产 , 且通过 UEFI 引导。

Proxmox VE 自带修改版的 fwupd 软件包 , 以通过 Proxmox 签名密钥支持 Secure Boot。该软件包有意移除了对 udisks2 的依赖建议 , 因为在 hypervisor 上观察到过由 udisks2 引起的问题。这意味着您必须在 /etc/fwupd/daemon.conf 中显式配置 EFI 分区的挂载点 , 例如:

文件 /etc/fwupd/daemon.conf

# Override the location used for the EFI system partition (ESP) path.
EspLocation=/boot/efi
TIP

如果更新说明要求重启主机 , 请先确认可以安全重启。参见 节点维护(Node Maintenance)

3.3.2.运行时固件文件 Runtime Firmware Files

此方式将固件存储在 Proxmox VE 操作系统中 , 并在设备的 持久化固件 较旧时 , 将其传递给设备。网卡、显卡等设备支持此方式 ; 主板、硬盘等依赖持久化固件的设备则不适用。

在 Proxmox VE 中 , pve-firmware 软件包已默认安装。因此 , 通过常规 系统更新(APT) 就能自动保持常见硬件所含固件的更新。

此外还存在一个 Debian 固件仓库 , 默认未配置。

如果您尝试安装额外的固件包但产生冲突 , APT 会中止安装。此时该特定固件可能需要通过其他方式获取。

3.3.3.CPU 微码更新 CPU Microcode Updates

微码更新旨在修复已发现的安全漏洞与其他严重 CPU 缺陷。尽管 CPU 性能可能受影响 , 但通常带补丁的微码仍比未打补丁、靠内核本身做缓解措施的情况性能更佳。根据 CPU 类型的不同 , 有时在已知漏洞状态下原出厂性能结果已无法在「刻意将 CPU 置于不安全状态」之外再现。

要查看当前 CPU 漏洞及其缓解情况 , 可运行 lscpu。只有在 Proxmox VE 主机 已更新到最新 、版本 未过 EOL , 且自上次内核更新后至少重启过一次的情况下 , 才能呈现当前真实已知的漏洞。

除推荐的通过 持久化 BIOS/UEFI 更新来进行微码更新之外 , 还有一种独立方式 — 早期 OS 微码更新(Early OS Microcode Updates)。它使用方便 , 在主板厂商不再提供 BIOS/UEFI 更新时也很有用。不论采用哪种方式 , 应用微码更新都需要重启。

配置早期 OS 微码更新 Set up Early OS Microcode Updates

要配置由 Linux 内核在引导早期应用的微码更新 , 需执行以下步骤:

  1. 启用 Debian 固件仓库
  2. 运行 apt update 获取最新可用软件包(也可通过 Web 界面 , 节点 → 更新)。
  3. 安装与 CPU 厂商对应的微码包:
    • Intel CPU :apt install intel-microcode
    • AMD CPU :apt install amd64-microcode
  4. 重启 Proxmox VE 主机。

此后任何微码更新都同样需要重启才能生效。

微码版本 Microcode Version

要获取当前运行的微码修订版 , 以供对比或调试:

# grep microcode /proc/cpuinfo | uniq
microcode       : 0xf0

一个微码包通常包含针对许多不同 CPU 的更新 , 但针对您特定 CPU 的更新并不一定频繁。因此仅凭软件包发布日期 , 无法得知厂商何时针对您这款 CPU 发布过更新。

如果您安装了新的微码包并重启了 Proxmox VE 主机 , 且此新微码比 CPU 内置与主板固件中的都更新 , 系统日志中会出现 "microcode updated early" 字样。

# dmesg | grep microcode
[    0.000000] microcode: microcode updated early to revision 0xf0, date = 2021-11-12
[    0.896580] microcode: Microcode Update Driver: v2.2.
故障排查 Troubleshooting

为调试目的 , 可以临时禁用每次启动时常规应用的早期 OS 微码更新:

  1. 确认主机可以 安全重启
  2. 重启主机进入 GRUB 菜单(菜单被隐藏时按住 SHIFT)。
  3. 在想要启动的 Proxmox VE 启动条目上按 E
  4. 移动到以 linux 开头的行 , 在末尾用空格分隔后追加 dis_ucode_ldr
  5. CTRL-X 以本次不启用早期 OS 微码更新的方式启动。

若怀疑问题与最近一次微码更新相关 , 应考虑软件包降级 , 而不是卸载(apt purge <intel-microcode|amd64-microcode>)。否则 , 可能会加载过旧的 持久化 微码 , 即便较新版本在实际运行中也不会出问题。

如果 Debian 仓库里还保留着较早的微码包版本 , 就可以进行降级 , 例如:

# apt list -a intel-microcode
Listing... Done
intel-microcode/stable-security,now 3.20230808.1~deb12u1 amd64 [installed]
intel-microcode/stable 3.20230512.1 amd64
# apt install intel-microcode=3.202305*
...
Selected version '3.20230512.1' (Debian:12.1/stable [amd64]) for 'intel-microcode'
...
dpkg: warning: downgrading intel-microcode from 3.20230808.1~deb12u1 to 3.20230512.1
...
intel-microcode: microcode will be updated at next boot
...

再次确认主机可以 安全重启。要应用微码包中为您 CPU 类型所包含的较旧微码 , 请立即重启。

TIP

建议将降级后的软件包保持一段时间 , 稍后再试更新版本。即使未来包版本号没变 , 中间的系统更新也可能已修复您此前遇到的问题。

# apt-mark hold intel-microcode
intel-microcode set on hold.
# apt-mark unhold intel-microcode
# apt update
# apt full-upgrade

3.4.网络配置 Network Configuration

Proxmox VE 使用 Linux 网络栈 , 在 Proxmox VE 节点的网络配置上提供了极大灵活性。配置可通过 GUI 完成 , 也可以手工编辑 /etc/network/interfaces , 该文件包含完整的网络配置 ; 完整格式说明见 interfaces(5) 手册页。所有 Proxmox VE 工具都尽量保留用户的直接修改 , 但仍推荐使用 GUI, 以避免出错。

需要一个 Linux 桥接接口(通常名为 vmbrX)将客户机连接到底层物理网络。它可以视作虚拟交换机 , 客户机与物理接口都连入其中。本节给出若干示例 , 涵盖 bond 冗余、 vlansrouted 路由 与 NAT 等多种用例。

对于更复杂的虚拟网络 , 可在 Proxmox VE 集群中使用 软件定义网络(SDN)

CAUT

不确定时 , 不建议使用传统 Debian 工具 ifupifdown。它们存在一些陷阱 , 例如执行 ifdown vmbrX 会中断所有客户机流量 , 但稍后再 ifup 同一桥时不会重新接回这些客户机。

3.4.1.应用网络变更 Apply Network Changes

Proxmox VE 不会直接写入 /etc/network/interfaces , 而是写入临时文件 /etc/network/interfaces.new。这样可以一次集中做多项相关修改 , 也能在应用前确认配置正确 , 避免错误的网络配置导致节点不可达。

使用 ifupdown2 热重载网络 Live-Reload Network with ifupdown2

使用推荐的 ifupdown2 软件包(自 Proxmox VE 7.0 起为新装系统的默认值) , 可以在不重启的情况下应用网络配置变更。在 GUI 中修改网络配置后 , 点击 Apply Configuration 按钮即可将变更从暂存的 interfaces.new 移到 /etc/network/interfaces 并即时生效。

若您直接手工修改了 /etc/network/interfaces , 可运行 ifreload -a 应用。

NOTE

若您是在 Debian 上叠加安装 Proxmox VE, 或从更早版本升级到 Proxmox VE 7.0 , 请确认已安装 ifupdown2apt install ifupdown2

重启节点应用 Reboot Node to Apply

另一种应用新网络配置的方式是重启节点。重启时 systemd 服务 pvenetcommit 会先激活暂存的 interfaces.new 文件 , 然后由 networking 服务应用该配置。

3.4.2.命名约定 Naming Conventions

当前我们对设备名采用以下约定:

  • 以太网设备 :en* , 即 systemd 网络接口命名方案。该方案用于自 Proxmox VE 5.0 起的新装系统。
  • 以太网设备 :eth[N] , 0 ≤ N (eth0eth1 ……)。该方案用于 5.0 之前安装的 Proxmox VE 主机。升级到 5.0 时保留原名。
  • 桥名 :通常 vmbr[N] , 0 ≤ N ≤ 4094 (vmbr0vmbr4094) , 也可使用任意以字母开头、长度不超过 10 的字母数字字符串。
  • 绑定接口 :bond[N] , 0 ≤ N (bond0bond1 ……)。
  • VLAN :在设备名后加点号与 VLAN 号即可(eno1.50bond1.30)。

这能让排查网络问题更容易 , 因为设备名直接表明设备类型。

Systemd 网络接口命名 Systemd Network Interface Names

Systemd 为网络设备名定义了带版本的命名方案。该方案以两字符前缀 en 表示以太网设备 , 后续字符取决于驱动、设备位置等属性。常见模式包括:

  • o<index>[n<phys_port_name>|d<dev_port>] — 板载设备
  • s<slot>[f<function>][n<phys_port_name>|d<dev_port>] — 按热插拔 ID
  • [P<domain>]p<bus>s<slot>[f<function>][n<phys_port_name>|d<dev_port>] — 按总线 ID
  • x<MAC> — 按 MAC 地址

常见示例:

  • eno1 — 第一块板载网卡
  • enp3s0f1 — PCI 总线 3 、 槽位 0 网卡的功能 1

完整设备名模式列表见 systemd.net-naming-scheme(7) 手册页

新版 systemd 可能会引入新的命名方案版本并默认使用。因此 , 升级 systemd(例如做 Proxmox VE 大版本升级时)可能改变网络设备名 , 进而需要调整网络配置。要避免因方案版本变更导致名字变化 , 可以手动锁定(pin)一个具体的方案版本(见下文)。

不过 , 即使锁定了命名方案版本 , 内核或驱动更新仍可能导致设备名变更。要彻底避免某个特定网络设备名字变化 , 可使用 link 文件手工覆写其名字(见下文)。

更多关于网络接口名的信息 , 参见 Predictable Network Interface Names

锁定特定的命名方案版本 Pinning a specific naming scheme version

可通过在 内核命令行 添加 net.naming-scheme=<version> 参数来锁定具体版本。版本列表见 systemd.net-naming-scheme(7) 手册页

例如 , 锁定 v252(Proxmox VE 8.0 全新安装的最新方案版本):

net.naming-scheme=v252

关于编辑内核命令行 , 参见 本节。需重启使变更生效。

覆写网络设备名 Overriding Network Device Names
使用 pve-network-interface-pinning 工具 Using the pve-network-interface-pinning Tool

Proxmox VE 提供了一个工具 , 用于自动生成 .link 文件以覆写网络设备名 , 同时自动替换以下文件中出现的旧接口名:

  • /etc/network/interfaces
  • /etc/pve/nodes/<nodename>/host.fw
  • /etc/pve/sdn/controllers.cfg
  • /etc/pve/sdn/fabrics.cfg
NOTE

由于生成的映射仅对生成它的节点本地有效 , 防火墙数据中心配置(/etc/pve/firewall/cluster.fw)中包含的接口名 不会 被自动更新。

生成的 link 文件存放在 /usr/local/lib/systemd/network。对于配置文件 , 同目录下会生成带 .new 后缀的新文件 , 您可以使用 diff 等工具检查改动:

diff -y /etc/network/interfaces /etc/network/interfaces.new

若发现问题或希望在 重启之前 撤销变更 , 删除所有 .new 文件以及 /usr/local/lib/systemd/network 中相应的 link 文件即可。

以下命令会为所有尚无 .link 文件的物理接口生成 .link 文件 , 并更新选定的 Proxmox VE 配置文件(见上)。生成的名字使用默认前缀 nic , 即结果为 nic1nic2 ……

pve-network-interface-pinning generate

可用 --prefix 修改默认前缀:

pve-network-interface-pinning generate --prefix myprefix

也可以仅锁定指定接口:

pve-network-interface-pinning generate --interface enp1s0

锁定指定接口时 , 还可以指定其确切的目标名字:

pve-network-interface-pinning generate --interface enp1s0 --target-name if42

要应用 pve-network-interface-pinning 所做变更 , 需要重启节点。

手动创建 .link 文件 Manually Creating .link Files

您可以使用自定义 systemd.link 文件 手工为某个网络设备指定名字。这会覆盖按最新命名方案分配的名字 , 从而避免因内核更新、驱动更新或新版命名方案带来的名字变化。

自定义 link 文件应放在 /etc/systemd/network/ 下 , 命名形如 <n>-<id>.link , 其中 n 为小于 99 的优先级 , id 为标识符。 link 文件包含两个段 :[Match] 决定该文件作用于哪些接口 ; [Link] 决定这些接口的配置(包含命名)。

要为某个网络设备指定名字 , 需要在 [Match] 段中以唯一且持久的方式识别该设备。一种做法是使用 MACAddress 选项匹配设备的 MAC 地址 , 因为它通常不会变。

[Match] 段还应包含 Type 选项 , 以确保仅匹配预期的物理接口 , 而不会匹配同 MAC 的桥 / 绑定 / VLAN 接口。在大多数场景下 Type 应设为 ether 仅匹配以太网设备 , 但某些场景可能需要别的取值 , 详见 systemd.link(5) 手册页

然后 , 在 [Link] 段中用 Name 选项指定名字。

link 文件会被复制到 initramfs, 因此添加、修改或删除 link 文件后 , 推荐刷新 initramfs

# update-initramfs -u -k all

例如 , 要为 MAC 为 aa:bb:cc:dd:ee:ff 的以太网设备指定名字 enwan0 , 创建文件 /etc/systemd/network/10-enwan0.link 内容如下:

[Match]
MACAddress=aa:bb:cc:dd:ee:ff
Type=ether

[Link]
Name=enwan0

别忘了同时调整 /etc/network/interfaces 使用新名字 , 并按上文刷新 initramfs。需重启节点使变更生效。

NOTE

建议名字以 eneth 开头 , 这样 Proxmox VE 才会将其识别为可在 GUI 中配置的物理网络设备。同时 , 应确保未来不会与其他接口名冲突。一种做法是采用不会被 systemd 当作网络接口名匹配的命名(见上节), 例如上文示例中的 enwan0

关于 link 文件的更多信息 , 参见 systemd.link(5) 手册页

3.4.3.选择网络配置 Choosing a network configuration

根据您当前的网络组织方式与可用资源 , 可选用桥接(bridged)、路由(routed)或 NAT 伪装(masquerading)三种网络配置。

私有 LAN 中的 Proxmox VE, 通过外部网关访问互联网

这种场景下 桥接(Bridged) 模式最合适 , 也是新装 Proxmox VE 的默认模式。每台客户机都有一块虚拟接口连入 Proxmox VE 的桥 , 效果类似客户机网卡直接连到 LAN 中一台新交换机 , Proxmox VE 主机充当该交换机。

托管商处的 Proxmox VE, 客户机使用公有 IP 段

这种场景下可使用 桥接(Bridged)路由(Routed) 模式 , 取决于托管商的允许范围。

托管商处的 Proxmox VE, 仅有单个公有 IP

此时获取客户机出向网络访问的唯一途径是 NAT 伪装(Masquerading)。要让客户机被外部访问到 , 还需配置 端口转发(Port Forwarding)

为获得更多灵活性 , 可以配置 VLAN(IEEE 802.1q)和网卡绑定(也称「链路聚合」)。这样就能构建复杂、灵活的虚拟网络。

3.4.4.使用桥的默认配置 Default Configuration Using a Bridge

桥接网络默认拓扑
图 3.2 :桥接(Bridge)网络默认拓扑

桥相当于以软件实现的物理交换机。所有虚拟客户机可共享同一个桥 , 也可以创建多个桥以隔离网络域。每台主机可拥有最多 4094 个桥。

安装程序会创建一个名为 vmbr0 的桥 , 连接到第一块以太网卡。 /etc/network/interfaces 中对应配置可能形如:

auto lo
iface lo inet loopback

iface eno1 inet manual

auto vmbr0
iface vmbr0 inet static
        address 192.168.10.2/24
        gateway 192.168.10.1
        bridge-ports eno1
        bridge-stp off
        bridge-fd 0

虚拟机表现得就像直接连接到物理网络。从网络的角度看 , 每台 VM 都拥有自己独立的 MAC 地址 , 即便它们其实是通过同一根网线接入网络。

3.4.5.路由配置 Routed Configuration

多数托管商不支持上述配置。出于安全考虑 , 一旦在同一接口上检测到多个 MAC , 它们会立即关闭网络。

NOTE

有些托管商允许您在管理界面中登记额外 MAC, 这能避免上述问题 , 但配置起来比较繁琐 , 因为每台 VM 都需要登记一个 MAC。

可以通过将所有流量都「路由」经单一接口来回避此问题。这样所有网络包都使用同一个 MAC。

路由网络拓扑
图 3.3 :路由(Routed)网络拓扑

常见场景 :您有一个公网 IP(这里以 198.51.100.5 为例) , 还有一段额外 IP 块(203.0.113.16/28)分配给 VM。推荐配置如下:

auto lo
iface lo inet loopback

auto eno0
iface eno0 inet static
        address  198.51.100.5/29
        gateway  198.51.100.1
        post-up echo 1 > /proc/sys/net/ipv4/ip_forward
        post-up echo 1 > /proc/sys/net/ipv4/conf/eno0/proxy_arp


auto vmbr0
iface vmbr0 inet static
        address  203.0.113.17/28
        bridge-ports none
        bridge-stp off
        bridge-fd 0

3.4.6.使用 iptables 实现 NAT 伪装 Masquerading (NAT) with iptables

NAT 伪装允许仅有私有 IP 的客户机使用主机 IP 出网。每个出向数据包由 iptables 改写为来源于主机 , 响应包再相应改写并路由回原发送方。

auto lo
iface lo inet loopback

auto eno1
#real IP address
iface eno1 inet static
        address  198.51.100.5/24
        gateway  198.51.100.1

auto vmbr0
#private sub network
iface vmbr0 inet static
        address  10.10.10.1/24
        bridge-ports none
        bridge-stp off
        bridge-fd 0

        post-up   echo 1 > /proc/sys/net/ipv4/ip_forward
        post-up   iptables -t nat -A POSTROUTING -s '10.10.10.0/24' -o eno1 -j MASQUERADE
        post-down iptables -t nat -D POSTROUTING -s '10.10.10.0/24' -o eno1 -j MASQUERADE
NOTE

在某些启用了防火墙的 NAT 伪装场景中 , 出向连接可能需要 conntrack 区域(zone)。否则防火墙可能阻断出向连接 , 因为它们更倾向匹配 VM 桥的 POSTROUTING, 而非 MASQUERADE

/etc/network/interfaces 中加入以下行可解决该问题:

post-up   iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1
post-down iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1

更多信息可参考:

Netfilter Packet Flow

netdev 邮件列表上引入 conntrack zone 的补丁

用 raw 表 TRACE 解释清晰的博客文章

3.4.7.Linux 网卡绑定(Bond) Linux Bond

绑定(bonding , 即 NIC 组队 / 链路聚合)是一种将多张 NIC 绑定为单一逻辑网络设备的技术。它能够实现一项或两项目标:提升容错与提升吞吐。

磁盘 I/O 与网络 I/O 速度都很快的高速硬件 , 在网络层成为瓶颈是常见情况。使用多张 NIC 可线性提升吞吐 , 而绑定还能让网络链路变得冗余。在现代 Linux 内核里 , 我们将一组绑定的 NIC 称为 bond, 在 Cisco 的术语里这通常叫 EtherChannel, 而 Linux 内核模块的对应项目叫 bonding driver

使用绑定 , 可以做到两个 HA 网络互连 , 并能扩张可用带宽。即便目标交换机不支持 link aggregation , 故障切换也能工作(不过此时无法叠加吞吐 , 因为同一时刻只用一条链路)。可以用 round-robin 模式或活动备份模式实现链路冗余 , 一旦使用绑定 , Proxmox VE 集群网络也可承受单链路故障。

有 7 种绑定模式:

  • Round-robin (balance-rr):从首个可用从设备到最后一个 , 顺序发送数据包。提供负载均衡和容错。
  • Active-backup (active-backup):仅一块从设备激活。其他从设备只在当前活动从设备故障时才会激活。该单一逻辑接口的 MAC 仅在一个端口上对外可见 , 避免对网络交换机产生干扰。仅提供容错。
  • XOR (balance-xor):基于 [(源 MAC 地址 XOR 目的 MAC 地址) MODULO 从设备数] 的策略发送。每个目的 MAC 都会选择同一从设备。提供负载均衡与容错。
  • Broadcast (broadcast):在所有从设备上发送所有数据。提供容错。
  • IEEE 802.3ad Dynamic link aggregation (802.3ad)(LACP):创建共享同一速度与双工设置的聚合组。按 802.3ad 标准利用激活组中的所有从设备。
  • Adaptive transmit load balancing (balance-tlb):自适应发送负载均衡的 Linux 绑定驱动模式 , 不要求任何特殊网络交换机支持。出向流量按各从设备当前负载(按链路速度计算的相对值)分发 , 入向流量由当前指定的一个从设备接收。若该接收从设备故障 , 另一从设备接管其 MAC 地址。
  • Adaptive load balancing (balance-alb):在 balance-tlb 之上 , 加入 IPV4 流量的接收负载均衡(rlb),且不需任何特殊交换机支持。 rlb 通过 ARP 协商完成。

若您的交换机支持 LACP(IEEE 802.3ad) , 推荐使用对应的绑定模式(802.3ad)。否则一般应使用 active-backup 模式。
若打算让集群网络(Corosync)使用绑定 , 推荐对该绑定使用 active-passive 模式 , 否则其它模式不被支持。

下例展示在三个 Proxmox VE 集群节点上配置 LACP 绑定(802.3ad)作为 corosync 网络。

auto lo
iface lo inet loopback

iface eno1 inet manual

iface eno2 inet manual

iface eno3 inet manual

auto bond0
iface bond0 inet static
      bond-slaves eno1 eno2
      address  192.168.1.1/24
      bond-miimon 100
      bond-mode 802.3ad
      bond-xmit-hash-policy layer2+3

auto vmbr0
iface vmbr0 inet static
      address  10.10.10.2/24
      gateway  10.10.10.1
      bridge-ports eno3
      bridge-stp off
      bridge-fd 0
桥 + 绑定网络拓扑
图 3.4 :桥 + 绑定(Bond)网络拓扑

另一种用法 :绑定本身用作桥端口 , 这能让客户机网络获得故障切换特性。

auto lo
iface lo inet loopback

iface eno1 inet manual

iface eno2 inet manual

auto bond0
iface bond0 inet manual
      bond-slaves eno1 eno2
      bond-miimon 100
      bond-mode 802.3ad
      bond-xmit-hash-policy layer2+3

auto vmbr0
iface vmbr0 inet static
      address  10.10.10.2/24
      gateway  10.10.10.1
      bridge-ports bond0
      bridge-stp off
      bridge-fd 0

3.4.8.VLAN 802.1Q VLAN 802.1Q

虚拟 LAN(VLAN)是在 OSI 第 2 层(数据链路层)上分区与隔离的广播域。这样在同一物理网络内可以并存多个网络 , 各 VLAN 之间互相隔离。例如 , VLAN 可用于隔离单位中各部门 , 让客户机仅能访问其本部门 VLAN 中的设备。

常见用例 :让客户机能够使用 VLAN(802.1q VLAN tagging)。这可由多种方式实现。

VLAN for Guest Networks

Proxmox VE 透明地支持此模式。在配置虚拟机网络设备时直接指定 VLAN tag 即可。这种方式还可以做到:

  • 通过桥端口路由
  • 使用 VLAN 感知的 Linux 桥
  • 使用 Open vSwitch 桥(实验性)
  • 在 VM 内部配置(仅特定场景)
VLAN on the Host

要让主机自身通过 VLAN 通信 , 可在原始物理设备(NIC 或绑定)上叠加 VLAN , 由桥附加这些设备。这适合需要主机管理网络与客户机网络位于不同 VLAN 时的场景。

例 :将主机管理 IP 放在 VLAN 5 , 同时把客户机网络作为默认 VLAN :

auto lo
iface lo inet loopback

iface eno1 inet manual

iface eno1.5 inet manual

auto vmbr0v5
iface vmbr0v5 inet static
        address  10.10.10.2/24
        gateway  10.10.10.1
        bridge-ports eno1.5
        bridge-stp off
        bridge-fd 0

auto vmbr0
iface vmbr0 inet manual
        bridge-ports eno1
        bridge-stp off
        bridge-fd 0

下一例同样意图 , 但使用 VLAN 感知(vlan-aware)的桥:

auto lo
iface lo inet loopback

iface eno1 inet manual


auto vmbr0.5
iface vmbr0.5 inet static
        address  10.10.10.2/24
        gateway  10.10.10.1

auto vmbr0
iface vmbr0 inet manual
        bridge-ports eno1
        bridge-stp off
        bridge-fd 0
        bridge-vlan-aware yes
        bridge-vids 2-4094

同样可以套用绑定 , 以保证主机管理网络的可靠性:

auto lo
iface lo inet loopback

iface eno1 inet manual
iface eno2 inet manual

auto bond0
iface bond0 inet manual
      bond-slaves eno1 eno2
      bond-miimon 100
      bond-mode 802.3ad
      bond-xmit-hash-policy layer2+3

iface bond0.5 inet manual

auto vmbr0v5
iface vmbr0v5 inet static
        address  10.10.10.2/24
        gateway  10.10.10.1
        bridge-ports bond0.5
        bridge-stp off
        bridge-fd 0

auto vmbr0
iface vmbr0 inet manual
        bridge-ports bond0
        bridge-stp off
        bridge-fd 0

3.4.9.关闭 IPv6 Disabling IPv6 on the Node

Proxmox VE 在所有环境下默认开启 IPv6 , 各组件均能透明使用。建议保留启用 , 即便您并未在外部网络中配置任何 IPv6 地址。 IPv6 通过 link-local 地址实现的服务无需任何配置即可工作 , 例如可在节点之间高效广播。

但如果实在需要在节点上关闭 IPv6 , 可通过 sysctl 实现。在 /etc/sysctl.d/disable-ipv6.conf 中加入:

net.ipv6.conf.all.disable_ipv6 = 1

使变更立即生效 , 执行 sysctl -p

3.4.10.关闭桥端口的 MAC 学习 Disabling MAC Learning on a Bridge

默认 , 网桥使用 MAC 学习以便处理流量。但在某些环境(例如启用了客户端隔离 / Public Wi-Fi 类型的环境)中可能不希望使用 MAC 学习。

要在 Proxmox VE 桥上关闭 MAC 学习 , 可在 /etc/network/interfaces 中相应桥下加入:

bridge-disable-mac-learning 1

之后 Proxmox VE 会手动把客户机的 MAC、IP 添加到桥的转发数据库 , 而不依赖学习。

3.5.时间同步 Time Synchronization

现代计算机系统通常使用 网络时间协议(Network Time Protocol,NTP) 在网络上自动同步时间。 Proxmox VE 完全建立在系统范围时间同步之上。

所有 Proxmox VE 集群节点都必须保持时间同步 , 否则身份认证(如使用了 Kerberos)、副本(replication)和备份等关键功能可能不工作。

NOTE

Debian Bookworm 中默认安装并使用 chrony。Debian Bullseye 及其之前版本默认使用 systemd-timesyncd。从 Bullseye 升级到 Bookworm 后 , 需要手动安装 chronysystemd-timesyncd

3.5.1.使用自定义 NTP 服务器 Using Custom NTP Servers

一般默认配置已可使用 Debian 提供的服务器作为 NTP 源。然而 , 在隔离网络或希望使用您自己 NTP 服务器的场景下 , 修改 NTP 服务器很有帮助。

For chrony:

/etc/chrony/chrony.conf 中指定要使用的服务器:

server ntp1.example.com iburst
server ntp2.example.com iburst
server ntp3.example.com iburst

重启 chrony 服务:

# systemctl restart chronyd

查看日志确认新配置生效:

# journalctl --since -1h -u chrony
...
Aug 26 13:00:09 node1 systemd[1]: Started chrony, an NTP client/server.
Aug 26 13:00:15 node1 chronyd[4873]: Selected source 10.0.0.1 (ntp1.example.com)
Aug 26 13:00:15 node1 chronyd[4873]: System clock TAI offset set to 37 seconds
...
For systemd-timesyncd:

/etc/systemd/timesyncd.conf 中指定要使用的服务器:

[Time]
NTP=ntp1.example.com ntp2.example.com ntp3.example.com ntp4.example.com

然后重启同步服务(systemctl restart systemd-timesyncd)并通过 journalctl --since -1h -u systemd-timesyncd 验证新配置已被使用:

...
Oct 07 14:58:36 node1 systemd[1]: Stopping Network Time Synchronization...
Oct 07 14:58:36 node1 systemd[1]: Starting Network Time Synchronization...
Oct 07 14:58:36 node1 systemd[1]: Started Network Time Synchronization.
Oct 07 14:58:36 node1 systemd-timesyncd[13514]: Using NTP server 10.0.0.1:123 (ntp1.example.com).
Oct 07 14:58:36 node1 systemd-timesyncd[13514]: interval/delta/delay/jitter/drift 64s/-0.002s/0.020s/0.000s/-31ppm
...

3.6.外部指标服务器 External Metric Server

指标服务器列表

从 Proxmox VE 4.0 开始 , 您可以定义外部指标服务器 , 它将周期性接收来自您主机的各种统计数据。

当前支持的指标服务器有:

外部指标服务器在 /etc/pve/status.cfg 中定义 , 也可通过 Web 界面配置。

3.6.1.Graphite 服务器配置 Graphite server configuration

Graphite 配置界面

默认服务器期望工作在端口 2003 并使用默认的 proxmox 数据库路径(schema)。

可以在配置中指定使用的协议为 udp、tcp 或 http(s);超时(timeout)默认 1 秒。完整选项见 pvesh help cluster status set

使用 http(s) 时 , 还可以指定 路径(path)。设置已记录的内容到 Graphite 的不同位置时此项有用。

3.6.2.Influxdb 插件配置 Influxdb plugin configuration

InfluxDB 配置界面

Proxmox VE 通过 UDP 发送数据 , 因此您的 influxdb 服务器必须按此模式配置。下面是 1.x 版的合适示例配置段:

[[udp]]
   enabled = true
   bind-address = "0.0.0.0:8089"
   database = "proxmox"
   batch-size = 1000
   batch-timeout = "1s"

在 influxdb 的 config.toml 中设置完毕后 , 需要重启 influxdb 服务。

同时 , Proxmox VE 也支持 InfluxDB 2.x 的 http api。它可与 OSS 2.x 一起使用 , 也可与 cloud 或企业版一起使用。

要配置外部指标服务器 , 您还需要 InfluxDB 中创建的有效访问令牌(API token)。该 token 需要在配置好的组织中拥有写入存储桶的权限。

OSS 版本中也可以使用 v1 兼容 API, 但应配合 v1 兼容的认证方式。这在 cloud 版本中并不可用 , 因为只支持 v2 API。

对于 v1 兼容性 , 应在 user 字段写入用户名 , password 字段写入密码。
对于较新的 v2 API 调用 , 可只填写 token , 留空 user。

另外可以指定 organizationbucket 与是否检查 TLS 证书。
有效组织名只能包含 ASCII 字符 0x20–0x7e。

3.7.磁盘健康监控 Disk Health Monitoring

尽管推荐使用稳健且冗余的存储 , 监控本地磁盘健康仍非常有帮助。

从 Proxmox VE 4.3 开始 , 安装并默认激活 smartmontools。它是一组用于监视并控制现代 ATA、SCSI 与 NVMe 等设备本机 SMART 系统的工具与守护进程。

可在 GUI 中获取磁盘的 SMART 状态 , 选择某节点后选择 Disks 面板 , 选定磁盘后点击 Show S.M.A.R.T. values, 也可在 shell 中运行:

# smartctl -a /dev/sdX

其中 /dev/sdX 为待查询的磁盘设备路径。

若返回结果显示 SMART 已禁用 , 启用:

# smartctl -s on /dev/sdX

关于 smartctl 的更多用法 , 见 man smartctl

默认 , smartmontools 守护进程 smartd 处于激活并启用状态 , 每 30 分钟扫描一次 /dev/sdX/dev/hdX 的磁盘 , 检查错误与警告。如有异常 , 信息会以邮件方式发往 root。完整选项详见 man smartdman smartd.conf

在使用硬件 RAID 控制器时 , 检查阵列与磁盘的可能命令最好咨询厂家。常见硬件控制器有:

  • Broadcom MegaRAID — storcli
  • HP Smart Array — ssacli
  • Adaptec — arcconf
  • Microsemi (PMC) — arcconfmaxView

这类工具常见独立于 smartd 单独使用 , 它们可直接询问 RAID 控制器后端磁盘。具体输出取决于控制器型号 , 阵列健康检查应参考相应厂商手册。

在某些 RAID 控制器后端 , smartctl 也可通过 -d 参数访问到单块磁盘 , 例如 smartctl -a -d megaraid,0 /dev/bus/0

建议结合厂家工具与脚本 , 在异常时主动告警 , 而不是等待问题影响业务才发现。

3.8.逻辑卷管理器 (LVM) Logical Volume Manager (LVM)

多数人会把 Proxmox VE 直接安装到本地磁盘上。 Proxmox VE 安装光盘对本地磁盘管理给出多种方案 , 当前默认使用 LVM。安装器会让您选择一块磁盘 , 并将其作为名为 pve 的卷组(Volume Group,VG)的物理卷(Physical Volume,PV)。下面是一次小型 8GB 磁盘的测试安装输出:

# pvs
  PV         VG   Fmt  Attr PSize PFree
  /dev/sda3  pve  lvm2 a--  7.87g 876.00m

# vgs
  VG   #PV #LV #SN Attr   VSize VFree
  pve    1   3   0 wz--n- 7.87g 876.00m

安装器在该 VG 内分配三个逻辑卷(Logical Volume,LV):

# lvs
  LV   VG   Attr       LSize   Pool Origin Data%  Meta%
  data pve  twi-a-tz--   4.38g             0.00   0.63
  root pve  -wi-ao----   1.75g
  swap pve  -wi-ao---- 896.00m
  • root :格式化为 ext4 , 包含操作系统。
  • swap :交换分区。
  • data :使用 LVM-thin , 用于存放 VM 镜像。 LVM-thin 高效地支持快照与克隆 , 适合此用途。

对 Proxmox VE 4.1 之前的版本 , 安装器会创建名为 data 的标准 LV , 挂载在 /var/lib/vz

从 4.2 起 , data 是一个 LVM-thin 池 , 用于存放基于块的客户机镜像 ;/var/lib/vz 仅作为根文件系统下的一个目录。

3.8.1.硬件 Hardware

强烈推荐为此类部署使用带 BBU 的硬件 RAID 控制器。它能提升性能、提供冗余 , 并便于热插拔更换磁盘。

LVM 自身对硬件无特殊要求 , 内存占用极低。

3.8.2.引导加载程序 Bootloader

默认安装两个引导加载程序。第一个分区包含标准 GRUB ; 第二个分区是 EFI System Partition(ESP) , 用以在 EFI 系统上引导 , 并能从用户态执行 持久化固件更新

3.8.3.创建卷组 Creating a Volume Group

假设我们有一块空盘 /dev/sdb , 要在其上创建名为 vmdata 的卷组。

CAUT

下列命令会销毁 /dev/sdb 上的所有现有数据 , 请务必先确认您选择了正确的磁盘。

先创建一个分区:

# sgdisk -N 1 /dev/sdb

不交互确认地创建一个 PV , 元数据大小为 250K:

# pvcreate --metadatasize 250k -y -ff /dev/sdb1

/dev/sdb1 上创建名为 vmdata 的卷组:

# vgcreate vmdata /dev/sdb1

3.8.4.为 /var/lib/vz 创建额外 LV Creating an extra LV for /var/lib/vz

方法很简单 , 创建一个新的 thin LV:

# lvcreate -n <Name> -V <Size[M,G,T]> <VG>/<LVThin_pool>

实际示例:

# lvcreate -n vz -V 10G pve/data

然后在该 LV 上创建文件系统:

# mkfs.ext4 /dev/pve/vz

最后挂载它。

WARN

请确保挂载时 /var/lib/vz 为空。在默认安装中此目录非空。要使其为空 , 最简单做法是:

# systemctl stop pvestatd.service
# systemctl stop pvedaemon.service
# systemctl stop pve-cluster.service
# mv /var/lib/vz /var/lib/vz_tmp
# mkdir /var/lib/vz
# mount /dev/pve/vz /var/lib/vz
# mv /var/lib/vz_tmp/* /var/lib/vz/
# rmdir /var/lib/vz_tmp
# systemctl start pve-cluster.service
# systemctl start pvedaemon.service
# systemctl start pvestatd.service

要让其重启后自动挂载 , 在 /etc/fstab 中添加:

# echo '/dev/pve/vz /var/lib/vz ext4 defaults 0 2' >> /etc/fstab

3.8.5.调整 thin 池大小 Resizing the thin pool

用以下命令同时调整 LV 与元数据池大小:

# lvresize --size +<size[\M,G,T]> --poolmetadatasize +<size[\M,G]> <VG>/<LVThin_pool>
NOTE

扩容数据池时也应同步扩容元数据池(poolmetadatasize)。

3.8.6.创建 LVM-thin 池 Create a LVM-thin pool

thin 池必须建立在卷组之上。如何创建卷组 , 见上节 LVM。

# lvcreate -L 80G -T -n vmstore vmdata

3.9.Linux 上的 ZFS ZFS on Linux

ZFS 是由 Sun Microsystems 设计的、文件系统与逻辑卷管理器合二为一的存储方案。从 Proxmox VE 3.4 起 , Linux 内核原生移植版的 ZFS 文件系统作为可选文件系统加入 , 也可作为根文件系统的额外选项。所有相关软件包都已包含在内 , 无需手工编译 ZFS 模块。

借助 ZFS , 可以用预算内的硬件实现最大化的企业特性 , 也能凭借 SSD 缓存乃至全 SSD 部署构建高性能系统。 ZFS 可在中等 CPU 与内存负载下取代昂贵的硬件 RAID 卡 , 同时管理简单。

ZFS 的总体优势:

  • 通过 Proxmox VE GUI 与 CLI 即可轻松配置与管理
  • 可靠
  • 抵御数据损坏
  • 文件系统级数据压缩
  • 快照
  • 写时复制(copy-on-write)克隆
  • 多种 RAID 级别 :RAID0、 RAID1、 RAID10、 RAIDZ-1、 RAIDZ-2、 RAIDZ-3、 dRAID、 dRAID2、 dRAID3
  • 可使用 SSD 作为缓存
  • 自愈
  • 持续完整性检查
  • 面向大容量存储设计
  • 跨网络异步复制
  • 开源
  • 加密
  • ……

3.9.1.硬件 Hardware

ZFS 对内存极为敏感 , 因此至少需要 8GB 起步。实际上 , 在硬件 / 预算允许范围内尽可能多。为防止数据损坏 , 推荐使用高质量的 ECC RAM。

若使用专用缓存盘和 / 或日志盘 , 应选用企业级 SSD。这能显著提升整体性能。

IMP

请勿在带硬件 RAID 控制器的系统上使用 ZFS(含其自带缓存或读写缓存)。 ZFS 期望直接管理磁盘。一种合适做法是把 RAID 控制器切换为 「HBA / IT」 模式。

若要在 VM 内部(嵌套虚拟化)实验 Proxmox VE 安装 , 不要为该 VM 的磁盘选择 virtio, 它不被 ZFS 支持。请改用 IDE 或 SCSI(virtio SCSI 控制器类型也可以)。

3.9.2.作为根文件系统安装 Installation as Root File System

使用 Proxmox VE 安装器时 , 您可选择 ZFS 作为根文件系统。安装时需选择 RAID 类型:

RAID0也称「条带(striping)」。容量为各盘容量之和。但 RAID0 不增加冗余 , 任意单盘故障即导致整个卷无法使用。
RAID1也称「镜像(mirroring)」。数据被同样地写入所有盘。至少需要 2 块同等容量盘 , 可用容量为单盘容量。
RAID10RAID0 与 RAID1 的组合。至少 4 块盘。
RAIDZ-1RAID-5 的变种 , 单校验。至少 3 块盘。
RAIDZ-2RAID-5 的变种 , 双校验。至少 4 块盘。
RAIDZ-3RAID-5 的变种 , 三校验。至少 5 块盘。

安装器会自动分区、创建名为 rpool 的 ZFS 池 , 并在 ZFS 子卷 rpool/ROOT/pve-1 上安装根文件系统。

另一个子卷 rpool/data 用于存放 VM 镜像。为让 Proxmox VE 工具识别它 , 安装器会在 /etc/pve/storage.cfg 中加入:

zfspool: local-zfs
        pool rpool/data
        sparse
        content images,rootdir

安装完成后 , 用 zpool 命令查看 ZFS 池状态:

# zpool status
  pool: rpool
 state: ONLINE
  scan: none requested
config:

        NAME        STATE     READ WRITE CKSUM
        rpool       ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            sda2    ONLINE       0     0     0
            sdb2    ONLINE       0     0     0
          mirror-1  ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0

errors: No known data errors

zfs 命令配置与管理 ZFS 文件系统。下例列出安装后所有文件系统:

# zfs list
NAME               USED  AVAIL  REFER  MOUNTPOINT
rpool             4.94G  7.68T    96K  /rpool
rpool/ROOT         702M  7.68T    96K  /rpool/ROOT
rpool/ROOT/pve-1   702M  7.68T   702M  /
rpool/data          96K  7.68T    96K  /rpool/data
rpool/swap        4.25G  7.69T    64K  -

3.9.3.ZFS RAID 级别考虑 ZFS RAID Level Considerations

选择 ZFS 池的布局时 , 有几个因素需要权衡。 ZFS 池的基本构建块是 虚拟设备(vdev)。池中所有 vdev 被同等使用 , 数据在它们之间条带化(RAID0)。 vdev 详情见 zpoolconcepts(7) 手册页。

性能 Performance

每种 vdev 类型的性能特征不同。两个关注的指标是 IOPS(每秒 I/O 操作数)与读写带宽。

mirror vdev(RAID1)在写入时表现近似于单盘。读取性能则随镜像中盘数线性提升。

常见情形 :4 块盘做 2 个 mirror vdev(RAID10), 写性能近似两块单盘的 IOPS 与带宽 , 读性能近似 4 块单盘。

任意冗余级别的 RAIDZ 在 IOPS 上接近单盘 , 带宽较高。具体带宽取决于 RAIDZ vdev 的大小与冗余级别。

dRAID 池性能应与等价的 RAIDZ 池相当。

对运行 VM 来说 , IOPS 在多数场景下是更重要的指标。

容量、空间使用与冗余 Size, Space usage and Redundancy

mirror vdev 组成的池性能特征最好 , 但可用空间为可用盘的 50%。若 mirror vdev 中盘数超过 2(如三向镜像), 则可用空间更少。每个 mirror vdev 至少需要一块健康盘 , 池才能继续工作。

由 N 块盘组成的 RAIDZ 类型 vdev 的可用空间约为 N-P,P 即 RAIDZ 级别。 RAIDZ 级别表示在不丢数据情况下任意可故障盘数。一个特殊情况 :4 盘 RAIDZ2, 此时通常用 2 个 mirror vdev 性能更好 , 可用空间相同。

使用任何 RAIDZ 级别时还需注意 ZVOL 数据集(用于 VM 磁盘)的行为。每个数据块都需要至少与池 ashift 值定义的最小块大小等同的校验数据。 ashift=12 时池块大小为 4k , 而 ZVOL 默认块大小为 8k。因此在 RAIDZ2 中每写入一个 8k 块 , 还会额外写入两个 4k 校验块 ,8k + 4k + 4k = 16k。这是简化看法 , 实际还会有元数据、压缩等。

该行为可通过查看 ZVOL 的以下属性观察:

  • volsize
  • refreservation(池非精简置备时)
  • used(池精简置备且无快照时)
# zfs get volsize,refreservation,used <pool>/vm-<vmid>-disk-X

volsize 是磁盘对外呈现给 VM 的大小 , refreservation 显示在池上预留的空间 , 含校验数据所需空间。若池为精简置备 , refreservation 为 0。还可对比 VM 内部使用空间与 used 属性 , 但快照会影响该值。

有几种应对空间放大的方法:

  • 增大 volblocksize 以提升 数据 / 校验 比
  • mirror vdev 替换 RAIDZ
  • 使用 ashift=9(512 字节块)

volblocksize 仅在创建 ZVOL 时可设置。默认值可在存储配置中调整。这样做时客户机内也需相应调优 , 视用例不同 , 写放大问题只是从 ZFS 层移到客户机层。

创建池时使用 ashift=9 可能会因底层盘特性导致性能不佳 , 而且后续无法更改。

Mirror vdev(RAID1、 RAID10)对 VM 工作负载行为更好。除非环境有特定需求且能接受 RAIDZ 性能特征 , 否则推荐使用 mirror。

3.9.4.ZFS dRAID ZFS dRAID

在 ZFS dRAID(declustered RAID)中 , 热备盘参与到 RAID 中。它们的备用容量在某盘故障时被预留并用于重建。视配置而定 , 这能比 RAIDZ 在盘故障时获得更快重建。详见 OpenZFS 官方文档。

NOTE

dRAID 为大池设计 , 不建议用于少于 10–15 块盘的部署。少盘场景下使用 RAIDZ 通常更好。

NOTE

GUI 要求 dRAID 至少使用所选 vdev 数量的 2 倍以上磁盘 , 加上 1 块或更多备盘。

  • dRAID1 或 dRAID :至少 2 块盘 , 在不丢数据前可故障 1 块
  • dRAID2 :至少 3 块盘 , 在不丢数据前可故障 2 块
  • dRAID3 :至少 4 块盘 , 在不丢数据前可故障 3 块

更多信息见手册页:

# man zpoolconcepts
备盘与数据 Spares and Data

spares 数量告诉系统应保留多少盘作为故障备盘。默认 0。无备盘时重建不会获得加速。

data 定义冗余组中的设备数。默认 8。除非 盘 - 校验 - 备盘 小于 8 时取较小值。一般地 , 较少的数据设备数能带来更高 IOPS、更好压缩比与更快重建(resilver) , 但会减少池可用容量。

3.9.5.引导加载程序 Bootloader

Proxmox VE 使用 proxmox-boot-tool 管理引导加载程序配置。详见 Proxmox VE 主机引导加载程序 一节(§3.13)。

3.9.6.ZFS 管理 ZFS Administration

本节给出常见任务的若干用例。 ZFS 本身十分强大且选项丰富。管理 ZFS 的主要命令是 zfszpool。两者都附带详尽手册页:

# man zpool
# man zfs
创建新的 zpool Create a new zpool

创建新池至少需要一块盘。 ashift 应与底层盘扇区大小(2 的 ashift 次方)相等或更大。

# zpool create -f -o ashift=12 <pool> <device>
TIP

池名必须遵循以下规则 :以字母开头 , 仅含字母、数字、 _-:. 与空格 , 不能以保留字 mirrorraidzdraidspare 开头 , 也不能为关键字 log

启用压缩(见 ZFS 压缩):

# zfs set compression=lz4 <pool>
创建 RAID-0 池 Create a new pool with RAID-0

至少 1 块盘:

# zpool create -f -o ashift=12 <pool> <device1> <device2>
创建 RAID-1 池 Create a new pool with RAID-1

至少 2 块盘:

# zpool create -f -o ashift=12 <pool> mirror <device1> <device2>
创建 RAID-10 池 Create a new pool with RAID-10

至少 4 块盘:

# zpool create -f -o ashift=12 <pool> mirror <device1> <device2> mirror <device3> <device4>
创建 RAIDZ-1 池 Create a new pool with RAIDZ-1

至少 3 块盘:

# zpool create -f -o ashift=12 <pool> raidz1 <device1> <device2> <device3>
创建 RAIDZ-2 池 Create a new pool with RAIDZ-2

至少 4 块盘:

# zpool create -f -o ashift=12 <pool> raidz2 <device1> <device2> <device3> <device4>

建立池前 , 请阅读 ZFS RAID 级别考虑 一节以大致估算 IOPS 与带宽预期 , 尤其是要使用 RAID-Z 模式时。

扩展 RAIDZ-N Extend RAIDZ-N
NOTE

扩展 RAIDZ vdev 后 , 此前已写入数据的 数据 / 校验 比仍保持原值 , 仅新写入的数据使用新比。

假设已有池 <pool>, 其中含 RAIDZ-N vdev <raidzN-M> , 用以下语法添加新物理盘 <device>

zpool attach <pool> <raidzN-M> <device>

zpool status <pool> 验证总体成功 , 用 zpool list <pool> -v 查看每盘详情。 zfs list <pool> 可查看池的新容量。

创建带缓存(L2ARC)的池 Create a new pool with cache (L2ARC)

可使用专用设备或分区作为二级缓存以提升性能。这种缓存对以静态数据为主、随机读多的工作负载尤其有帮助。它充当实际存储与内存中 ARC 之间的额外缓存层 , 内存受限不得不缩减 ARC 时也能起作用。

创建带磁盘缓存的 ZFS 池:

# zpool create -f -o ashift=12 <pool> <device> cache <cache-device>

这里只用了单 <device> 与单 <cache-device> , 但也可与上文的 RAID 模式组合。

注意 :缓存设备没有 mirror 或 raid 模式 , 它们只是简单累加。若任一缓存设备读出错 , ZFS 会透明地把请求转回底层存储层。

创建带日志(ZIL)的池 Create a new pool with log (ZIL)

可使用专用盘或分区作 ZFS Intent Log(ZIL)。它主要用于安全的同步事务 , 故常出现在如数据库等性能关键路径上 , 或频繁触发 fsync 的程序。

池本身被默认作为 ZIL 位置 , 把 ZIL I/O 转移到独立设备能减少事务延迟 , 同时减轻主池压力 , 提升整体性能。

用作日志设备的盘 / 分区推荐:

  • 使用带掉电保护的快速 SSD , 提交延迟更小
  • 分区(或整盘)至少几 GB , 但超过已装内存一半再增加并不会带来实际优势

创建带独立日志设备的 ZFS 池:

# zpool create -f -o ashift=12 <pool> <device> log <log-device>

上例只用单 <device> 与单 <log-device> , 也可与其他 RAID 变种组合。

还可把日志设备做成多盘镜像 , 主要确保单一日志设备故障时性能不会立刻下降。

若所有日志设备都失效 , ZFS 主池本身会再次被使用 , 直到日志设备被替换。

给现有池添加缓存与日志 Add cache and log to an existing pool

若已有池但无缓存与日志 , 仍可随时添加 , 或仅添加其中一种。

例 :您有一块带掉电保护的优质企业级 SSD , 想用来提升池整体性能。日志设备最大尺寸约为已装物理内存的一半 , 因此 ZIL 在 SSD 上往往只占小部分 , 余下空间可作缓存。

先用 partedgdisk 在 SSD 上创建两个 GPT 分区 , 然后加入池:

# zpool add -f <pool> log <device-part1> cache <device-part2>

<pool><device-part1><device-part2> 替换为池名与两个 /dev/disk/by-id/ 分区路径即可。

也可分别添加 ZIL 与缓存。给现有 ZFS 池添加日志设备:

# zpool add <pool> log <log-device>
更换故障设备 Changing a failed device
# zpool replace -f <pool> <old-device> <new-device>

更换可引导的故障设备

视 Proxmox VE 安装方式不同 , 系统使用 systemd-boot 或经 proxmox-boot-tool 调用 GRUB , 或使用纯 GRUB 作为引导加载程序(见 主机引导加载程序)。可执行:

# proxmox-boot-tool status

复制分区表、重发 GUID 与替换 ZFS 分区的步骤都相同。要让系统能从新盘引导 , 后续步骤随所用引导加载程序而异。

# sgdisk <healthy bootable device> -R <new device>
# sgdisk -G <new device>
# zpool replace -f <pool> <old zfs partition> <new zfs partition>
NOTE

使用 zpool status 确认 resilver 完成后再继续。

使用 proxmox-boot-tool

# proxmox-boot-tool format <new disk's ESP>
# proxmox-boot-tool init <new disk's ESP> [grub]
NOTE

ESP 即 EFI System Partition , 默认是 proxmox-boot-tool 管理的可引导盘上的第 2 分区(自 5.4 起的安装版本)。详情见 设置新分区作为同步 ESP

NOTE

对未使用 proxmox-boot-tool 的系统 , 检查 / 复制分区方案与 ZFS 内部结构通常需要更多步骤 , 详见对应文档。

使用纯 GRUB

# grub-install <new disk>
NOTE

对单盘故障 , 可通过两块盘并行的 mirror vdev 做无停机替换。

3.9.7.配置邮件通知 Configure E-Mail Notification

ZFS 自带事件守护进程 ZED , 用于监听 ZFS 内核模块产生的事件。该守护进程也能在如池错误等 ZFS 事件发生时发送邮件。新版 ZFS 把守护进程拆到独立包 zfs-zed , 在 Proxmox VE 默认已安装。

用您喜欢的编辑器修改 /etc/zfs/zed.d/zed.rc 进行配置。邮件通知所需的设置是 ZED_EMAIL_ADDR , 默认 root

ZED_EMAIL_ADDR="root"

请注意 , Proxmox VE 会把发送给 root 的邮件转发到 root 用户配置的邮箱地址。

3.9.8.限制 ZFS 内存使用 Limit ZFS Memory Usage

ZFS 默认使用主机内存的 50% 作为自适应替换缓存(ARC)。从 Proxmox VE 8.1 起 , 新装系统的 ARC 使用上限设为已装物理内存的 10% , 上限不超过 16 GiB。该值写入 /etc/modprobe.d/zfs.conf

为 ARC 分配足够内存对 I/O 性能至关重要 , 减小要谨慎。一般经验 :至少 2 GiB 起 + 每 TiB 存储 1 GiB。例如 8 TiB 池应给 ARC 10 GiB 内存。

ZFS 也强制最小值为 64 MiB。

修改本次启动的 ARC 上限(重启后丢失) , 直接写入 zfs_arc_max 模块参数:

 echo "$[10 * 1024*1024*1024]" >/sys/module/zfs/parameters/zfs_arc_max

永久修改 ARC 上限 , 在 /etc/modprobe.d/zfs.conf 中加入(或修改):

options zfs zfs_arc_max=8589934592

本例将上限设为 8 GiB(8 × 230)。

IMP

若期望 zfs_arc_max 取值小于等于 zfs_arc_min(默认为系统内存的 1/32), 则需同时把 zfs_arc_min 设为不大于 zfs_arc_max - 1

echo "$[8 * 1024*1024*1024 - 1]" >/sys/module/zfs/parameters/zfs_arc_min
echo "$[8 * 1024*1024*1024]" >/sys/module/zfs/parameters/zfs_arc_max

该例(临时)把上限设为 8 GiB , 用于总内存超过 256 GiB 的系统 , 此时仅设 zfs_arc_max 不会生效。

IMP

若根文件系统是 ZFS , 每次更改这些值后需更新 initramfs 才能持久生效:

# update-initramfs -u -k all

3.9.9.ZFS 上的 SWAP SWAP on ZFS

在 zvol 上创建的交换空间可能造成问题 , 例如服务器卡死或产生高 I/O 负载 , 在向外部存储启动备份时尤为常见。

强烈建议确保有足够内存以避免低内存场景。若必须或希望添加 swap , 推荐在物理盘上创建分区作为 swap 设备。可在安装器高级选项中预留空间。还可降低 swappiness, 服务器推荐值 10:

# sysctl -w vm.swappiness=10

要持久化 , 编辑 /etc/sysctl.conf 加入:

vm.swappiness = 10
取值策略
vm.swappiness = 0仅在出现「内存不足(out of memory)」时才会 swap
vm.swappiness = 1最小程度 swap , 但不完全禁用
vm.swappiness = 10系统内存充足时 , 该值有时被推荐用以提升性能
vm.swappiness = 60默认值
vm.swappiness = 100内核会激进 swap

3.9.10.加密的 ZFS 数据集 Encrypted ZFS Datasets

WARN

ZFS 原生加密功能在 ZoL 0.8.0 引入。虽已成熟 , 但仍属较新 , 与未加密数据集相比有一些不足 , 详见参考链接。

ZoL 0.8.0 起支持数据集原生加密。从更早版本升级后 , 可在每个池上启用加密特性:

# zpool get feature@encryption tank
NAME  PROPERTY            VALUE            SOURCE
tank  feature@encryption  disabled         local

# zpool set feature@encryption=enabled

# zpool get feature@encryption tank
NAME  PROPERTY            VALUE            SOURCE
tank  feature@encryption  enabled         local
WARN

暂不支持以 GRUB 引导的 ZFS-on-root 启用此特性 , 在 systemd-boot 下也仅有限支持。

NOTE

启用后无法回退 , 必须重新创建池才能撤销。

WARN

务必妥善备份与保管密钥材料。在没有密钥的情况下 , 已加密数据无法访问。

加密需在创建数据集 / zvol 时设置 , 并默认被子数据集继承。例如创建加密数据集 tank/encrypted_data 并将其配置为 Proxmox VE 存储:

# zfs create -o encryption=on -o keyformat=passphrase tank/encrypted_data
Enter passphrase:
Re-enter passphrase:

# pvesm add zfspool encrypted_zfs -pool tank/encrypted_data

此存储上创建的所有客户机卷 / 磁盘都会以父数据集的共享密钥材料加密。要实际使用该存储 , 需载入相关密钥材料并挂载数据集 , 一步完成:

# zfs mount -l tank/encrypted_data
Enter passphrase for 'tank/encrypted_data':

也可以使用(随机)密钥文件代替交互输入 , 通过设置 keylocationkeyformat , 在创建时或对已有数据集用 zfs change-key

# dd if=/dev/urandom of=/path/to/keyfile bs=32 count=1

# zfs change-key -o keyformat=raw -o keylocation=file:///path/to/keyfile tank/encrypted_data
WARN

使用密钥文件时 , 需特别注意访问权限与文件位置 , 防止意外暴露。一旦密钥材料丢失 , 数据将无法解密。

加密数据集下创建的客户机卷 , 其 encryptionroot 属性会指向相应数据集。每个 encryptionroot 仅需载入一次密钥材料即可让其下所有加密数据集可用。

更多细节与高级用法见 encryptionrootencryptionkeylocationkeyformatkeystatus 属性 , zfs load-keyzfs unload-keyzfs change-key 命令 , 以及 man zfs 的 Encryption 节。

3.9.11.ZFS 压缩 Compression in ZFS

对数据集启用压缩后 , ZFS 会在写入前尝试压缩所有 块 , 在读取时解压。已存在数据不会被回溯压缩。

启用压缩:

# zfs set compression=<algorithm> <dataset>

推荐 lz4 , CPU 开销极低。也可使用 lzjbgzip-N(N 为 1 最快到 9 压缩比最佳)。视算法与数据可压缩性而定 , 启用压缩甚至能提升 I/O 性能。

随时可关闭:

# zfs set compression=off <dataset>

同样 , 仅新块受影响。

3.9.12.ZFS Special 设备 ZFS Special Device

从 0.8.0 起 ZFS 支持 special 设备。池中的 special 设备用于存放元数据、去重表 , 也可选地存放小文件块。

对由慢速机械盘组成、元数据变更多的池 , special 设备能显著提速。例如大量创建、更新、删除文件的工作负载会从中受益。 ZFS 数据集也可配置为把整个小文件存于 special 设备 , 进一步提升性能。 special 设备应使用快速 SSD。

IMP

special 设备的冗余应当与池一致 , special 设备故障会让整个池失效。

WARN

向池中添加 special 设备无法撤销。

创建带 special 设备 + RAID-1 的池:

# zpool create -f -o ashift=12 <pool> mirror <device1> <device2> special mirror <device3> <device4>

给现有 RAID-1 池添加 special 设备:

# zpool add <pool> special mirror <device1> <device2>

ZFS 数据集暴露 special_small_blocks=<size> 属性。 size 可为 0(关闭)或 512B–1M 之间的 2 的幂。设置后 , 小于 size 的新文件块将分配到 special 设备。

IMP

special_small_blocks 大于或等于数据集的 recordsize(文件系统默认 128K)或 zvol 的 volblocksize(默认 16K), 所有 数据都将写入 special 设备 , 慎用。

把池上属性的默认值统一改为 4K:

# zfs set special_small_blocks=4K <pool>

仅对单个数据集启用:

# zfs set special_small_blocks=4K <pool>/<filesystem>

对单个数据集关闭:

# zfs set special_small_blocks=0 <pool>/<filesystem>

3.9.13.ZFS 池特性 ZFS Pool Features

ZFS 磁盘上格式的变更只在大版本切换时引入 , 通过 features 指定。所有特性与机制详见 zpool-features(5) 手册页。

启用新特性可能让池无法被旧版 ZFS 导入 , 因此必须由管理员主动执行 zpool upgrade(见 zpool-upgrade(8) 手册页)。

除非确实需要某项新特性 , 否则启用并无好处。

实际上 , 启用新特性还有几项弊端:

  • ZFS-on-root 且仍使用 GRUB 引导的系统 , 一旦 rpool 上启用了新特性 , 可能因 GRUB 中 ZFS 实现不兼容而无法引导。
  • 用旧内核(仍带旧 ZFS 模块)启动时 , 系统将无法导入升级过的池。
  • 用旧 Proxmox VE ISO 抢救无法启动的系统也会同样失败。
IMP

除非您确实需要使用新特性 , 不要 升级池。新特性一旦启用就无法撤销。

启用 ZFS 池新特性:

# zpool upgrade <pool>

3.10.BTRFS BTRFS

WARN

BTRFS 集成目前为技术预览(tech preview)。

BTRFS 是 Linux 内核原生支持的现代写时复制文件系统 , 提供快照、内置 RAID、通过校验和实现数据与元数据自愈等特性。自 Proxmox VE 7.0 起 , BTRFS 作为根文件系统的可选项引入。

BTRFS 总体优势:

  • 主系统设置几乎与基于 ext4 的传统方式一致
  • 快照
  • 文件系统级数据压缩
  • 写时复制克隆
  • RAID0、 RAID1、 RAID10
  • 抵御数据损坏
  • 自愈
  • Linux 内核原生支持

注意事项:

  • RAID 5/6 仍为实验性且危险 , 见 BTRFS Status。

3.10.1.作为根文件系统安装 Installation as Root File System

使用 Proxmox VE 安装器时可选 BTRFS 作为根文件系统。安装时需选 RAID 类型:

RAID0「条带」。容量为各盘容量之和。无冗余 , 任一盘故障整卷不可用。
RAID1「镜像」。数据同写所有盘 , 至少 2 块同容量盘 , 可用容量为单盘。
RAID10RAID0 与 RAID1 组合 , 至少 4 块盘。

安装器自动分区并在 /var/lib/pve/local-btrfs 创建额外子卷。为让 Proxmox VE 工具识别 , 安装器在 /etc/pve/storage.cfg 中创建以下条目:

dir: local
        path /var/lib/vz
        content iso,vztmpl,backup
        disable

btrfs: local-btrfs
        path /var/lib/pve/local-btrfs
        content iso,vztmpl,backup,images,rootdir

此举显式禁用默认的 local 存储 , 改用额外子卷上的 BTRFS 存储条目。

btrfs 命令配置与管理 BTRFS 文件系统。安装后列出所有额外子卷:

# btrfs subvolume list /
ID 256 gen 6 top level 5 path var/lib/pve/local-btrfs

3.10.2.BTRFS 管理 BTRFS Administration

本节给出常见任务的若干用例。

创建 BTRFS 文件系统 Creating a BTRFS file system

mkfs.btrfs 创建 BTRFS。 -d-m 分别设置数据与元数据 profile , 可选 -L 设标签。支持 singleraid0raid1raid10

在单盘 /dev/sdb 上创建 , 标签 My-Storage

 # mkfs.btrfs -m single -d single -L My-Storage /dev/sdb

在两个分区上创建 RAID1:

 # mkfs.btrfs -m raid1 -d raid1 -L My-Storage /dev/sdb1 /dev/sdc1
挂载 BTRFS Mounting a BTRFS file system

可手动挂载:

 # mkdir /my-storage
 # mount /dev/sdb /my-storage

也可像其他挂载点一样加入 /etc/fstab 以便开机自动挂载。强烈建议使用 mkfs.btrfs 打印的 UUID 而非块设备路径 , 尤其多盘场景。

文件 /etc/fstab 示例:

# ... 其他挂载点省略
# 强烈推荐使用 mkfs.btrfs 输出的 UUID
UUID=e2c0c3ff-2114-4f54-b767-3a203e49f6f3 /my-storage btrfs defaults 0 0
TIP

若出现 UUID 冲突(例如克隆盘) , 需要先解决冲突才能挂载。

然后首次挂载:

mount /my-storage

下次重启起系统会自动挂载。

把 BTRFS 加入 Proxmox VE Adding a BTRFS file system to Proxmox VE

可通过 Web 界面或 CLI 添加现有 BTRFS 文件系统:

pvesm add btrfs my-storage --path /my-storage
创建子卷 Creating a subvolume

创建子卷会把它链接到 BTRFS 文件系统上的某个路径 , 该路径对外表现为普通目录。

# btrfs subvolume create /some/path
删除子卷 Deleting a subvolume

rmdir 删除目录不同 , 用 btrfs 命令删除子卷时不需要子卷为空。

# btrfs subvolume delete /some/path
创建子卷快照 Creating a snapshot of a subvolume

BTRFS 并不严格区分快照与普通子卷 , 因此创建快照也可视为创建子卷的任意副本。 Proxmox VE 约定在为客户机磁盘 / 子卷创建快照时使用只读标志 , 但之后仍可修改该标志。

# btrfs subvolume snapshot -r /some/path /a/new/path

这会在 /a/new/path 处创建 /some/path 的只读「克隆」。对 /some/path 的后续修改会导致受影响数据在修改前被复制。省略 -r 则两个子卷都可写。

启用压缩 Enabling compression

BTRFS 默认不压缩。可通过添加 compress 挂载选项启用。已写入数据不会被回溯压缩。

默认 rootfs 在 /etc/fstab 中形如:

UUID=<uuid of your root file system> / btrfs defaults 0 1

可追加 compress=zstdcompress=lzocompress=zlib

UUID=<uuid of your root file system> / btrfs defaults,compress=zstd 0 1

重启后生效。

检查空间使用 Checking Space Usage

经典的 df 在某些 BTRFS 配置下输出可能令人困惑。更准确地用 btrfs filesystem usage /PATH

# btrfs fi usage /my-storage

3.11.Proxmox 节点管理 Proxmox Node Management

Proxmox VE 节点管理工具 pvenode 可用于控制节点专有的设置与资源。

目前 pvenode 支持设置节点描述、对节点上客户机批量操作、查看节点任务历史、以及管理节点 SSL 证书(用于 API 与由 pveproxy 提供的 Web GUI)。

3.11.1.Wake-on-LAN Wake-on-LAN

Wake-on-LAN(WoL)通过发送「幻数据包」远程唤醒网络中处于睡眠的计算机。至少一块 NIC 必须支持该特性 , 且须在 BIOS/UEFI 中启用相应选项(名称可能是 Enable Wake-on-LanPower On By PCIE Device , 详询主板厂商手册)。可用 ethtool 检查某接口的 WoL 配置:

ethtool <interface> | grep Wake-on

pvenode 可通过 WoL 唤醒集群中处于睡眠的成员:

pvenode wakeonlan <node>

这会在 UDP 端口 9 广播 WoL 幻包 , 包中含从 wakeonlan 属性获取的 <node> MAC 地址。用如下命令设置节点专有的 wakeonlan 属性:

pvenode config set -wakeonlan XX:XX:XX:XX:XX:XX

发送 WoL 包的接口由默认路由决定。可用 bind-interface 覆盖:

pvenode config set -wakeonlan XX:XX:XX:XX:XX:XX,bind-interface=<iface-name>

广播地址(默认 255.255.255.255)可用 broadcast-address 显式改变:

pvenode config set -wakeonlan XX:XX:XX:XX:XX:XX,broadcast-address=<broadcast-address>

3.11.2.任务历史 Task History

排查服务器问题(例如失败的备份任务)时 , 查看先前任务的日志常常很有帮助。 Proxmox VE 通过 pvenode task 命令访问节点任务历史。

list 子命令获取经过过滤的已完成任务列表。例如列出与 VM 100 相关且以错误结束的任务:

pvenode task list --errors --vmid 100

用 UPID 查看任务日志:

pvenode task log UPID:pve1:00010D94:001CA6EA:6124E1B9:vzdump:100:root@pam:

3.11.3.批量客户机电源管理 Bulk Guest Power Management

对大量 VM / 容器 , 可用 pvenodestartallstopall 子命令批量启停。默认 pvenode startall 仅启动设为开机自启的客户机(见 自动启动 / 关机) , 可用 --force 覆盖该行为。两命令均支持 --vms 限定 VMID。

例如无论是否设了 onboot , 都启动 VM 100101102

pvenode startall --vms 100,101,102 --force

停止上述客户机(以及任何其他正在运行者):

pvenode stopall
NOTE

stopall 先尝试正常关闭 , 只有超时后才强行停止。

3.11.4.首个客户机启动延迟 First Guest Boot Delay

若您的 VM / 容器依赖缓慢启动的外部资源(例如 NFS 服务器), 可为节点设置一个从 Proxmox VE 启动到第一台配置为 autostart 的客户机启动之间的延迟。

设置如下(10 表示 10 秒):

pvenode config set --startall-onboot-delay 10

3.11.5.批量客户机迁移 Bulk Guest Migration

升级场景中若需把所有客户机从一节点迁到另一节点 , pvenode 也提供 migrateall 子命令。默认会把系统上所有客户机迁到目标节点 , 也可限定一组客户机。

例如将 VM 100101102 带本地磁盘在线迁到节点 pve2

pvenode migrateall pve2 --vms 100,101,102 --with-local-disks

3.11.6.气球驱动 RAM 使用目标 RAM Usage Target for Ballooning

自动内存分配 的目标百分比默认为 80%。可用 ballooning-target 属性按节点自定义。例如将目标设为 90%:

pvenode config set --ballooning-target 90

3.12.证书管理 Certificate Management

3.12.1.集群内通信证书 Certificates for Intra-Cluster Communication

每个 Proxmox VE 集群默认会创建自己的(自签)证书颁发机构(CA) , 并为每个节点生成由该 CA 签发的证书。这些证书用于与集群 pveproxy 服务的加密通信以及使用 SPICE 时的 Shell / 控制台功能。

CA 证书与密钥保存在 Proxmox Cluster File System(pmxcfs) 中。

3.12.2.API 与 Web GUI 证书 Certificates for API and Web GUI

REST API 与 Web GUI 由每个节点上运行的 pveproxy 服务提供。 pveproxy 所用证书有以下选项:

  1. 默认使用节点专属证书 /etc/pve/nodes/NODENAME/pve-ssl.pem。该证书由集群 CA 签名 , 因此不会被浏览器与操作系统自动信任。
  2. 使用外部提供的证书(例如由商业 CA 签名)。
  3. 使用 ACME(Let's Encrypt)获取可信证书并自动续期 , 该方式也集成在 Proxmox VE API 与 Web 界面中。

选项 2 与 3 使用的文件是 /etc/pve/local/pveproxy-ssl.pem/etc/pve/local/pveproxy-ssl.key(后者不可有口令)。

NOTE

不要替换或修改 /etc/pve/local/pve-ssl.pem/etc/pve/local/pve-ssl.key, 它们是节点专属的 , 由集群 CA 管理。

证书通过 Proxmox VE 节点管理命令进行管理(见 pvenode(1) 手册页)。

WARN

请勿手动替换这些文件的内容 , 除非完全了解后果。重启 pveproxy 服务后更改才会生效。

3.12.3.上传自定义证书 Upload Custom Certificate

若您已有希望用于某 Proxmox VE 节点的证书 , 可直接通过 Web 界面上传。注意证书的密钥文件(若提供)不得被口令保护。

3.12.4.通过 Let's Encrypt(ACME)获取可信证书 Trusted certificates via Let's Encrypt (ACME)

Proxmox VE 内置 ACME(Automatic Certificate Management Environment)协议实现 , 允许管理员使用 Let's Encrypt 等 ACME 提供方轻松设置 TLS 证书 , 这些证书能在现代操作系统与浏览器中开箱即信任。

目前实现的两种 ACME 端点是 Let's Encrypt 生产与其 staging 环境。 ACME 客户端支持使用内置 Web 服务器完成 http-01 校验 , 以及使用 DNS 插件完成 dns-01 校验(支持 acme.sh 所有 DNS API 端点)。

ACME 账户 ACME Account

每个集群需为其所用端点注册一个 ACME 账户。该账户邮箱将作为 ACME 端点发来的续期到期或类似通知的联系点。

可在 Web 界面 数据中心 → ACME 或用 pvenode CLI 注册 / 停用 ACME 账户:

 pvenode acme account register account-name mail@example.com
TIP

由于速率限制 , 建议先用 Let's Encrypt staging 端点测试配置 , 再切到生产端点。

ACME 插件 ACME Plugins

ACME 插件的任务是自动验证您(以及您操作下的 Proxmox VE 集群)是某域名的真实持有者。这是自动证书管理的基础。

ACME 协议定义了多种挑战类型 , 例如 http-01:由 Web 服务器提供一个具有特定内容的文件以证明对域名的控制。若因技术限制或记录对应地址无法从公网访问 , 可改用 dns-01:通过在域名区创建特定 DNS 记录完成挑战。

Proxmox VE 开箱支持这两种挑战。您可通过 Web 界面(数据中心 → ACME)或 pvenode acme plugin add 命令配置插件。插件配置保存在 /etc/pve/priv/acme/plugins.cfg, 对集群所有节点可用。

节点域名 Node Domains

每个域名是节点专属的。可在 节点 → 证书 或用 pvenode config 命令添加或管理。配置好所需域名、确认已选所需 ACME 账户 , 即可通过 Web 界面下单获取证书。成功后界面将在 10 秒后刷新。续期将自动进行。

3.12.5.ACME HTTP 挑战插件 ACME HTTP Challenge Plugin

始终存在一个隐式配置的独立插件 , 通过内置在 80 端口的 Web 服务器验证 http-01 挑战。

NOTE

仅在 pveproxy 已经停止或未绑定到 80 端口时才可用;默认 pveproxy 监听 8006。

使用 Let's Encrypt ACME 的前置条件:

  • 必须接受 Let's Encrypt 服务条款以注册账户。
  • 节点的 80 端口 必须可从互联网访问。
  • 80 端口 不得 有其他监听者。
  • 请求的(子)域名必须解析到节点公网 IP。

3.12.6.ACME DNS API 挑战插件 ACME DNS API Challenge Plugin

若外部无法通过 http-01 验证 , 可改用 dns-01。该方法需要一台允许通过 API 供应 TXT 记录的 DNS 服务器。

配置用于验证的 ACME DNS API Configuring ACME DNS APIs for validation

Proxmox VE 复用 acme.sh 项目开发的 DNS 插件 , 具体 API 配置参见其文档。最简单是通过 Web 界面(数据中心 → ACME)。

选择 DNS 挑战类型 , 再选您的 API 提供商 , 填入凭据。验证延迟指设置 DNS 记录后到向 ACME 提供方发起验证之间的秒数 , 因为提供方通常需要时间在自身基础设施中传播记录。

DNS 提供商与 API 端点繁多 , Proxmox VE 会为部分提供商自动生成凭据表单。其他情况则会显示一个较大文本域 , 直接把所有 KEY=VALUE 凭据粘贴进去即可。

通过 CNAME 别名做 DNS 验证 DNS Validation through CNAME Alias

若主 DNS 不支持通过 API 供应 , 可用别名模式把验证交由另一域名 / DNS 服务器处理。手动为 _acme-challenge.domain1.example 添加一个指向 _acme-challenge.domain2.example 的永久 CNAME , 并在节点配置文件中相应的 acmedomainX 键上设置 alias 属性为 domain2.example, 即可让 domain2.example 的 DNS 服务器验证 domain1.example 的所有挑战。

组合使用插件 Combination of Plugins

若节点可通过多个域名到达且各域名需求或 DNS 供应能力不同 , 可组合使用 http-01 与 dns-01 验证。也可为每个域名指定不同插件实例 , 从多个提供商混用 DNS API。

TIP

如遇问题 , 可把 staging 作为默认端点调试 , 确认无误后再切回生产账户。

3.12.7.ACME 证书自动续期 Automatic renewal of ACME certificates

若节点已成功配置为使用 ACME 证书(通过 pvenode 或 GUI), pve-daily-update.service 将自动续期。当前策略是 :证书已过期或将在 30 天内过期则尝试续期。

NOTE

修改 ACME 账户 / 域名配置后 , 若希望立即触发续期 , 可运行 pvenode acme cert renew

3.12.8.pvenode ACME 示例 ACME Examples with pvenode

示例 :使用 Let's Encrypt 证书的 pvenode 调用 Sample pvenode invocation for using Let's Encrypt certificates
root@proxmox:~# pvenode acme account register default mail@example.invalid
Directory endpoints:
0) Let's Encrypt V2 (https://acme-v02.api.letsencrypt.org/directory)
1) Let's Encrypt V2 Staging (https://acme-staging-v02.api.letsencrypt.org/directory)
2) Custom
Enter selection: 1

Terms of Service: https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
Do you agree to the above terms? [y|N]y
...
Task OK
root@proxmox:~# pvenode config set --acme domains=example.invalid
root@proxmox:~# pvenode acme cert order
Loading ACME account details
Placing ACME order
...
Status is 'valid'!

All domains validated!
...
Downloading certificate
Setting pveproxy certificate and key
Restarting pveproxy
Task OK
示例 :设置 OVH API 验证域名 Setting up the OVH API for validating a domain
NOTE

以下仅作演示 , 请按 OVH 官方文档获取与配置 API token。

先获取 Proxmox VE 访问 API 所需信息:

root@proxmox:~# cat /path/to/api-token
OVH_AK=XXXXXXXXXXXXXXXX
OVH_AS=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
root@proxmox:~# source /path/to/api-token
root@proxmox:~# curl -XPOST -H"X-Ovh-Application: $OVH_AK" -H "Content-type: application/json" \
https://eu.api.ovh.com/1.0/auth/credential  -d '{
  "accessRules": [
    {"method": "GET","path": "/auth/time"},
    {"method": "GET","path": "/domain"},
    {"method": "GET","path": "/domain/zone/*"},
    {"method": "GET","path": "/domain/zone/*/record"},
    {"method": "POST","path": "/domain/zone/*/record"},
    {"method": "POST","path": "/domain/zone/*/refresh"},
    {"method": "PUT","path": "/domain/zone/*/record/"},
    {"method": "DELETE","path": "/domain/zone/*/record/*"}
]
}'
{"consumerKey":"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ","state":"pendingValidation","validationUrl":"https://eu.api.ovh.com/auth/?credentialToken=AAAA..."}

(打开 validationUrl , 按提示把 Application Key 与 账号 / Consumer Key 关联)

root@proxmox:~# echo "OVH_CK=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" >> /path/to/api-token

接着设置 ACME 插件:

root@proxmox:~# pvenode acme plugin add dns example_plugin --api ovh --data /path/to/api_token
root@proxmox:~# pvenode acme plugin config example_plugin
┌────────┬──────────────────────────────────────────┐
│ key    │ value                                    │
╞════════╪══════════════════════════════════════════╡
│ api    │ ovh                                      │
├────────┼──────────────────────────────────────────┤
│ data   │ OVH_AK=XXXXXXXXXXXXXXXX                  │
│        │ OVH_AS=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY  │
│        │ OVH_CK=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ  │
├────────┼──────────────────────────────────────────┤
│ digest │ 867fcf556363ca1bea866863093fcab83edf47a1 │
├────────┼──────────────────────────────────────────┤
│ plugin │ example_plugin                           │
├────────┼──────────────────────────────────────────┤
│ type   │ dns                                      │
└────────┴──────────────────────────────────────────┘

最后配置域名并下证书订单:

root@proxmox:~# pvenode config set -acmedomain0 example.proxmox.com,plugin=example_plugin
root@proxmox:~# pvenode acme cert order
Loading ACME account details
Placing ACME order
Order URL: https://acme-staging-v02.api.letsencrypt.org/acme/order/11111111/22222222

Getting authorization details from 'https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/33333333'
The validation for example.proxmox.com is pending!
[...] Using OVH endpoint: ovh-eu
[...] Checking authentication
[...] Consumer key is ok.
[...] Adding record
[...] Added, sleep 10 seconds.
Add TXT record: _acme-challenge.example.proxmox.com
Triggering validation
Sleeping for 5 seconds
Status is 'valid'!
[...] Remove TXT record: _acme-challenge.example.proxmox.com

All domains validated!

Creating CSR
Checking order status
Order is ready, finalizing order
valid!

Downloading certificate
Setting pveproxy certificate and key
Restarting pveproxy
Task OK
示例 :从 staging 切换到生产 ACME 目录 Switching from the staging to the regular ACME directory

不支持直接更改账户使用的 ACME 目录 , 但 Proxmox VE 支持多账户 , 可新建一个指向生产(可信)目录的账户。也可停用 staging 账户并重建。

示例 :用 pvenode 把默认 ACME 账户从 staging 切到生产:

root@proxmox:~# pvenode acme account deactivate default
Renaming account file from '/etc/pve/priv/acme/default' to '/etc/pve/priv/acme/_deactivated_default_4'
Task OK

root@proxmox:~# pvenode acme account register default example@proxmox.com
Directory endpoints:
0) Let's Encrypt V2 (https://acme-v02.api.letsencrypt.org/directory)
1) Let's Encrypt V2 Staging (https://acme-staging-v02.api.letsencrypt.org/directory)
2) Custom
Enter selection: 0

Terms of Service: https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
Do you agree to the above terms? [y|N]y
...
Task OK

3.13.主机引导加载程序 Host Bootloader

Proxmox VE 目前根据安装器所选磁盘方案使用两种引导加载程序之一。

对使用 ZFS 作为根文件系统的 EFI 系统 , 除非启用了 Secure Boot , 否则使用 systemd-boot;其他部署使用标准 GRUB(这也通常适用于在 Debian 之上的安装)。

3.13.1.安装器使用的分区方案 Partitioning Scheme Used by the Installer

Proxmox VE 安装器在所有参与安装的盘上创建 3 个分区:

  • 一个 1 MB 的 BIOS 引导分区(gdisk 类型 EF02)
  • 一个 512 MB 的 EFI 系统分区(ESP , gdisk 类型 EF00)
  • 第三个分区 , 占用指定 hdsize 或剩余空间 , 用于所选存储类型

使用 ZFS 作根的系统从 512 MB EFI 系统分区上的内核与 initrd 镜像引导。对传统 BIOS 系统与启用 Secure Boot 的 EFI 系统 , 使用 GRUB;对未启用 Secure Boot 的 EFI 系统使用 systemd-boot;两者都安装并配置为指向 ESP。

对所有使用 GRUB 引导的系统 , BIOS 模式下的 GRUB(--target i386-pc)会被安装到所有所选盘的 BIOS 引导分区上。

3.13.2.用 proxmox-boot-tool 同步 ESP 内容 Synchronizing the content of the ESP with proxmox-boot-tool

proxmox-boot-tool 是一个工具 , 用于让 EFI 系统分区的内容保持正确配置并同步。它把特定内核版本复制到所有 ESP , 并配置引导加载程序以从这些 vfat 格式化的 ESP 启动。在 ZFS-on-root 场景中 , 这意味着 rpool 上可启用所有可选特性 , 而不必局限于 GRUB 中 ZFS 实现的子集或单独创建一个小 boot-pool。

在有冗余的部署里 , 安装器会在所有盘上创建 ESP。这能确保即使第一启动盘故障 , 或 BIOS 只能从特定盘引导 , 系统仍可启动。

ESP 在常规运行时不会保持挂载 , 这能避免系统崩溃时 vfat 格式的 ESP 发生文件系统损坏 , 也无需在主启动盘故障时手动修改 /etc/fstab

proxmox-boot-tool 负责以下任务:

  • 格式化并初始化新分区
  • 复制并配置新内核与 initrd 镜像到所有已列出的 ESP
  • 内核升级及其他维护任务时同步配置
  • 管理需同步的内核版本列表
  • 配置引导加载程序从特定内核版本引导(固定 / pin)

查看当前已配置的 ESP 及其状态:

# proxmox-boot-tool status
设置新分区作为同步 ESP Setting up a new partition for use as synced ESP

把分区格式化并初始化为同步 ESP(例如在 rpool 中替换故障 vdev 后 , 或把早于该同步机制的旧系统做转换)。

WARN

格式化将抹掉该分区现有数据 , 务必确认目标分区正确。

把空分区 /dev/sda2 格式化为 ESP:

# proxmox-boot-tool format /dev/sda2

把已有、未挂载的 ESP(位于 /dev/sda2)纳入内核同步机制:

# proxmox-boot-tool init /dev/sda2

或强制用 GRUB 而非 systemd-boot 初始化(例如为 Secure Boot 支持):

# proxmox-boot-tool init /dev/sda2 grub

之后 /etc/kernel/proxmox-boot-uuids 将新增一行对应该分区的 UUID。 init 命令也会自动触发所有 ESP 刷新。

更新所有 ESP 上的配置 Updating the configuration on all ESPs

复制并配置所有可引导内核 , 并让 /etc/kernel/proxmox-boot-uuids 中列出的所有 ESP 保持同步:

# proxmox-boot-tool refresh

(这等同于根为 ext4 或 xfs 的系统上运行 update-grub。)修改内核命令行或希望同步所有内核与 initrd 时需要执行。

NOTE

使用 proxmox-boot-tool 的系统会在 update-grub 时自动调用 proxmox-boot-tool refresh

proxmox-boot-tool 考虑的内核版本 Kernel Versions considered by proxmox-boot-tool

默认配置的内核版本:

  • 当前运行的内核
  • 软件包更新时新安装的版本
  • 已安装的最近两个内核
  • 若适用 , 次新内核系列(如 5.0、 5.3)的最新版
  • 任何手动选择的内核
手动保留某内核可引导 Manually keeping a kernel bootable

proxmox-boot-tool kernel add 把特定内核与 initrd 加入可引导列表。例如把 ABI 版本 5.0.15-1-pve 加入:

# proxmox-boot-tool kernel add 5.0.15-1-pve

列出当前被选作引导的所有内核版本:

# proxmox-boot-tool kernel list
Manually selected kernels:
5.0.15-1-pve

Automatically selected kernels:
5.0.12-1-pve
4.15.18-18-pve

从手动所选列表移除:

# proxmox-boot-tool kernel remove 5.0.15-1-pve
NOTE

对上述任何更改 , 最后需运行 proxmox-boot-tool refresh 才能真正更新 ESP 中的配置。

3.13.3.判断使用的引导加载程序 Determine which Bootloader is Used

判断使用的引导加载程序最简单、最可靠的方法是观察 Proxmox VE 节点的启动过程 , 要么看到 GRUB 的蓝色窗口 , 要么看到 systemd-boot 简洁的黑底白字。

在运行系统上判断未必 100% 准确 , 最稳妥是执行:

# efibootmgr -v

若返回「EFI 变量不支持」, 则使用的是 BIOS/Legacy 模式下的 GRUB。

若输出包含类似下行 , 则是 UEFI 模式 GRUB:

Boot0005* proxmox       [...] File(\EFI\proxmox\grubx64.efi)

若输出包含类似下行 , 则是 systemd-boot:

Boot0006* Linux Boot Manager    [...] File(\EFI\systemd\systemd-bootx64.efi)

运行 proxmox-boot-tool status 也能看出是否已配置 , 这是系统如何启动的良好线索。

3.13.4.GRUB GRUB

GRUB 多年来是 Linux 系统引导的事实标准 , 文档相当完善。

配置

GRUB 配置通过默认文件 /etc/default/grub/etc/default/grub.d 中的片段修改。修改后重新生成配置:

# update-grub

3.13.5.systemd-boot Systemd-boot

systemd-boot 是一个轻量 EFI 引导加载程序。它直接从它所安装的 EFI 服务分区(ESP)读取内核与 initrd 镜像。直接从 ESP 加载内核的主要优点是无需重新实现访问存储的驱动。 Proxmox VE 使用 proxmox-boot-tool 让 ESP 上的配置保持同步。

配置

systemd-boot 的主配置是某 EFI 系统分区(ESP)根目录下的 loader/loader.conf。详见 loader.conf(5) 手册页。每个引导项放在 loader/entries/ 下独立文件中。示例 entry.conf/ 指 ESP 根目录):

title    Proxmox
version  5.0.15-1-pve
options   root=ZFS=rpool/ROOT/pve-1 boot=zfs
linux    /EFI/proxmox/5.0.15-1-pve/vmlinuz-5.0.15-1-pve
initrd   /EFI/proxmox/5.0.15-1-pve/initrd.img-5.0.15-1-pve

3.13.6.编辑内核命令行 Editing the Kernel Commandline

可根据所用引导加载程序在以下位置修改内核命令行:

GRUB :把命令行放入 /etc/default/grubGRUB_CMDLINE_LINUX_DEFAULT。运行 update-grub 会把其内容追加到 /boot/grub/grub.cfg 的所有 linux 条目。

systemd-boot :把命令行作为一行放入 /etc/kernel/cmdline。运行 proxmox-boot-tool refresh 以应用更改 , 它会把该行设置到 loader/entries/proxmox-*.conf 所有配置文件的 options 上。

完整内核参数列表见 https://www.kernel.org/doc/html/v<YOUR-KERNEL-VERSION>/admin-guide/kernel-parameters.html。把 <YOUR-KERNEL-VERSION> 替换为 major.minor 版本 , 例如 6.5 内核:https://www.kernel.org/doc/html/v6.5/admin-guide/kernel-parameters.html

查内核版本:在 Web 界面(节点 → Summary)看 , 或运行:

# uname -r

取输出最前两段数字即可。

3.13.7.覆盖下一次引导的内核版本 Override the Kernel-Version for next Boot

若想启动某个非当前默认内核 , 可:

  • 使用启动初期显示的引导菜单
  • proxmox-boot-tool 把系统一次性或永久(直至解除)固定到某内核版本

这有助于绕开新内核与硬件的不兼容问题。

NOTE

设置或清除固定后 , 都需要运行 refresh 同步 ESP 内容与配置。

永久选择 5.15.30-1-pve 作为引导版本:

# proxmox-boot-tool kernel pin 5.15.30-1-pve
TIP

永久固定的内核会跳过自动选择规则 , 所以如果不再手动引用且被 APT 移除 , 系统可能无法启动 , 务必谨慎。

仅下次启动生效(例如测试某更新内核是否已修复问题):

# proxmox-boot-tool kernel pin 5.15.30-1-pve --next-boot

清除固定版本配置:

# proxmox-boot-tool kernel unpin

unpin 也有 --next-boot 选项 , 但用于清除以 --next-boot 设置的固定;由于该配置在启动时会自动清除 , 手动调用意义不大。

设置或清除后记得运行:

# proxmox-boot-tool refresh

3.13.8.Secure Boot Secure Boot

自 Proxmox VE 8.1 起 , 通过签名软件包并与 proxmox-boot-tool 集成 , 开箱支持 Secure Boot。

使 Secure Boot 工作所需的包 , 可通过 meta-package proxmox-secure-boot-support 一次安装:

  • shim-signed(由 Microsoft 签名的 shim 引导加载程序)
  • shim-helpers-amd64-signed(后备引导加载程序与 MOKManager , 由 Proxmox 签名)
  • grub-efi-amd64-signed(GRUB EFI 引导加载程序 , 由 Proxmox 签名)
  • proxmox-kernel-6.X.Y-Z-pve-signed(内核镜像 , 由 Proxmox 签名)

目前只支持 GRUB 开箱作为 Secure Boot 的引导加载程序 , 其他引导加载程序目前未纳入 Secure Boot 代码签名。

Proxmox VE 的新安装将自动包含上述所有包。 Secure Boot 工作原理与自定义详见 Proxmox 官方 Wiki。

把现有安装切到 Secure Boot Switching an Existing Installation to Secure Boot
WARN

现有 UEFI 安装可切到 Secure Boot, 无需从头重装 , 但过程复杂 , 请先备份 , 并仅在确认必要时操作。

先确保系统已更新到最新 , 然后安装 proxmox-secure-boot-support。 GRUB 会自动为通过默认 shim 引导创建所需 EFI 引导项。

systemd-boot

若使用 systemd-boot(见「判断使用的引导加载程序」), 则需额外步骤。仅当 Proxmox VE 安装为 ZFS-on-root 时才会是这种情况。

检查:

# findmnt /

若主机确实用 ZFS 作根 , FSTYPE 列应为 zfs

TARGET SOURCE           FSTYPE OPTIONS
/      rpool/ROOT/pve-1 zfs    rw,relatime,xattr,noacl,casesensitive

找出合适的潜在 ESP(EFI 系统分区):

# lsblk -o +FSTYPE

输出形如:

NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS FSTYPE
sda      8:0    0   32G  0 disk
├─sda1   8:1    0 1007K  0 part
├─sda2   8:2    0  512M  0 part             vfat
└─sda3   8:3    0 31.5G  0 part             zfs_member
sdb      8:16   0   32G  0 disk
├─sdb1   8:17   0 1007K  0 part
├─sdb2   8:18   0  512M  0 part             vfat
└─sdb3   8:19   0 31.5G  0 part             zfs_member

本例中 sda2sdb2 是目标(可通过大小 512M 与 FSTYPE=vfat 识别 , ZFS RAID-1 安装)。

proxmox-boot-tool 为每个 ESP 分别正确设置以通过 GRUB 启动:

# proxmox-boot-tool init /dev/sda2 grub

之后可用 efibootmgr -v 做合理性检查 , 应包含类似:

[..]
Boot0009* proxmox       HD(2,GPT,..,0x800,0x100000)/File(\EFI\proxmox\shimx64.efi)
[..]
NOTE

该切换完成后 , 如需卸载 systemd-boot, 请谨慎 , 并先验证 GRUB 路径可用。

接下来可重启 , 在 UEFI 固件设置中启用 Secure Boot。重启后 , UEFI 固件引导菜单中应出现一个可选的 proxmox 条目 , 通过预签名的 EFI shim 启动。

若 UEFI 引导菜单中找不到 proxmox 条目 , 在固件支持时可手动添加自定义引导项 , 指向 \EFI\proxmox\shimx64.efi

TIP

启用 Secure Boot 后 , 可能需要为自建或第三方内核模块签名 , 见下节。

使用 DKMS / 第三方模块与 Secure Boot Using DKMS/Third Party Modules With Secure Boot

启用 Secure Boot 的系统上 , 内核将拒绝加载未由可信密钥签名的模块。内核包附带的默认模块由内核镜像内嵌、仅被该具体内核镜像信任的一次性密钥签名。

要加载其他模块(例如 DKMS 构建或手工构建), 需要用 Secure Boot 栈信任的密钥签名。最简单方式是用 mokutil 把其注册为机主密钥(Machine Owner Key, MOK)。

dkms 工具会自动在 /var/lib/dkms/mok.key/var/lib/dkms/mok.pub 生成密钥对与证书 , 并用它签名它构建并安装的内核模块。

查看证书内容:

# openssl x509 -in /var/lib/dkms/mok.pub -noout -text

在系统上注册:

# mokutil --import /var/lib/dkms/mok.pub
input password:
input password again:

mokutil 会两次询问一个(临时)口令 , 该口令还需在下一步中再次输入!重启系统应自动进入 MOKManager EFI 程序 , 您可在其中验证密钥 / 证书 , 并用注册时选择的口令确认注册。之后内核应允许加载 DKMS 构建的模块(由已注册的 MOK 签名)。 MOK 也可用于签名自定义 EFI 二进制与内核镜像(如需要)。

对非 DKMS 管理的自建 / 第三方模块也可用相同流程 , 但密钥 / 证书的生成与签名需要手动完成。

3.14.内核同页合并(KSM) Kernel Samepage Merging (KSM)

内核同页合并(KSM)是 Linux 内核提供的可选内存去重特性 , 在 Proxmox VE 中默认启用。 KSM 扫描一段物理内存页中的相同内容 , 并识别映射到这些页的虚拟页。若发现相同页 , 对应虚拟页被重新映射到同一物理页 , 旧页释放。虚拟页被标为「写时复制」 , 任何写操作会写入新内存区 , 共享物理页保持不变。

3.14.1.KSM 的影响 Implications of KSM

在虚拟化环境中 KSM 能优化内存使用 , 因为多台运行相似系统或工作负载的 VM 可能共享大量相同内存页。

然而 , 虽然 KSM 减少内存使用 , 却带来侧信道攻击等安全风险。研究表明 , 可以通过同一主机上另一 VM 利用 KSM 的特征推断目标 VM 运行信息。

因此 , 若您使用 Proxmox VE 提供托管服务 , 应考虑禁用 KSM 以增强安全 , 并核查所在地的法规 , 因为禁用 KSM 可能是法律要求。

3.14.2.禁用 KSM Disabling KSM

KSM 可在节点层级或单 VM 层级禁用。

在节点上禁用 KSM

查看 KSM 是否活跃:

# systemctl status ksmtuned

若活跃 , 立刻禁用:

# systemctl disable --now ksmtuned

最后 , 取消当前已合并的所有页:

# echo 2 > /sys/kernel/mm/ksm/run

对特定 VM 禁用 KSM

allow-ksm VM 配置项控制该 VM 是否允许页合并。默认 true, 可这样禁用:

# qm set <vmid> --allow-ksm 0