暴露集群选项

默认情况下,集群配置(例如 worker 内存、docker 镜像等)由管理员在服务器配置文件中静态设置。要允许用户在创建新集群时更改某些参数,管理员必须在配置中明确地暴露这些参数。

用户体验

在用户侧,暴露选项允许用户可以

>>> options = gateway.cluster_options()
>>> options
Options<worker_cores=1, worker_memory=1.0, environment='basic'>
# Using Gateway.new_cluster
>>> cluster = gateway.new_cluster(worker_cores=2, environment="tensorflow")

# Or using the GatewayCluster constructor
>>> cluster = GatewayCluster(worker_cores=2, environment="tensorflow")
  • 如果在 Jupyter Notebook 中工作,可以使用基于 ipywidgets 的 GUI 来配置集群。

Cluster options widget

有关用户体验的更多信息,请参见 配置集群

服务器配置

通过设置 c.Backend.cluster_options 向用户暴露选项。此配置字段可以接受以下任一值:

Options(*fields[, handler])

对暴露的集群选项的声明性规范。

一个 dask_gateway_server.options.Options 对象接受两个参数:

  • *fields: 一个或多个 dask_gateway_server.options.Field 对象,它们提供每个面向用户的选项的类型化声明性规范。

  • handler: 一个可选的处理函数,用于将这些选项设置的值转换为要在相应的 ClusterConfig 上设置的配置值。其签名应为 handler(options)handler(options, user),其中 options 是用户选项的验证后字典,而 user 是该用户的 User 模型。

Field 对象为面向用户的选项提供类型化规范。有几种不同的 Field 类可用,每种代表一种不同的常见类型:

Integer(field[, default, min, max, label, ...])

一个整数字段,带可选边界。

Float(field[, default, min, max, label, target])

一个浮点数字段,带可选边界。

Bool(field[, default, label, target])

一个布尔字段。

String(field[, default, label, target])

一个字符串字段。

Select(field, options[, default, label, target])

一个选择字段,允许用户从几个选项中进行选择。

Mapping(field[, default, label, target])

一个映射字段。

每个字段支持以下标准参数:

  • field: 要使用的字段名称。必须是有效的 Python 标识符。这将是用户以编程方式设置此字段时使用的关键字(例如 "worker_cores")。

  • default: 如果用户未指定此字段,则使用的默认值。

  • label: 一个人类可读的标签,将用于 GUI 表示(例如 "Worker Cores")。可选,如果未提供,则将使用 field

  • target: 在处理后的选项字典中要设置的目标键。必须是有效的 Python 标识符。可选,如果未提供,则将使用 field

验证(类型、边界等)后,请求集群的所有选项字典将传递给一个 handler 函数。此函数在 dask-gateway-server 上运行。在这里可以进行任何额外的验证(在 handler 中引发的错误会转发给用户),以及暴露的选项字段与后端 ClusterConfig 上的配置字段之间所需的任何转换。默认的 handler 返回提供的选项,不做更改。

可用选项是后端特定的。例如,如果在 Kubernetes 上运行,选项 handler 可以返回 KubeClusterConfig 上任何配置字段的覆盖值。有关您的后端可用哪些集群配置字段的信息,请参见 Cluster Backends

示例

Worker 核数和内存

在这里,我们暴露选项供用户配置 c.ClusterConfig.worker_coresc.ClusterConfig.worker_memory。我们对每种资源设置了边界,以防止用户请求过大的 worker。handler 用于将用户指定的内存从 GiB 转换为字节(因为 c.ClusterConfig.worker_memory 期望字节单位)。

from dask_gateway_server.options import Options, Integer, Float

def options_handler(options):
    return {
        "worker_cores": options.worker_cores,
        "worker_memory": int(options.worker_memory * 2 ** 30),
    }

c.Backend.cluster_options = Options(
    Integer("worker_cores", default=1, min=1, max=4, label="Worker Cores"),
    Float("worker_memory", default=1, min=1, max=8, label="Worker Memory (GiB)"),
    handler=options_handler,
)

集群配置模板

除了暴露单个选项,您也可以选择暴露“配置模板”(profiles)——即常见选项组的用户友好名称。例如,在这里我们提供 3 个集群配置模板(小型、中型和大型),用户可以从中选择。

from dask_gateway_server.options import Options, Select

# A mapping from profile name to configuration overrides
profiles = {
    "small": {"worker_cores": 2, "worker_memory": "4 G"},
    "medium": {"worker_cores": 4, "worker_memory": "8 G"},
    "large": {"worker_cores": 8, "worker_memory": "16 G"},
}

# Expose `profile` as an option, valid values are 'small', 'medium', or
# 'large'. A handler is used to convert the profile name to the
# corresponding configuration overrides.
c.Backend.cluster_options = Options(
    Select(
        "profile",
        ["small", "medium", "large"],
        default="medium",
        label="Cluster Profile",
    ),
    handler=lambda options: profiles[options.profile],
)

不同用户组的不同选项

集群选项可以根据用户配置为不同,方法是为 c.Backend.cluster_options 提供一个函数。此函数接收一个 dask_gateway_server.models.User 对象,并应返回一个 dask_gateway_server.options.Options 对象。它也可以是一个可选的 async 函数。

与上一个示例类似,在这里我们暴露选项供用户配置 c.ClusterConfig.worker_coresc.ClusterConfig.worker_memory。然而,我们根据用户是否属于“power-users”组提供不同的范围。

from dask_gateway_server.options import Options, Integer, Float

def options_handler(options):
    return {
        "worker_cores": options.worker_cores,
        "worker_memory": int(options.worker_memory * 2 ** 30),
    }

def generate_options(user):
    if "power-users" in user.groups:
        options = Options(
            Integer("worker_cores", default=1, min=1, max=8, label="Worker Cores"),
            Float("worker_memory", default=1, min=1, max=16, label="Worker Memory (GiB)"),
            handler=options_handler,
        )
    else:
        options = Options(
            Integer("worker_cores", default=1, min=1, max=4, label="Worker Cores"),
            Float("worker_memory", default=1, min=1, max=8, label="Worker Memory (GiB)"),
            handler=options_handler,
        )

c.Backend.cluster_options = generate_options

用户特定配置

由于 handler 函数可以可选地接收 User 对象,您可以使用它来添加用户特定配置。请注意,您无需暴露任何配置选项即可利用此功能,选项 handler 无论如何都会被调用。

在这里,我们根据用户的组配置 worker 核数和内存

from dask_gateway_server.options import Options

def options_handler(options, user):
    if "power-users" in user.groups:
        return {
            "worker_cores": 8,
            "worker_memory": "16 G"
        }
    else:
        return {
            "worker_cores": 4,
            "worker_memory": "8 G"
        }

c.Backend.cluster_options = Options(handler=options_handler)