关于集群

为了将总工作负载分散到多个服务器上,Incus 可以以集群模式运行。在这种情况下,任意数量的 Incus 服务器共享同一个分布式数据库,该数据库保存集群成员及其实例的配置。可以使用 incus 客户端或 REST API 统一管理 Incus 集群。

集群成员

Incus 集群由一个引导服务器和至少两个其他集群成员组成。它将其状态存储在一个 分布式数据库 中,该数据库是一个使用 Raft 算法复制的 Cowsql 数据库。

虽然您可以创建一个只有两个成员的集群,但强烈建议集群成员的数量至少为三个。通过这种设置,集群可以在至少一个成员丢失的情况下仍然能够为其分布式状态建立仲裁。

创建集群时,Cowsql 数据库仅在引导服务器上运行,直到第三个成员加入集群。然后,第二台和第三台服务器都将收到数据库的副本。

有关更多信息,请参见 如何形成集群

成员角色

在具有三个成员的集群中,所有成员都复制存储集群状态的分布式数据库。如果集群有更多成员,则只有其中一些成员复制数据库。其余成员可以访问数据库,但不会复制它。

在任何时候,都存在一个选定的集群领导者,它监控其他成员的运行状况。

每个复制数据库的成员都具有投票者或备用者的角色。如果集群领导者脱机,则投票者之一将被选为新的领导者。如果投票者成员脱机,则备用成员将自动提升为投票者。只要大多数投票者在线,数据库(以及集群)就会保持可用。

以下角色可以分配给 Incus 集群成员。自动角色由 Incus 本身分配,用户无法修改。

角色

自动

描述

database

分布式数据库的投票成员

database-leader

分布式数据库的当前领导者

database-standby

分布式数据库的备用(非投票)成员

event-hub

内部 Incus 事件的交换点(集线器)(至少需要两个)

ovn-chassis

OVN 网络的上行链路网关候选者

投票成员的默认数量(cluster.max_voters)为三个。备用成员的默认数量(cluster.max_standby)为两个。通过此配置,只要您一次最多关闭一个投票成员,您的集群将保持运行。

有关更多信息,请参见 如何管理集群

脱机成员和容错

如果集群成员停机时间超过配置的脱机阈值,则其状态将标记为脱机。在这种情况下,此成员上无法执行任何操作,并且需要跨所有成员更改状态的操作也无法执行。

脱机成员一旦重新上线,操作即可再次使用。

如果脱机的成员是领导者本身,则其他成员将选举一个新的领导者。

如果您无法或不想使服务器重新上线,则可以 将其从集群中删除

您可以通过设置 cluster.offline_threshold 配置来调整将未响应的成员视为脱机之前的秒数。默认值为 20 秒。最小值为 10 秒。

要自动 疏散 脱机成员上的实例,请将 cluster.healing_threshold 配置设置为非零值。

有关更多信息,请参见 如何恢复集群

故障域

您可以使用故障域来指示在为已脱机的集群成员分配角色时应优先考虑哪些集群成员。例如,如果当前具有数据库角色的集群成员关闭,则 Incus 会尝试将其数据库角色分配给同一故障域中的另一个集群成员(如果可用)。

要更新集群成员的故障域,请使用 incus cluster edit <member> 命令并将 failure_domain 属性从 default 更改为另一个字符串。

成员配置

通常假设 Incus 集群成员是相同的系统。这意味着加入集群的所有 Incus 服务器在存储池和网络方面必须与引导服务器具有相同的配置。

为了适应诸如磁盘排序略有不同或网络接口命名略有不同的情况,对于与存储和网络相关的某些配置选项,存在一个例外,这些选项是特定于成员的。

当此类设置存在于集群中时,任何正在添加的服务器都必须为其提供值。大多数情况下,这是通过交互式incus admin init命令完成的,该命令会提示用户输入与存储或网络相关的许多配置键的值。

这些设置通常包括

  • 存储池的源设备和大小

  • ZFS zpool、LVM 稀疏池或 LVM 卷组的名称

  • 桥接网络的外部接口和 BGP 下一跳

  • 托管physicalmacvlan网络的父网络设备的名称

有关更多信息,请参阅如何为集群配置存储如何为集群配置网络

如果您想提前查看这些问题(这对于脚本编写很有用),请查询/1.0/cluster API 端点。这可以通过incus query /1.0/cluster或其他 API 客户端来完成。

镜像

默认情况下,Incus 会在尽可能多的集群成员上复制镜像,数量与数据库成员的数量相同。这通常意味着在集群内最多复制三份。

您可以增加此数字以提高容错能力和镜像在本地可用的可能性。为此,请设置cluster.images_minimal_replica配置。特殊值-1可用于将镜像复制到所有集群成员。

集群组

在 Incus 集群中,您可以将成员添加到集群组。您可以使用这些集群组在属于所有可用成员子集的集群成员上启动实例。例如,您可以为所有具有 GPU 的成员创建一个集群组,然后在此集群组上启动所有需要 GPU 的实例。

默认情况下,所有集群成员都属于default组。

有关更多信息,请参阅如何设置集群组在特定集群成员上启动实例

实例的自动放置

在集群设置中,每个实例都位于一个集群成员上。当您启动实例时,您可以将其目标设置为特定的集群成员、集群组或让 Incus 自动将其分配给集群成员。

默认情况下,自动分配会选择实例数量最少的集群成员。如果多个成员的实例数量相同,则会随机选择其中一个成员。

但是,您可以使用scheduler.instance配置选项控制此行为。

  • 如果对于集群成员,scheduler.instance设置为all,则如果满足以下条件,则为该实例选择此集群成员:

    • 实例在没有--target的情况下创建,并且集群成员的实例数量最少。

    • 实例的目标是驻留在此集群成员上。

    • 实例的目标是驻留在该集群成员所属的集群组的成员上,并且与集群组的其他成员相比,该集群成员的实例数量最少。

  • 如果对于集群成员,scheduler.instance设置为manual,则如果满足以下条件,则为该实例选择此集群成员:

    • 实例的目标是驻留在此集群成员上。

  • 如果对于集群成员,scheduler.instance设置为group,则如果满足以下条件,则为该实例选择此集群成员:

    • 实例的目标是驻留在此集群成员上。

    • 实例的目标是驻留在该集群成员所属的集群组的成员上,并且与集群组的其他成员相比,该集群成员的实例数量最少。

实例放置脚本

Incus 支持使用自定义逻辑通过使用嵌入式脚本(脚本)来控制实例的自动放置。此方法比内置的实例放置功能提供了更大的灵活性。

实例放置脚本必须使用Starlark 语言(它是 Python 的一个子集)编写。每次 Incus 需要知道将实例放置在何处时,都会调用脚本。脚本会接收有关正在放置的实例和可能承载该实例的候选集群成员的信息。脚本还可以请求有关每个候选集群成员状态和可用硬件资源的信息。

实例放置脚本必须实现具有以下签名的instance_placement函数

instance_placement(request, candidate_members):

  • request是一个对象,其中包含scriptlet.InstancePlacement的扩展表示形式。此请求包括projectreason字段。reason可以是newevacuationrelocation

  • candidate_members是一个list,其中包含表示api.ClusterMember条目的集群成员对象。

例如

def instance_placement(request, candidate_members):
    # Example of logging info, this will appear in Incus' log.
    log_info("instance placement started: ", request)

    # Example of applying logic based on the instance request.
    if request.name == "foo":
        # Example of logging an error, this will appear in Incus' log.
        log_error("Invalid name supplied: ", request.name)

        fail("Invalid name") # Exit with an error to reject instance placement.

    # Place the instance on the first candidate server provided.
    set_target(candidate_members[0].server_name)

    return # Return empty to allow instance placement to proceed.

脚本必须应用于 Incus,方法是将其存储在instances.placement.scriptlet全局配置设置中。

例如,如果脚本保存在名为instance_placement.star的文件中,则可以使用以下命令将其应用于 Incus

cat instance_placement.star | incus config set instances.placement.scriptlet=-

要查看应用于 Incus 的当前脚本,请使用incus config get instances.placement.scriptlet命令。

以下函数可用于脚本(除了 Starlark 提供的函数之外):

  • log_info(*messages):在info级别向 Incus 的日志添加日志条目。messages是一个或多个消息参数。

  • log_warn(*messages):在warn级别向 Incus 的日志添加日志条目。messages是一个或多个消息参数。

  • log_error(*messages):在error级别向 Incus 的日志添加日志条目。messages是一个或多个消息参数。

  • set_target(member_name):设置应在其中创建实例的集群成员。member_name是要在其中创建实例的集群成员的名称。如果未调用此函数,则 Incus 将使用其内置的实例放置逻辑。

  • get_cluster_member_resources(member_name):获取有关集群成员上资源的信息。返回一个对象,其中包含以api.Resources形式表示的资源信息。member_name是要获取资源信息的集群成员的名称。

  • get_cluster_member_state(member_name):获取集群成员的状态。返回一个对象,其中包含以api.ClusterMemberState形式表示的集群成员的状态。member_name是要获取状态的集群成员的名称。

  • get_instance_resources():获取有关实例将需要的资源的信息。返回一个对象,其中包含以scriptlet.InstanceResources形式表示的资源信息。

  • get_instances(location, project):根据项目和/或位置过滤器获取实例列表。返回以[]api.Instance形式表示的实例列表。

  • get_instances_count(location, project, pending):根据项目和/或位置过滤器获取实例数量。此计数可能包括当前正在创建但尚无数据库记录的实例。

  • get_cluster_members(group):根据集群组获取集群成员列表。返回以[]api.ClusterMember形式表示的集群成员列表。

  • get_project(name):根据项目名称获取项目对象。返回以api.Project形式表示的项目对象。

注意

对象类型中的字段名称等效于关联的 Go 类型中的 JSON 字段名称。