使用工具#
JupyterHub 旨在与云计算和容器技术领域的许多工具连接。本页将更详细地描述这些工具,以提供更多上下文信息。
云计算提供商#
这是运行实际计算的任何东西。通常是指公司、大学服务器或其他组织,它们托管可远程访问的计算资源。JupyterHub 将在这些计算资源上运行,这意味着如果用户与您的 JupyterHub 交互,他们也将使用这些资源。
它们提供以下内容
计算
磁盘空间
网络(内部和外部)
创建、调整大小和删除集群
其中一些组织是公司(例如,Google),但 JupyterHub 也适用于大学集群或自定义集群部署。对于这些材料,任何安装了 Kubernetes 的集群都可以与 JupyterHub 配合使用。
有关使用云提供商设置帐户服务的更多信息,请参见 此处。
容器技术#
容器技术本质上是将运行软件所需的所有组件捆绑在一起的想法。有许多方法可以做到这一点,但我们将重点关注一种称为 Docker 的方法。以下是 Docker 的主要概念
容器镜像#
容器镜像包含运行代码所需的依赖项。这包括 **所有内容**,一直到操作系统本身。它还包括代码运行的文件系统,其中可能包括数据等。容器也是可移植的,这意味着您可以在几乎任何机器上精确地重新创建运行代码的计算环境。
在 Docker 中,镜像被描述为层,就像依赖项的层一样。例如,假设您要构建一个运行 scikit-learn 的容器。它依赖于 Python,因此您有两个层:一个用于 python,另一个继承 python 层并添加 scikit-learn 的额外部分。此外,该基本 python 层需要一个操作系统才能运行,因此现在您有三个层:ubuntu -> python -> scikit-learn。您明白了。这样做的妙处在于,这意味着您可以在镜像之间共享基本层。这意味着,如果您有许多不同的镜像都要求 ubuntu,则无需在周围放置许多 ubuntu 副本。
镜像可以从许多东西创建。如果您使用的是 Docker,最基本的方法是使用 **Dockerfile**。这本质上是一系列说明,告诉 Docker 如何创建镜像。它可能会告诉 Docker 您想在镜像中包含哪些基本层,以及镜像中需要的其他一些依赖项。把它想象成一个食谱,告诉 Docker 如何创建镜像。
容器#
您可以“运行”容器镜像,它会为您创建一个容器。容器是容器镜像的特定实例。这意味着它实际上存在于计算机上。它是一个自包含的计算环境,根据容器镜像中的层构建。但是,由于它现在正在计算机上运行,因此它可以执行其他有用的操作,例如与其他 Docker 容器通信或通过互联网进行通信。
Kubernetes#
Kubernetes 是一种运行在云基础设施上的服务。它为集群部署提供了一个单一联系点,允许用户指定所需的计算需求(例如,多少台机器,每台机器多少个 CPU,多少 RAM)。然后,它处理集群上的资源并确保这些资源始终可用。如果出现故障,Kubernetes 会尝试自动将其恢复。
Kubernetes 只能管理分配给它的计算资源。这意味着它通常 **不能** 自己创建新的资源(磁盘空间除外)。
以下部分描述了 Kubernetes 中与 JupyterHub 最相关的对象。
进程#
是指在机器上运行的任何程序。例如,Jupyter Notebook 创建了几个进程来处理代码执行和浏览器中的显示。从技术上讲,这不是 Kubernetes 对象,因为任何计算机上都运行着进程,但 Kubernetes 会跟踪运行的进程,以确保它们在需要时保持运行。
Pod#
Pod 本质上是一组或多个一起运行的 容器。您可以将它们视为将容器组合在一起的方式,这些容器作为一个组来完成某些目标。
例如,假设您想创建一个对全世界开放的 Web 服务器,但您也希望进行身份验证,以便只有特定用户组可以访问它。您可以使用一个包含两个容器的 Pod。
一个用于身份验证。它将在其容器镜像中指定类似 Apache 的内容,并将连接到外部世界。
一个接收来自身份验证容器的信息,并对其进行一些特殊处理(也许它运行一个 Python 进程)。
这很有用,因为它允许您对要运行的服务的组件进行分隔,这使得管理更容易,并使系统更加稳定。
有关 Pod 的更多信息,请参阅 Kubernetes 关于 Pod 的文档。
部署#
部署是 Kubernetes 上的一组 Pod。它是 Kubernetes 如何知道始终需要运行哪些容器以及哪些机器。例如,如果您有两个 Pod:一个用于执行上述身份验证,另一个用于管理数据库,您可以在部署中指定两者。
Kubernetes 将确保这两个 Pod 都处于活动状态,如果其中一个出现故障,它将尝试重新创建它。它通过不断检查 Pod 的当前状态,然后将其与部署的原始规范进行比较来实现。如果当前状态与部署规范之间存在差异,Kubernetes 将尝试进行更改,直到当前状态与规范匹配。
有关部署的更多信息,请参阅 Kubernetes 关于部署的文档。
注意
用户通常不会直接“创建”部署,而是从发送到 Kubernetes 的一组指令中生成它们。我们将在“Helm”部分介绍这一点。
服务#
服务仅仅是引用部署的稳定方式。Kubernetes 的宗旨是智能地处理动态且快速变化的计算环境。这意味着运行 Pod 的 VM 可能会发生变化,IP 地址也会不同,等等。但是,您不希望每次发生这种情况时都必须重新定位自己。Kubernetes 服务跟踪后端的所有这些更改,并提供一个单一地址来管理您的部署。
有关服务的更多信息,请参阅 Kubernetes 关于服务的文档。
命名空间#
最后,命名空间 定义了 Kubernetes 中的一组对象。它通常是我们迄今为止讨论过的组中最“高级”的组。例如,命名空间可以是使用 JupyterHub 运行的单个类。
有关命名空间的更多信息,请参阅 Kubernetes 关于命名空间的文档。
持久卷声明#
持久卷声明是一种无需绑定到特定计算机或机器即可获得持久存储的方式。Kubernetes 就是关于这种灵活性,这意味着我们不想仅仅因为我们的文件已经存在于特定操作系统上而锁定自己。持久卷声明通过了解如何将文件在磁盘类型之间进行转换(例如,AWS 与 Google 磁盘)来帮助解决这个问题。
有关持久卷声明的更多信息,请参阅 Kubernetes 关于持久卷的文档。
Helm#
Helm 是一种使用标准模板指定 Kubernetes 对象的方法。
图表#
Helm 控制 Kubernetes 的方式是使用结构化信息的模板,这些模板指定了一些计算需求。这些模板被称为“图表”或“Helm 图表”。它们包含 Kubernetes 生成所需的所有信息
部署对象
服务对象
部署的持久卷对象。
上述组件的集合
它们可以安装到命名空间中,这会导致 Kubernetes 开始将上述对象部署到该命名空间中。
图表既有名称也有版本,这意味着您可以轻松地更新它们并基于它们进行构建。有 社区维护的图表 可用,我们使用图表在本指南中安装和升级 JupyterHub。在我们的例子中,Helm 图表是一个名为 config.yaml
的文件。
版本#
版本基本上是插入特定命名空间的 Helm 图表的特定实例。如果您想升级您的 Kubernetes 部署(例如,通过更改每个用户应该获得的内存量),那么您可以更改 Helm 图表,然后将其重新部署到您的 Kubernetes 集群。这将生成一个新版本的版本。
JupyterHub#
JupyterHub 是一种利用上述组件来提供用户可以远程访问的计算环境的方法。它存在于两个 Kubernetes 部署中,即 Proxy 和 Hub,每个部署都包含一个 Pod。每个部署都完成一些任务,这些任务共同构成了 JupyterHub。最后,JupyterHub 的输出是一个用户 Pod,它指定单个用户将在其中操作的计算环境。因此,本质上,JupyterHub 是一个集合
包含 JupyterHub 机器的 Pod
一堆不断创建或销毁的用户 Pod。
下面我们将描述主要的 JupyterHub Pod。
代理 Pod#
这是面向用户的 Pod。它提供人们访问 JupyterHub 的 IP 地址。当新用户访问此 Pod 时,它将决定是否
将该用户发送到 Hub Pod,该 Pod 将为该用户创建一个容器,或者
如果该用户的容器已经存在,则直接将他们发送到该容器。
有关用户身份的信息存储在他们计算机上的 cookie 中。这就是代理 Pod 如何知道用户是否已经拥有正在运行的容器。
Hub Pod#
接收来自代理 Pod 的流量。它有 3 个主要运行进程
身份验证器,它可以验证用户的帐户。它还包含一个进程。
一个“KubeSpawner”,它与 Kubernetes API 交谈并告诉它为用户生成 Pod(如果不存在)。KubeSpawner 将告诉 Kubernetes 为新用户创建一个 Pod,然后它将告诉代理 Pod 用户的 Pod 已创建。
一个管理面板,其中包含有关谁创建了 Pod 以及集群上存在哪些使用情况的信息。