Proxmox VE 集群管理器 pvecm 是用于创建一组物理服务器的工具。这类服务器组称为 集群。我们使用 Corosync Cluster Engine 实现可靠的组通信。 集群中的节点数量没有明确的硬性限制。实践中,实际可支持的节点数量可能受主机和网络性能限制。 目前(2021 年)已有使用高端企业硬件、超过 50 个节点的生产集群案例。

pvecm 可用于创建新集群、将节点加入集群、离开集群、获取状态信息,以及执行各种其他集群相关任务。 Proxmox Cluster File System(“pmxcfs”)用于将集群配置透明地分发到所有集群节点。

将节点组织为集群具有以下优势:

  • 集中式、基于 Web 的管理

  • 多主集群:每个节点都可以执行所有管理任务

  • 使用 pmxcfs 这个数据库驱动的文件系统存储配置文件,并通过 corosync 在所有节点上实时复制

  • 可在物理主机之间轻松迁移虚拟机和容器

  • 快速部署

  • 提供防火墙和 HA 等集群范围服务

要求

  • 所有节点之间必须能够通过 UDP 端口 5405-5412 互相连接,corosync 才能正常工作。

  • 日期和时间必须同步。

  • 节点之间需要 TCP 端口 22 上的 SSH 隧道。

  • 如果需要高可用,至少需要三个节点才能获得可靠仲裁。所有节点应使用相同版本。

  • 建议为集群流量使用专用 NIC,尤其是在使用共享存储时。

  • 添加节点时需要集群节点的 root 密码。

  • 虚拟机在线迁移仅在各节点 CPU 来自同一厂商时受支持。其他情况下可能可以工作,但绝不保证。

Note 不能将 Proxmox VE 3.x 及更早版本与 Proxmox VE 4.X 集群节点混用。
Note 虽然可以混用 Proxmox VE 4.4 和 Proxmox VE 5.0 节点,但这种做法不支持作为生产配置, 只应在整个集群从一个主版本升级到另一个主版本期间临时使用。
Note 无法将 Proxmox VE 6.x 与更早版本组成集群。Proxmox VE 6.x 与更早版本之间的集群协议 (corosync)发生了根本变化。Proxmox VE 5.4 的 corosync 3 软件包仅用于升级到 Proxmox VE 6.0 的过程。

准备节点

首先,在所有节点上安装 Proxmox VE。确保每个节点都使用最终的主机名和 IP 配置进行安装。 集群创建后无法更改主机名和 IP。

通常会在 /etc/hosts 中记录所有节点名称及其 IP(或通过其他方式让这些名称可解析), 但这并不是集群正常工作的必要条件。不过这样可能比较方便,因为可以使用更容易记住的节点名, 通过 SSH 从一个节点连接到另一个节点(另见 Link Address Types)。 请注意,我们始终建议在集群配置中通过 IP 地址引用节点。

创建集群

可以在控制台上创建集群(通过 ssh 登录),也可以使用 Proxmox VE Web 界面 (Datacenter → Cluster)通过 API 创建集群。

Note 请为集群使用唯一名称。该名称之后无法更改。集群名称遵循与节点名称相同的规则。

通过 Web GUI 创建

screenshot/gui-cluster-create.png

Datacenter → Cluster 下,点击 Create Cluster。输入集群名称,并从下拉列表中选择一个网络连接作为主集群网络(Link 0)。 默认情况下,它使用通过节点主机名解析得到的 IP。

从 Proxmox VE 6.2 开始,一个集群最多可以添加 8 个备用链路。要添加冗余链路,请点击 Add 按钮,并在相应字段中选择链路编号和 IP 地址。在 Proxmox VE 6.2 之前,要添加第二条链路作为备用链路, 可以勾选 Advanced 复选框,并选择额外网络接口(Link 1,另见 Corosync Redundancy)。

Note 请确保用于集群通信的网络没有用于网络存储或在线迁移等高流量用途。 集群网络本身产生的数据量很小,但对延迟非常敏感。请查看完整的 集群网络要求

通过命令行创建

通过 ssh 登录到第一个 Proxmox VE 节点,并运行以下命令:

 hp1# pvecm create CLUSTERNAME

要检查新集群状态,请使用:

 hp1# pvecm status

同一网络中的多个集群

可以在同一物理或逻辑网络中创建多个集群。在这种情况下,每个集群都必须拥有唯一名称, 以避免集群通信栈中可能出现的冲突。此外,这也能让集群清晰区分,避免人为混淆。

虽然 corosync 集群的带宽需求相对较低,但数据包延迟和每秒包数(PPS)才是限制因素。 同一网络中的不同集群可能会竞争这些资源,因此对于较大的集群,使用独立的物理网络基础设施仍然有意义。

向集群添加节点

Caution 加入集群时,/etc/pve 中的所有现有配置都会被覆盖。尤其是,加入的节点不能承载任何客户机, 否则客户机 ID 可能冲突,并且该节点会继承集群的存储配置。若要加入一个已有客户机的节点, 可作为变通方式先为每个客户机创建备份(使用 vzdump),加入集群后再用不同 ID 还原。 如果该节点的存储布局不同,则需要重新添加该节点的存储,并调整每个存储的节点限制, 以反映该存储实际在哪些节点上可用。

通过 GUI 将节点加入集群

screenshot/gui-cluster-join-information.png

登录到已有集群节点的 Web 界面。在 Datacenter → Cluster 下,点击顶部的 Join Information 按钮。然后点击 Copy Information 按钮。也可以手动复制 Information 字段中的字符串。

screenshot/gui-cluster-join.png

接下来,登录要添加节点的 Web 界面。在 Datacenter → Cluster 下,点击 Join Cluster。将之前复制的 Join Information 文本填入 Information 字段。 加入集群所需的大多数设置都会自动填写。出于安全原因,集群密码必须手动输入。

Note 要手动输入所有必需数据,可以禁用 Assisted Join 复选框。

点击 Join 按钮后,集群加入流程会立即开始。节点加入集群后,其当前节点证书会被替换为由集群证书颁发机构(CA)签名的证书。 这意味着当前会话会在几秒后停止工作。之后可能需要强制重新加载 Web 界面,并使用集群凭据重新登录。

现在,该节点应该可以在 Datacenter → Cluster 下看到。

通过命令行将节点加入集群

通过 ssh 登录要加入现有集群的节点。

 # pvecm add IP-ADDRESS-CLUSTER

对于 IP-ADDRESS-CLUSTER,请使用现有集群节点的 IP 或主机名。建议使用 IP 地址 (见 Link Address Types)。

要检查集群状态,请使用:

 # pvecm status
添加 4 个节点后的集群状态
 # pvecm status
Cluster information
~~~~~~~~~~~~~~~~~~~
Name:             prod-central
Config Version:   3
Transport:        knet
Secure auth:      on

Quorum information
~~~~~~~~~~~~~~~~~~
Date:             Tue Sep 14 11:06:47 2021
Quorum provider:  corosync_votequorum
Nodes:            4
Node ID:          0x00000001
Ring ID:          1.1a8
Quorate:          Yes

Votequorum information
~~~~~~~~~~~~~~~~~~~~~~
Expected votes:   4
Highest expected: 4
Total votes:      4
Quorum:           3
Flags:            Quorate

Membership information
~~~~~~~~~~~~~~~~~~~~~~
    Nodeid      Votes Name
0x00000001          1 192.168.15.91
0x00000002          1 192.168.15.92 (local)
0x00000003          1 192.168.15.93
0x00000004          1 192.168.15.94

如果只想获取所有节点列表,请使用:

 # pvecm nodes
列出集群中的节点
 # pvecm nodes

Membership information
~~~~~~~~~~~~~~~~~~~~~~
    Nodeid      Votes Name
         1          1 hp1
         2          1 hp2 (local)
         3          1 hp3
         4          1 hp4

使用独立集群网络添加节点

向使用独立集群网络的集群添加节点时,需要使用 link0 参数设置该节点在该网络上的地址:

# pvecm add IP-ADDRESS-CLUSTER --link0 LOCAL-IP-ADDRESS-LINK0

如果要使用 Kronosnet 传输层内置的 冗余,还需要使用 link1 参数。

使用 GUI 时,可以在 Cluster Join 对话框中相应的 Link X 字段选择正确接口。

移除集群节点

Caution 继续之前请仔细阅读该流程,因为它可能并不是你想要或需要的操作。

将该节点上的所有虚拟机移走。确保已复制任何需要保留的本地数据或备份。 此外,确保移除所有指向待移除节点的计划复制任务。

Caution 如果在移除节点之前没有移除指向该节点的复制任务,会导致复制任务变得无法移除。 尤其要注意,如果迁移已复制的虚拟机,复制会自动切换方向;因此,从待删除节点迁移已复制虚拟机后, 复制任务会自动设置为指向该节点。

如果待移除节点配置了 Ceph

  1. 确保仍有足够的 Proxmox VE 节点运行 OSD(upin)。

    Note 默认情况下,Ceph 池的 size/min_size3/2,并在对象均衡器 CRUSH 中以完整节点作为 failure domain。 因此,如果在线且运行 OSD 的节点少于 size3),数据冗余会降级。 如果在线节点少于 min_size,池 I/O 会被阻塞,受影响的客户机可能崩溃。
  2. 确保仍有足够的 monitorsmanagers,以及在使用 CephFS 时的 metadata servers 可用。

  3. 为维持数据冗余,每次销毁 OSD(尤其是节点上的最后一个 OSD)都会触发数据再均衡。 因此,请确保剩余节点上的 OSD 有足够可用空间。

  4. 要从待删除节点移除 Ceph,请先逐个 销毁 其 OSD。

  5. 一旦 CEPH status 再次变为 HEALTH_OK,继续执行:

    1. 通过 Web 界面的 Ceph → CephFS 或运行以下命令,销毁其 metadata server

      # pveceph mds destroy <local hostname>
    2. 销毁其 monitor

    3. 销毁其 manager

  6. 最后,运行以下命令从 CRUSH 层次结构中移除现在已经为空的 bucket(待移除的 Proxmox VE 节点):

    # ceph osd crush remove <hostname>

在以下示例中,我们将从集群中移除节点 hp4。

登录到*另一个*集群节点(不是 hp4),并执行 pvecm nodes 命令以确定要移除的节点 ID:

 hp1# pvecm nodes

Membership information
~~~~~~~~~~~~~~~~~~~~~~
    Nodeid      Votes Name
         1          1 hp1 (local)
         2          1 hp2
         3          1 hp3
         4          1 hp4

此时,必须关闭 hp4,并确保它不会以当前配置再次在该网络中启动。

Important 如上所述,在移除*之前*关闭节点非常关键,并且要确保它不会以当前配置在现有集群网络中再次启动。 如果按原样启动该节点,集群可能损坏,并且可能难以恢复到可用状态。

关闭节点 hp4 后,即可安全地将其从集群中移除。

 hp1# pvecm delnode hp4
 Killing node 4
Note 此时可能会收到 Could not kill node (error = CS_ERR_NOT_EXIST) 错误消息。 这并不表示节点删除实际失败,而只是 corosync 尝试 kill 一个离线节点时失败。因此可以安全忽略。

再次使用 pvecm nodespvecm status 检查节点列表。它应类似如下:

hp1# pvecm status

...

Votequorum information
~~~~~~~~~~~~~~~~~~~~~~
Expected votes:   3
Highest expected: 3
Total votes:      3
Quorum:           2
Flags:            Quorate

Membership information
~~~~~~~~~~~~~~~~~~~~~~
    Nodeid      Votes Name
0x00000001          1 192.168.15.90 (local)
0x00000002          1 192.168.15.91
0x00000003          1 192.168.15.92

如果出于任何原因想让该服务器再次加入同一集群,必须:

  • 在其上全新安装 Proxmox VE,

  • 然后按上一节说明将其加入集群。

已移除节点的配置文件仍会保留在 /etc/pve/nodes/hp4 中。请恢复仍需要的任何配置, 之后移除该目录。

Note 移除节点后,其 SSH 指纹仍会保留在其他节点的 known_hosts 中。 如果使用相同 IP 或主机名重新加入节点后收到 SSH 错误,请在重新添加的节点上运行一次 pvecm updatecerts,以在集群范围内更新其指纹。

不重装而分离节点

Caution 这*不是*推荐方法,请谨慎操作。如果不确定,请使用前一种方法。

也可以在不从头重装的情况下将节点从集群中分离出来。但从集群移除该节点后,它仍然可以访问任何共享存储。 在开始从集群移除节点之前,必须先解决这一点。一个 Proxmox VE 集群不能与另一个集群共享完全相同的存储, 因为存储锁无法跨集群边界工作。此外,这还可能导致 VMID 冲突。

建议创建一个新存储,仅允许要分离的节点访问。举例来说,这可以是 NFS 上的新导出, 也可以是新的 Ceph 池。关键是不能让多个集群访问完全相同的存储。设置好该存储后, 将该节点上的所有数据和虚拟机移动到其中。之后即可准备将该节点从集群中分离。

Warning 请确保所有共享资源都已清晰分离!否则会遇到冲突和问题。

首先,在该节点上停止 corosync 和 pve-cluster 服务:

systemctl stop pve-cluster
systemctl stop corosync

以本地模式重新启动集群文件系统:

pmxcfs -l

删除 corosync 配置文件:

rm /etc/pve/corosync.conf
rm -r /etc/corosync/*

现在可以再次将文件系统作为普通服务启动:

killall pmxcfs
systemctl start pve-cluster

该节点现在已经从集群中分离。可以在集群中任一剩余节点上使用以下命令将其删除:

pvecm delnode oldnode

如果命令因剩余节点丢失仲裁而失败,可以将预期票数设置为 1 作为临时处理:

pvecm expected 1

然后再次执行 pvecm delnode 命令。

现在切回已分离的节点,删除其上所有剩余的集群文件。这可以确保该节点之后能顺利加入其他集群。

rm /var/lib/corosync/*

由于其他节点的配置文件仍在集群文件系统中,你可能也希望清理它们。在完全确认节点名称正确后, 可以直接从 /etc/pve/nodes/NODENAME 递归移除整个目录。

Caution 该节点的 SSH 密钥会保留在 authorized_key 文件中。 这意味着节点之间仍然可以使用公钥认证互相连接。应通过从 /etc/pve/priv/authorized_keys 文件中移除相应密钥来修正这一点。

仲裁

Proxmox VE 使用基于仲裁的技术,在所有集群节点之间提供一致状态。

仲裁是分布式事务为了获准在分布式系统中执行某项操作而必须获得的最小票数。

Quorum (distributed computing)
— 来自 Wikipedia

在发生网络分区时,状态变更要求多数节点在线。如果集群失去仲裁,就会切换到只读模式。

Note Proxmox VE 默认给每个节点分配一票。

集群网络

集群网络是集群的核心。所有通过它发送的消息都必须按各自顺序可靠地传递到所有节点。 在 Proxmox VE 中,这部分由 corosync 完成;corosync 是一个高性能、低开销、高可用开发工具包的实现。 它服务于我们的去中心化配置文件系统(pmxcfs)。

网络要求

Proxmox VE 集群栈要求所有节点之间具备可靠网络,并且延迟低于 5 毫秒(LAN 性能),才能稳定运行。 在节点数量较少的配置中,延迟更高的网络_可能_可以工作,但这并不保证; 当节点超过三个且延迟高于约 10 ms 时,成功可能性会明显降低。

该网络不应被其他成员大量使用,因为 corosync 虽然不需要太多带宽,但对延迟抖动很敏感; 理想情况下,corosync 应运行在物理隔离的专用网络上。尤其不要让 corosync 和存储共享同一网络 (除非在 冗余配置中作为潜在的低优先级备用链路)。

设置集群前,最佳实践是检查网络是否适合该用途。为确保各节点能在集群网络上互相连接, 可以使用 ping 工具测试它们之间的连通性。

如果启用了 Proxmox VE 防火墙,将自动生成 corosync 的 ACCEPT 规则,无需手动操作。

Note Corosync 在 3.0 版本之前使用组播(该版本在 Proxmox VE 6.0 中引入)。 现代版本依赖 Kronosnet 进行集群通信,目前它只支持常规 UDP 单播。
Caution 仍然可以在 corosync.conf 中将 transport 设置为 udpudpu 来启用组播或旧式单播,但请记住,这会禁用所有加密和冗余支持。 因此不推荐这样做。

独立集群网络

在不带任何参数创建集群时,corosync 集群网络通常会与 Web 界面和虚拟机网络共享。 根据配置,甚至存储流量也可能通过同一网络发送。建议更改这种配置,因为 corosync 是对时间敏感的实时应用。

设置新网络

首先,必须设置新的网络接口。它应位于物理隔离的网络上。请确保该网络满足 集群网络要求

在创建集群时分离

可以通过用于创建新集群的 pvecm create 命令的 linkX 参数实现。

如果已经设置了一个静态地址为 10.10.10.1/25 的额外 NIC,并希望通过该接口收发所有集群通信, 则可以执行:

pvecm create test --link0 10.10.10.1

要检查一切是否正常工作,请执行:

systemctl status corosync

之后,按上文说明继续 使用独立集群网络添加节点

在创建集群后分离

如果已经创建了集群,并希望在不重建整个集群的情况下将通信切换到另一个网络,可以执行该操作。 由于节点必须重启 corosync,并在新网络上逐个恢复运行,此变更可能导致集群短暂丢失仲裁。

请先查看如何 编辑 corosync.conf 文件。 然后打开该文件,应能看到类似如下内容:

logging {
  debug: off
  to_syslog: yes
}

nodelist {

  node {
    name: due
    nodeid: 2
    quorum_votes: 1
    ring0_addr: due
  }

  node {
    name: tre
    nodeid: 3
    quorum_votes: 1
    ring0_addr: tre
  }

  node {
    name: uno
    nodeid: 1
    quorum_votes: 1
    ring0_addr: uno
  }

}

quorum {
  provider: corosync_votequorum
}

totem {
  cluster_name: testcluster
  config_version: 3
  ip_version: ipv4-6
  secauth: on
  version: 2
  interface {
    linknumber: 0
  }

}
Note ringX_addr 实际上指定的是 corosync 链路地址。名称 "ring" 是旧版 corosync 遗留下来的叫法,为向后兼容而保留。

首先,如果节点条目中尚未包含 name 属性,请添加它们。这些属性*必须*与节点名称匹配。

然后,将所有节点 ring0_addr 属性中的地址替换为新地址。这里可以使用普通 IP 地址或主机名。 如果使用主机名,请确保所有节点都能解析这些主机名(另见 Link Address Types)。

在本示例中,我们希望将集群通信切换到 10.10.10.0/25 网络,因此相应修改每个节点的 ring0_addr

Note 完全相同的流程也可用于更改其他 ringX_addr 值。不过建议一次只更改一个链路地址, 这样在出现问题时更容易恢复。

增加 config_version 属性后,新的配置文件应如下所示:

logging {
  debug: off
  to_syslog: yes
}

nodelist {

  node {
    name: due
    nodeid: 2
    quorum_votes: 1
    ring0_addr: 10.10.10.2
  }

  node {
    name: tre
    nodeid: 3
    quorum_votes: 1
    ring0_addr: 10.10.10.3
  }

  node {
    name: uno
    nodeid: 1
    quorum_votes: 1
    ring0_addr: 10.10.10.1
  }

}

quorum {
  provider: corosync_votequorum
}

totem {
  cluster_name: testcluster
  config_version: 4
  ip_version: ipv4-6
  secauth: on
  version: 2
  interface {
    linknumber: 0
  }

}

然后,最后检查所有变更信息是否正确,保存文件,并再次按照 编辑 corosync.conf 文件一节使其生效。

这些变更会实时应用,因此并不严格要求重启 corosync。如果还更改了其他设置, 或注意到 corosync 报错,可以选择触发一次重启。

在单个节点上执行:

systemctl restart corosync

现在检查一切是否正常:

systemctl status corosync

如果 corosync 重新开始工作,也在所有其他节点上重启它。 随后这些节点会在新网络上逐个加入集群成员关系。

Corosync 地址

corosync 链路地址(为向后兼容,在 corosync.conf 中表示为 ringX_addr)可以通过两种方式指定:

  • IPv4/v6 地址可以直接使用。建议使用它们,因为它们是静态的,通常不会被随意更改。

  • 主机名会使用 getaddrinfo 解析,这意味着默认情况下,如果 IPv6 地址可用,会优先使用 IPv6 地址 (另见 man gai.conf)。请记住这一点,尤其是在将现有集群升级到 IPv6 时。

Caution 应谨慎使用主机名,因为它们解析到的地址可以在不触碰 corosync 或其所在节点的情况下被更改, 这可能导致地址变更时没有考虑对 corosync 的影响。

如果偏好使用主机名,建议为 corosync 使用单独的静态主机名。同时确保集群中的每个节点都能正确解析所有主机名。

自 Proxmox VE 5.1 起,虽然仍支持主机名,但主机名会在录入时解析,只有解析后的 IP 会保存到配置中。

在更早版本中加入集群的节点,可能仍在 corosync.conf 中使用未解析的主机名。 按上文所述,将其替换为 IP 或单独主机名可能是个好做法。

Corosync 冗余

Corosync 默认通过其集成的 Kronosnet 层支持冗余网络(旧式 udp/udpu 传输不支持)。 可以通过指定多个链路地址启用该功能:使用 pvecm--linkX 参数、 在 GUI 中指定 Link 1(创建集群或添加新节点时),或在 corosync.conf 中指定多个 ringX_addr

Note 为提供有效故障切换,每条链路都应位于自己的物理网络连接上。

链路会根据优先级设置使用。可以通过在 corosync.conf 中相应 interface 段设置 knet_link_priority 来配置优先级,或者更推荐在使用 pvecm 创建集群时使用 priority 参数:

 # pvecm create CLUSTERNAME --link0 10.10.10.1,priority=15 --link1 10.20.20.1,priority=20

这会使 link1 优先使用,因为它拥有更高优先级。

如果没有手动配置优先级(或两条链路优先级相同),链路会按编号顺序使用,编号较低者优先级更高。

即使所有链路都正常工作,也只有最高优先级链路会承载 corosync 流量。 链路优先级不能混用,这意味着优先级不同的链路无法彼此通信。

由于低优先级链路只有在所有更高优先级链路都失败时才会承载流量,因此将用于其他任务 (虚拟机、存储等)的网络指定为低优先级链路是一种实用策略。在最坏情况下, 高延迟或更拥塞的连接也可能好过完全没有连接。

向现有集群添加冗余链路

要向运行中的配置添加新链路,请先查看如何 编辑 corosync.conf 文件

然后,在 nodelist 段中为每个节点添加新的 ringX_addr。确保为所有节点添加时使用相同的 X, 并且该地址对每个节点都是唯一的。

最后,如下所示,在 totem 段中添加新的 interface,并将 X 替换为上面选择的链路编号。

假设添加的是编号为 1 的链路,新的配置文件可能如下所示:

logging {
  debug: off
  to_syslog: yes
}

nodelist {

  node {
    name: due
    nodeid: 2
    quorum_votes: 1
    ring0_addr: 10.10.10.2
    ring1_addr: 10.20.20.2
  }

  node {
    name: tre
    nodeid: 3
    quorum_votes: 1
    ring0_addr: 10.10.10.3
    ring1_addr: 10.20.20.3
  }

  node {
    name: uno
    nodeid: 1
    quorum_votes: 1
    ring0_addr: 10.10.10.1
    ring1_addr: 10.20.20.1
  }

}

quorum {
  provider: corosync_votequorum
}

totem {
  cluster_name: testcluster
  config_version: 4
  ip_version: ipv4-6
  secauth: on
  version: 2
  interface {
    linknumber: 0
  }
  interface {
    linknumber: 1
  }
}

按照 编辑 corosync.conf 文件的最后步骤操作后,新链路会立即启用。 应不需要重启。可以使用以下命令检查 corosync 是否加载了新链路:

journalctl -b -u corosync

可以通过临时断开一个节点上的旧链路,并确认断开期间其状态仍保持在线,来测试新链路:

pvecm status

如果看到健康的集群状态,说明正在使用新链路。

SSH 在 Proxmox VE 集群中的作用

Proxmox VE 将 SSH 隧道用于多种功能。

  • 代理控制台/shell 会话(节点和客户机)

    连接到节点 A 时使用节点 B 的 shell,会连接到节点 A 上的终端代理, 该代理再通过非交互式 SSH 隧道连接到节点 B 上的登录 shell。

  • secure 模式下迁移虚拟机和 CT 内存及本地存储。

    迁移期间,会在源节点和目标节点之间建立一个或多个 SSH 隧道,用于交换迁移信息并传输内存和磁盘内容。

  • 存储复制

SSH 设置

在 Proxmox VE 系统上,会对 SSH 配置/设置进行以下更改:

  • root 用户的 SSH 客户端配置会设置为优先使用 AES 而不是 ChaCha20

  • root 用户的 authorized_keys 文件会链接到 /etc/pve/priv/authorized_keys, 以合并集群内的所有授权密钥

  • sshd 会配置为允许使用密码以 root 身份登录

Note 较旧系统还可能将 /etc/ssh/ssh_known_hosts 设置为指向 /etc/pve/priv/known_hosts 的符号链接,其中包含所有节点主机密钥的合并版本。 该机制已在 pve-cluster <<INSERT VERSION>> 中由显式 host key pinning 取代; 如果该符号链接仍存在,可以运行 pvecm updatecerts --unmerge-known-hosts 解除配置。

自动执行 .bashrc 及类似文件带来的陷阱

如果存在自定义 .bashrc,或配置的 shell 在登录时会执行的类似文件,ssh 会在会话成功建立后自动运行它。 这可能导致一些意外行为,因为这些命令可能会在上述任一操作中以 root 权限执行, 从而可能产生有问题的副作用。

为避免这类复杂情况,建议在 /root/.bashrc 中添加检查,确保会话是交互式会话后, 才运行 .bashrc 命令。

可以将以下片段添加到 .bashrc 文件开头:

# Early exit if not running interactively to avoid side-effects!
case $- in
    *i*) ;;
      *) return;;
esac

Corosync 外部投票支持

本节介绍在 Proxmox VE 集群中部署外部投票者的方法。配置后,集群可以承受更多节点故障, 同时不破坏集群通信的安全属性。

该功能涉及两个服务:

  • 运行在每个 Proxmox VE 节点上的 QDevice 守护进程

  • 运行在独立服务器上的外部投票守护进程

这样即使在较小配置中(例如 2+1 节点),也可以实现更高可用性。

QDevice 技术概览

Corosync Quorum Device(QDevice)是运行在每个集群节点上的守护进程。 它会根据外部运行的第三方仲裁者的决策,为集群的仲裁子系统提供配置数量的票数。 其主要用途是让集群能够承受超过标准仲裁规则允许数量的节点故障。这样做是安全的, 因为外部设备可以看到所有节点,因此只会选择一组节点给予投票。 只有当该节点集合在获得第三方投票后能够(重新)达到仲裁时,才会执行这一操作。

目前,仅支持 QDevice Net 作为第三方仲裁者。它是一个守护进程:如果能够通过网络访问某个集群分区的成员, 就向该分区提供一票。在任意时刻,它只会给集群的一个分区投票。 它设计为支持多个集群,并且几乎不需要配置和状态。新集群会被动态处理,运行 QDevice 的主机上不需要配置文件。

外部主机的唯一要求是能够通过网络访问集群,并且有可用的 corosync-qnetd 软件包。 我们为基于 Debian 的主机提供软件包,其他 Linux 发行版也应可通过各自的软件包管理器获得相应软件包。

Note 与 corosync 本身不同,QDevice 通过 TCP/IP 连接到集群。 该守护进程也可以运行在集群 LAN 之外,并不受 corosync 低延迟要求限制。

支持的配置

我们支持在偶数节点集群中使用 QDevice;如果 2 节点集群需要提供更高可用性,也建议使用它。 对于奇数节点集群,目前不建议使用 QDevice。原因在于 QDevice 为不同集群类型提供的票数不同。 偶数节点集群会获得额外的一票,这只会提高可用性,因为如果 QDevice 本身失败, 你所处的位置与完全没有 QDevice 时相同。

另一方面,对于奇数节点规模的集群,QDevice 会提供 (N-1) 票,其中 N 对应集群节点数。 这种替代行为是有意义的;如果它只提供一张额外票,集群可能进入脑裂状态。 该算法允许除一个节点外的所有节点(自然也包括 QDevice 本身)发生故障。不过,这有两个缺点:

  • 如果 QNet 守护进程本身失败,则不能再有任何其他节点失败,否则集群会立即失去仲裁。 例如,在 15 节点集群中,集群失去仲裁前可以有 7 个节点失败。但如果这里配置了 QDevice, 且 QDevice 本身失败,则 15 个节点中任何单个节点都不能失败。 在这种情况下,QDevice 几乎相当于单点故障。

  • 除一个节点外所有节点加 QDevice 都可以失败,这一点乍看很有吸引力, 但它可能导致 HA 服务大规模恢复,从而压垮唯一剩余的节点。此外,如果只剩下 ((N-1)/2) 个或更少节点在线,Ceph 服务器会停止提供服务。

如果理解这些缺点和影响,可以自行决定是否在奇数节点集群配置中使用该技术。

QDevice-Net 设置

建议将任何为 corosync-qdevice 提供票数的守护进程以非特权用户身份运行。 Proxmox VE 和 Debian 提供的软件包已经配置为这样运行。 守护进程与集群之间的流量必须加密,以确保 QDevice 安全地集成到 Proxmox VE 中。

首先,在外部服务器上安装 corosync-qnetd 软件包:

external# apt install corosync-qnetd

并在所有集群节点上安装 corosync-qdevice 软件包:

pve# apt install corosync-qdevice

完成后,确保集群中的所有节点都在线。

现在可以在其中一个 Proxmox VE 节点上运行以下命令设置 QDevice:

pve# pvecm qdevice setup <QDEVICE-IP>

集群中的 SSH 密钥会自动复制到 QDevice。

Note 请确保在外部服务器上为 root 用户设置基于密钥的访问,或在设置阶段临时允许 root 使用密码登录。 如果此阶段收到类似 Host key verification failed. 的错误,运行 pvecm updatecerts 可能可以修复该问题。

所有步骤成功完成后,会看到 "Done"。可以使用以下命令验证 QDevice 是否已设置:

pve# pvecm status

...

Votequorum information
~~~~~~~~~~~~~~~~~~~~~
Expected votes:   3
Highest expected: 3
Total votes:      3
Quorum:           2
Flags:            Quorate Qdevice

Membership information
~~~~~~~~~~~~~~~~~~~~~~
    Nodeid      Votes    Qdevice Name
    0x00000001      1    A,V,NMW 192.168.22.180 (local)
    0x00000002      1    A,V,NMW 192.168.22.181
    0x00000000      1            Qdevice

QDevice 状态标志

如上所示,QDevice 的状态输出通常包含三列:

  • A / NA:Alive 或 Not Alive。表示与外部 corosync-qnetd 守护进程的通信是否正常。

  • V / NV:QDevice 是否会为该节点投票。在脑裂情况下,如果节点之间的 corosync 连接中断, 但它们仍都能与外部 corosync-qnetd 守护进程通信,则只有一个节点会获得投票。

  • MW / NMW:Master wins(MV)或 not(NMW)。默认值为 NMW,见
    [votequorum_qdevice_master_wins manual page https://manpages.debian.org/bookworm/libvotequorum-dev/votequorum_qdevice_master_wins.3.en.html]

  • NR:QDevice 未注册。

Note 如果 QDevice 显示为 Not Alive(上方输出中的 NA),请确保外部服务器的端口 5403(qnetd 服务器默认端口)可通过 TCP/IP 访问。

常见问题

平局决胜

当出现平局时,即两个大小相同的集群分区无法互相看到、但都能看到 QDevice, QDevice 会随机选择其中一个分区并向其提供投票。

可能的负面影响

对于偶数节点集群,使用 QDevice 没有负面影响。如果它无法工作,效果与完全没有 QDevice 相同。

QDevice 设置后添加/删除节点

如果要在已配置 QDevice 的集群中添加新节点或移除现有节点,需要先移除 QDevice。 之后即可正常添加或移除节点。一旦集群再次拥有偶数节点数量,就可以按前文所述重新设置 QDevice。

移除 QDevice

如果使用官方 pvecm 工具添加了 QDevice,可以通过运行以下命令将其移除:

pve# pvecm qdevice remove

Corosync 配置

/etc/pve/corosync.conf 文件在 Proxmox VE 集群中具有核心作用。它控制集群成员关系和集群网络。 更多信息请查看 corosync.conf 手册页:

man corosync.conf

对于节点成员关系,应始终使用 Proxmox VE 提供的 pvecm 工具。 对于其他变更,可能需要手动编辑配置文件。以下是执行该操作的一些最佳实践建议。

编辑 corosync.conf

编辑 corosync.conf 文件并不总是很直接。每个集群节点上有两个该文件: 一个在 /etc/pve/corosync.conf,另一个在 /etc/corosync/corosync.conf。 编辑集群文件系统中的文件会将变更传播到本地文件,但反过来不会。

文件一旦变更,配置就会自动更新。这意味着能够集成到运行中 corosync 的变更会立即生效。 因此,应始终先复制一份并编辑副本,以避免在编辑过程中保存文件时触发非预期变更。

cp /etc/pve/corosync.conf /etc/pve/corosync.conf.new

然后,使用喜欢的编辑器打开配置文件,例如每个 Proxmox VE 节点上预安装的 nanovim.tiny

Note 配置变更后始终递增 config_version 数字;遗漏这一步可能导致问题。

完成必要变更后,再创建一份当前工作配置文件的副本。如果新配置应用失败或导致其他问题, 该副本可作为备份。

cp /etc/pve/corosync.conf /etc/pve/corosync.conf.bak

然后使用新配置文件替换旧配置文件:

mv /etc/pve/corosync.conf.new /etc/pve/corosync.conf

可以使用以下命令检查变更是否已自动应用:

systemctl status corosync
journalctl -b -u corosync

如果变更无法自动应用,可能需要通过以下命令重启 corosync 服务:

systemctl restart corosync

如发生错误,请查看下面的故障排查章节。

故障排查

问题:quorum.expected_votes must be configured

当 corosync 启动失败,并在系统日志中看到以下消息时:

[...]
corosync[1647]:  [QUORUM] Quorum provider: corosync_votequorum failed to initialize.
corosync[1647]:  [SERV  ] Service engine 'corosync_quorum' failed to load for reason
    'configuration error: nodelist or quorum.expected_votes must be configured!'
[...]

这意味着配置中为 corosync ringX_addr 设置的主机名无法解析。

在无仲裁时写入配置

如果需要在无仲裁节点上更改 /etc/pve/corosync.conf,并且清楚自己在做什么,请使用:

pvecm expected 1

这会将预期票数设置为 1,并使集群达到仲裁。随后可以修复配置,或将其还原到最后一个可工作的备份。

如果 corosync 已经无法启动,这还不够。在这种情况下,最好编辑 /etc/corosync/corosync.conf 中 corosync 配置的本地副本,让 corosync 能重新启动。 请确保所有节点上的该配置内容一致,以避免脑裂情况。

Corosync 配置术语表

ringX_addr

这表示节点之间 Kronosnet 连接的不同链路地址。

集群冷启动

显然,当所有节点都离线时,集群不具备仲裁。这是断电后常见的情况。

Note 使用不间断电源(“UPS”,也称为 “battery backup”)来避免这种状态始终是好做法, 尤其是在需要 HA 时。

节点启动时,pve-guests 服务会启动并等待仲裁。一旦具备仲裁,它会启动所有设置了 onboot 标志的客户机。

打开节点电源,或断电后恢复供电时,某些节点可能会比其他节点启动得更快。 请记住,客户机启动会延迟到达到仲裁之后。

客户机 VMID 自动选择

创建新客户机时,Web 界面会自动向后端请求一个空闲 VMID。默认搜索范围为 1001000000(低于 schema 强制执行的最大允许 VMID)。

有时管理员希望在单独范围内分配新 VMID,例如便于将临时虚拟机与手动选择 VMID 的虚拟机区分开。 有时只是希望提供长度稳定的 VMID;例如将下边界设置为 100000,可留出更多空间。

为满足这一用例,可以通过 datacenter.cfg 配置文件设置下边界、上边界或同时设置两者。 该文件可在 Web 界面 DatacenterOptions 下编辑。

Note 该范围仅用于 next-id API 调用,因此不是硬性限制。

客户机迁移

将虚拟客户机迁移到其他节点是集群中的一项有用功能。有一些设置可以控制这类迁移的行为。 可以通过 datacenter.cfg 配置文件进行设置,也可以针对特定迁移通过 API 或命令行参数设置。

客户机处于在线还是离线状态,或者是否具有本地资源(如本地磁盘),都会造成差异。

关于虚拟机迁移的详细信息,请参见 QEMU/KVM Migration Chapter

关于容器迁移的详细信息,请参见 Container Migration Chapter

迁移类型

迁移类型定义迁移数据应通过加密(secure)通道还是未加密(insecure)通道发送。 将迁移类型设置为 insecure 意味着虚拟客户机的 RAM 内容也会以未加密方式传输, 这可能导致客户机内部关键数据(例如密码或加密密钥)的信息泄露。

因此,如果不能完全控制网络,且无法保证无人窃听,强烈建议使用安全通道。

Note 存储迁移不遵循该设置。目前,它始终通过安全通道发送存储内容。

加密需要大量计算能力,因此该设置经常被改为 insecure 以获得更好性能。 现代系统的影响较低,因为它们在硬件中实现 AES 加密。在高速网络中, 性能影响尤其明显,例如可以传输 10 Gbps 或更高的网络。

迁移网络

默认情况下,Proxmox VE 使用承载集群通信的网络发送迁移流量。这并不理想, 因为敏感的集群流量可能受到干扰,而且该网络未必具有节点上可用的最佳带宽。

设置迁移网络参数后,可以为所有迁移流量使用专用网络。除内存外,这也会影响离线迁移的存储流量。

迁移网络以 CIDR 表示法作为网络来设置。这样做的优点是无需为每个节点设置单独 IP 地址。 Proxmox VE 可以根据 CIDR 形式指定的网络,确定目标节点上的实际地址。要启用这一点, 必须以每个节点在相应网络中恰好拥有一个 IP 的方式指定网络。

示例

假设有一个三节点配置,并具有三个独立网络。一个用于与 Internet 的公共通信, 一个用于集群通信,还有一个非常快的网络,希望将其用作迁移专用网络。

这种配置的网络配置可能如下所示:

iface eno1 inet manual

# public network
auto vmbr0
iface vmbr0 inet static
    address 192.X.Y.57/24
    gateway 192.X.Y.1
    bridge-ports eno1
    bridge-stp off
    bridge-fd 0

# cluster network
auto eno2
iface eno2 inet static
    address  10.1.1.1/24

# fast network
auto eno3
iface eno3 inet static
    address  10.1.2.1/24

这里,我们将网络 10.1.2.0/24 用作迁移网络。对于单次迁移,可以使用命令行工具的 migration_network 参数完成:

# qm migrate 106 tre --online --migration_network 10.1.2.0/24

要将其配置为集群中所有迁移的默认网络,请设置 /etc/pve/datacenter.cfg 文件的 migration 属性:

# use dedicated migration network
migration: secure,network=10.1.2.0/24
Note /etc/pve/datacenter.cfg 中设置迁移网络时,必须始终设置迁移类型。

常用命令示例

以下命令可用于查看集群、节点和迁移相关状态:

# pvecm status
# pvecm nodes
# qm migrate <vmid> <target-node> --online