自定义用户存储#
在本指南中,我们将“存储”描述为“卷” - 磁盘上用户数据所在的目录。
Kubernetes 处理持久卷的创建和分配,在幕后它使用云提供商的 API 来发出正确的命令。因此,我们关于卷的大部分讨论将描述 Kubernetes 对象。
JupyterHub 使用 Kubernetes 来管理用户存储。有两个主要的 Kubernetes 对象参与将存储分配给 Pod
一个
PersistentVolumeClaim
(PVC
) 指定了所需的存储类型。它的配置在您的config.yaml
文件中指定。一个
PersistentVolume
(PV
) 是用户数据实际所在的卷。它由 Kubernetes 使用PVC
中的详细信息创建。
作为 Kubernetes 对象,它们可以使用标准的 kubectl
命令查询(例如,kubectl --namespace=<your-namespace> get pvc
)
在 JupyterHub 中,每个用户都拥有自己的 PersistentVolumeClaim
对象,代表与其帐户关联的数据。当新用户启动其 JupyterHub 服务器时,将为该用户创建一个 PersistentVolumeClaim
。此声明告诉 Kubernetes 需要什么样的存储(例如,ssd 与 hd)以及需要多少存储。Kubernetes 检查是否为该用户存在 PersistentVolume
对象(由于这是一个新用户,因此不存在)。如果不存在 PV
对象,则 Kubernetes 将使用 PVC
为用户创建一个新的 PV
对象。
现在用户有了 PV
,Kubernetes 接下来必须将该 PV
附加(或“挂载”)到用户的 Pod(运行用户代码)。完成此操作后,用户将可以在 JupyterHub 中访问其 PV
。请注意,所有这些都在用户登录时在幕后自动完成。
PersistentVolumeClaim
和 PersistentVolume
不会被删除,除非 PersistentVolumeClaim
被 JupyterHub 管理员显式删除。当用户关闭其服务器时,其用户 Pod 会被删除,其卷会从 Pod 中分离,但 PVC
和 PV
对象仍然存在。将来,当用户再次登录时,JupyterHub 会检测到用户拥有预先存在的 PVC
,并将简单地将其附加到其新的 Pod,而不是创建新的 PVC
。
此过程如何出现故障?#
当 Kubernetes 使用 PVC
创建新的用户 PV
时,它会向 Kubernetes 所运行的云提供商的底层 API 发送命令。有时,对特定 PV
的请求可能会失败 - 例如,如果您的帐户已达到可用磁盘空间的限制。
另一个常见问题是集群中节点上可同时挂载的卷数限制。请查看您的云提供商以了解您请求的存储资源限制的详细信息。
注意
一些云提供商对每个节点可以挂载的磁盘数量有限制。由于 JupyterHub 为每个用户分配一个磁盘用于持久存储,因此这限制了在任何时间点可以运行在节点上的用户数量。如果您需要用户拥有持久存储,并且您最终遇到了此限制,则必须使用更多节点来容纳每个用户的磁盘。在这种情况下,我们建议为每个节点分配更少的资源(例如 RAM),因为您将在单个节点上容纳更少的用户。
配置#
大多数存储配置是在集群级别完成的,并且不是 JupyterHub 独有的。但是,有些部分是,我们将在此演示如何配置它们。
请注意,除非销毁旧的 PVC
,否则不会为现有用户创建新的 PVC
。如果您通过 config.yaml
更新用户的 PVC
配置,那么任何新用户将为他们创建新的 PVC
,但旧用户不会。要强制升级旧用户的存储类型,您需要手动删除他们的 PVC
(例如 kubectl --namespace=<your-namespace> delete pvc <pvc-name>
)。这将删除用户的所有数据,因此我们建议您先备份他们的文件系统,如果您想保留他们的数据。
删除用户的 PVC
后,他们下次登录时,将根据您更新的 PVC
规范为他们创建一个新的 PVC
。
配置的存储类型#
一个 StorageClass 对象用于确定为您的用户配置什么类型的 PersistentVolume
。大多数流行的云提供商都有一个标记为默认的 StorageClass
。您可以通过以下方式找到您的默认 StorageClass
kubectl get storageclass
并查找其名称旁边有 (default)
的对象。
要更改为您的用户配置的 PersistentVolume
类型,
按照 Kubernetes 文档 创建一个新的
StorageClass
对象在
config.yaml
中指定您刚刚创建的StorageClass
的名称singleuser: storage: dynamic: storageClass: <storageclass-name>
执行
helm upgrade
请注意,这只会影响登录的新用户。我们建议您在用户开始大量使用您的集群之前执行此操作。
我们将在下面提供流行云提供商的示例,但通常会参考 Kubernetes 文档。
Google Cloud#
在 Google Cloud 上,默认的 StorageClass
将配置标准的 Google 持久磁盘。这些磁盘运行在硬盘上。为了获得更高的性能,您可能需要使用 SSD。要使用 SSD,您可以通过将以下 yaml
放入一个新文件中来创建一个新的 StorageClass
。我们建议使用描述性的名称,例如 storageclass.yaml
,我们将在下面使用它
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: jupyterhub-user-ssd
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
allowedTopologies:
- matchLabelExpressions:
- key: failure-domain.beta.kubernetes.io/zone
values:
- <your-cluster-zone>
将 <your-cluster-zone>
替换为您创建集群的区域(您可以使用 gcloud container clusters list
找到它)。
接下来,通过在命令行中运行 kubectl apply -f storageclass.yaml
来创建此对象。有关各个字段含义的更多信息,请参阅 Kubernetes 文档。最重要的字段是 parameters.type
,它指定您要使用的存储类型。有两个选项:
pd-ssd
使StorageClass
配置 SSD。pd-standard
将配置非 SSD 磁盘。
创建此 StorageClass
后,您可以在您的 config.yaml
中使用以下内容配置 JupyterHub 的 PVC
模板
singleuser:
storage:
dynamic:
storageClass: jupyterhub-user-ssd
请注意,对于 storageClass:
,我们使用上面在 metadata.name
中指定的名称。
配置的存储大小#
您可以在您的 config.yaml
中的 PVC
中设置 JupyterHub 请求的存储大小。
singleuser:
storage:
capacity: 2Gi
这将为每个用户请求一个 2Gi
的卷。默认情况下,每个用户请求一个 10Gi
的卷。
我们建议您使用 IEC 二进制前缀(Ki、Mi、Gi 等)来指定您需要的存储量。 2Gi
(IEC 二进制前缀)是 (2 * 1024 * 1024 * 1024)
字节,而 2G
(SI 十进制前缀)是 (2 * 1000 * 1000 * 1000)
字节。
关闭每个用户的持久存储#
如果您不希望用户拥有任何持久存储,可以将其关闭。编辑 config.yaml
文件并将存储类型设置为 none
singleuser:
storage:
type: none
接下来 应用更改。
应用更改后,新用户将不再被分配持久 $HOME
目录。任何当前运行的用户仍然可以访问他们的存储,直到他们的服务器重新启动。您可能需要使用 kubectl
手动删除当前用户的 PVCs
以回收可能已分配的任何云磁盘。您可以使用以下命令获取当前的 PVC
列表:
kubectl --namespace=<your-namespace> get pvc
然后,您可以使用以下命令删除不需要的 PVCs
:
kubectl --namespace=<your-namespace> delete pvc <pvc-name>
请记住,删除某个人的 PVCs
将删除他们所有的数据,因此请谨慎操作!
附加存储卷#
如果您已经在 JupyterHub 之外创建了 PersistentVolume
和 PersistentVolumeClaim
,则可以将它们挂载到用户 Pod 中。例如,如果您有一个名为 jupyterhub-shared-volume
的共享 PersistentVolumeClaim
,则可以将其挂载到所有用户 Pod 中的 /home/shared
。
singleuser:
storage:
extraVolumes:
- name: jupyterhub-shared
persistentVolumeClaim:
claimName: jupyterhub-shared-volume
extraVolumeMounts:
- name: jupyterhub-shared
mountPath: /home/shared
请注意,如果您想将卷挂载到多个 Pod 中,则该卷必须支持合适的 访问模式。