自定义用户资源#

注意

有关您可以配置的所有 Helm 图表选项的列表,请参见 配置参考.

用户资源包括 JupyterHub 提供给用户的 CPU、RAM 和存储。大多数可以通过修改 Helm 图表来控制。有关将修改部署到 JupyterHub 部署的信息,请参见 应用配置更改.

由于 JupyterHub 可以为许多不同类型的用户提供服务,因此 JupyterHub 管理员必须能够灵活地 **分配用户资源**,例如内存或计算。例如,Hub 可能为具有大量资源需求的资深用户提供服务,也可能为具有更基本资源需求的初学者用户提供服务。能够根据用户群体的需求自定义 Hub 的资源可以改善所有 Hub 用户的使用体验。

设置用户内存和 CPU 保证/限制#

您 JupyterHub 上的每个用户都获得了一部分内存和 CPU 来使用。有两种方法可以指定用户可以使用多少资源:资源 *保证* 和资源 *限制*。

资源 *保证* 意味着所有用户将始终至少拥有此资源,但如果可用,他们可能会获得更多资源。例如,如果用户 *保证* 1G 的 RAM,用户理论上可以使用超过 1G 的 RAM,前提是这些资源没有被其他用户使用。

资源 *限制* 对可用资源设置了硬性限制。在上面的示例中,如果存在 1G 内存限制,则意味着用户最多可以使用 1G 的 RAM,无论机器上正在使用哪些其他资源。

默认情况下,每个用户 *保证* 1G 的 RAM。所有用户 *至少* 有 1G,但如果可用,他们理论上可以使用更多。您可以轻松更改这些资源的数量,以及它们是 *保证* 还是 *限制*,方法是更改您的 config.yaml 文件。这可以通过以下结构完成。

singleuser:
  memory:
    limit: 1G
    guarantee: 1G

这将设置 1G 的内存限制和保证。Kubernetes 将确保每个用户始终可以访问 1G 的 RAM,并且对更多 RAM 的请求将失败(您的内核通常会崩溃)。您可以将限制设置为高于保证,以允许某些用户在非常短的时间内使用更大的 RAM 量(例如,在运行一个消耗大量内存的单一、短暂函数时)。

类似地,您可以限制 CPU,如下所示

singleuser:
  cpu:
    limit: .5
    guarantee: .5

这将限制您的用户最多使用 0.5 个 CPU(即 1/2 个 CPU 内核),并保证他们使用相同的数量。

注意

请记住在更改 config.yaml 文件后 应用更改

设置用户 GPU 保证/限制#

可以为您的用户分配 GPU。这对于深度学习等更繁重的负载非常有用,这些负载可以利用 GPU。

例如,要创建一个分配一个 NVIDIA GPU 的配置文件

singleuser:
  profileList:
    - display_name: "GPU Server"
      description: "Spawns a notebook server with access to a GPU"
      kubespawner_override:
        extra_resource_limits:
          nvidia.com/gpu: "1"

这假设您的至少一个 Kubernetes 节点已连接了兼容的 GPU。执行此操作的方法因基础设施提供商而异。以下是一些链接,可以帮助您入门

您还需要按照说明部署 k8s-device-plugin 这里.

要检查您的 GPU 是否可被 Kubernetes 调度,您可以运行以下命令

kubectl get nodes -o=custom-columns=NAME:.metadata.name,GPUs:.status.capacity.'nvidia\.com/gpu'

修改用户共享内存大小#

增加运行深度学习等工作负载的 Pod 的共享内存 (SHM) 分配也有益。这是 PyTorch 的 DataLoader 等函数正常运行所必需的。

以下配置将通过在 /dev/shm 处挂载 tmpfs (ramdisk) 来增加 SHM 分配,替换默认的 64MB 分配。

singleuser:
  storage:
    extraVolumes:
      - name: shm-volume
        emptyDir:
          medium: Memory
    extraVolumeMounts:
      - name: shm-volume
        mountPath: /dev/shm

当用户的 Pod 创建时,卷 shm-volume 将被创建,并在 Pod 被销毁后被销毁。

关于 SHM 分配的一些重要注意事项

  • Pod 使用的 SHM 将计入其内存限制

  • 当内存限制被超过时,Pod 将被驱逐

修改用户存储类型和大小#

有关如何修改用户可以访问的存储类型和大小的信息,请参见 自定义用户存储

扩展和收缩集群的大小#

您可以轻松地扩展或缩减集群的大小,以满足使用需求或在集群未被使用时节省成本。当您有可预测的使用高峰时,这尤其有用。例如,如果您正在组织和运行研讨会,调整集群大小可以让您节省成本并在活动之前准备 JupyterHub。例如

  • 研讨会前一周:您可以创建集群,设置所有内容,然后将集群调整为零个节点以节省成本。

  • 研讨会当天:您可以将集群扩展到适合研讨会的大小。此工作流程还有助于您避免在研讨会当天争先恐后地设置集群和 JupyterHub。

  • 研讨会结束后:可以删除集群。

以下部分描述了如何在各种云平台上调整集群大小。

Google Cloud Platform#

使用 resize 命令并提供新的集群大小(即节点数)作为命令行选项 --num-nodes

gcloud container clusters resize \
    <YOUR-CLUSTER-NAME> \
    --num-nodes <NEW-SIZE> \
    --zone <YOUR-CLUSTER-ZONE>

要显示集群的名称、区域或当前大小,请使用以下命令

gcloud container clusters list

调整集群大小后,可能需要几分钟才能将新的集群大小报告回来,因为服务正在添加或删除节点。您可以使用 kubectl get node 来查找当前“就绪”节点的真实数量,以报告集群中所有节点的当前 Ready/NotReady 状态。

Microsoft Azure Platform#

使用 scale 命令并提供新的集群大小(即节点数)作为命令行选项 --node-count

az aks scale \
    --name <YOUR-CLUSTER-NAME> \
    --node-count <NEW-SIZE> \
    --resource-group <YOUR-RESOURCE-GROUP>

要显示集群的详细信息,请使用以下命令

az aks show --name <YOUR-CLUSTER-NAME> --resource-group <YOUR-RESOURCE-GROUP>

新的集群节点可能需要一些时间才能就绪。您可以使用 kubectl get node 来报告集群中所有节点的当前 Ready/NotReady 状态。

Amazon Web Services Elastic Kubernetes Service (EKS)#

AWS EKS 是一项 Amazon 服务,提供 AWS 管理的 Kubernetes 控制平面和一组命令行工具 eksctl,用于创建和管理 Kubernetes 集群。这只是在 AWS 基础设施上部署 Kubernetes 的一种方式,但以下假设您拥有

  1. 在 EKS 上部署的 Kubernetes 集群

  2. 命令行工具 eksctl 已安装 并配置为指向您的 EKS 集群。

要使用 eksctl 命令行工具扩展现有节点组

eksctl scale nodegroup \
  -n <NODEGROUP-NAME> \
  --nodes <DESIRED-NUMBER-OF-NODES>\
  --nodes-max <MAX-NUMBER-OF-NODES>\
  --nodes-min <MIN-NUMBER-OF-NODES>\
  --cluster=<YOUR-CLUSTER-NAME>

如果您已设置集群自动扩展器,您也可以使用 eksctl 命令行工具创建自动扩展节点组。

eksctl create nodegroup \
  --cluster <YOUR-CLUSTER-NAME> \
  --name <NODEGROUP-NAME> \
  --node-type <EC2-INSTANCE-TYPE(S)> \
  --nodes-max <MAX-NUMBER-OF-NODES>\
  --nodes-min <MIN-NUMBER-OF-NODES>\
  --ssh-access \
  --ssh-public-key <PATH-TO-KEYPAIR-WITH-EKS-PERMISSIONS> \
  --node-zones <OPTIONALLY-SPECIFY-AVAILABILIYT-ZONE-FOR-NODES> \
  --tags "k8s.io/cluster-autoscaler/node-template/taint/<some-taint-key>=<some-taint-value>:<some-taint-effect>, k8s.io/cluster-autoscaler/node-template/label/<some-node-label-key>=<some-node-label-value>,k8s.io/cluster-autoscaler/<YOUR-CLUSTER-NAME>=true,k8s.io/cluster-autoscaler/enabled=true" \
  --node-labels "<some-node-label-key>=<some-node-label-value>,failure-domain.beta.kubernetes.io/zone=<AVAILABILITY-ZONE>,failure-domain.beta.kubernetes.io/region=<AVAILABILITY-REGION>"

为了使 AWS 集群自动扩展器能够自动扩展节点组,必须应用以下标签:k8s.io/cluster-autoscaler/<YOUR-CLUSTER-NAME>=<any-value-only-key-matters>k8s.io/cluster-autoscaler/enabled=true

必须添加一个 tag,它对应于每个 node-labels,这些标签将在调度 Pod 时用作 nodeSelector;对于形式为 <some-node-label-key>=<some-node-label-value>node-labels,这些标签应为 k8s.io/cluster-autoscaler/node-template/label/<some-node-label-key>=<some-node-label-value>

也可以使用形式为 k8s.io/cluster-autoscaler/node-template/taint/<some-taint-key>=<some-taint-value>:<some-taint-effect> 的标签将污点应用于节点组中的节点。

最后,可以使用 node-labels 设置 AWS 区域(例如,eu-west-1)和可用区(例如,eu-west-1a):failure-domain.beta.kubernetes.io/region=<AVAILABILITY-REGION>failure-domain.beta.kubernetes.io/zone=<AVAILABILITY-ZONE>;或者使用 --node-zones 标志。设置可用区在单用户 Pod 可能被调度到不同可用区中的节点时很有用;当使用任何不支持跨可用区挂载的 persistentVolume 存储(包括 AWS EKS 中的默认 gp2 存储)时,这种情况会造成问题。在这些情况下,PV 将在用户 Pod 首次调度的节点的可用区中创建,如果将来同一个用户 Pod 被调度到不同的可用区,则会发生错误。通过控制 nodegroups 部署到的区域和/或为 values.yaml 中引用的自定义 StorageClass 中的卷指定可用区来避免这种情况。