自定义用户资源#
注意
有关您可以配置的所有 Helm chart 选项的列表,请参阅配置参考。
用户资源包括 JupyterHub 提供给用户的 CPU、RAM 和存储。其中大部分可以通过修改 Helm chart 来控制。有关如何将您的修改部署到 JupyterHub 的信息,请参阅应用配置更改。
由于 JupyterHub 可以为许多不同类型的用户提供服务,JupyterHub 的管理者和管理员必须能够灵活地**分配用户资源**,如内存或计算资源。例如,Hub 可能既要服务于有大量资源需求的高级用户,也要服务于资源需求更初级的入门用户。自定义 Hub 资源以满足这两个用户群体的能力,可以改善所有 Hub 用户的体验。
设置用户内存和 CPU 的保证/限制#
JupyterHub 上的每个用户都会获得一部分内存和 CPU 以供使用。有两种方式可以指定用户可使用的资源量:资源*保证*(guarantees)和资源*限制*(limits)。
资源*保证*意味着所有用户在任何时候都*至少*拥有这些可用资源,但如果系统中有更多可用资源,他们也可能被分配更多。例如,如果用户被*保证*拥有 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(即半个 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'
修改用户存储类型和大小#
有关如何修改用户可访问的存储类型和大小的信息,请参阅自定义用户存储。
扩展和收缩集群的大小#
您可以轻松地扩大或缩小集群的规模,以满足使用需求或在集群不使用时节省成本。当您有可预测的使用高峰时,这特别有用。例如,如果您正在组织并举办一个研讨会,调整集群大小可以让您在活动前节省成本并准备好 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 是亚马逊的一项服务,提供由 AWS 管理的 Kubernetes 控制平面和一套命令行工具 eksctl
,用于创建和管理 Kubernetes 集群。这只是使用 AWS 基础设施部署 Kubernetes 的一种方式,但以下内容假设您已经
在 EKS 上部署了一个 Kubernetes 集群
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>"
必须应用标签 k8s.io/cluster-autoscaler/<YOUR-CLUSTER-NAME>=<any-value-only-key-matters>
和 k8s.io/cluster-autoscaler/enabled=true
,AWS 集群自动伸缩器才能对节点组进行自动伸缩。
对于将用作 nodeSelector
的每个 node-labels
,都必须添加一个相应的 tag
;对于形式为 <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>
的标签为节点组中的节点应用污点(Taints)。
最后,可以使用 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
标志。当 singleUser pod 可能被调度到不同可用区的节点时,设置可用区非常有用;在使用任何不支持跨可用区挂载的 persistentVolume
存储后端(包括 AWS EKS 中的默认 gp2
存储)时,这种情况是有问题的。在这些情况下,PV
是在用户 pod 首次被调度的节点的可用区中创建的,如果将来同一个用户 pod 被调度到不同的可用区,就会发生错误。通过控制 nodegroups
部署的区域和/或在 values.yaml
中引用的自定义 StorageClass
中为卷指定可用区,可以避免这种情况。