服务#

JupyterHub 服务(不要与 Kubernetes 的 Service 对象混淆)是与 JupyterHub API 交互的进程。nbgraderculling idle Notebooks(清理空闲的 Notebook)是生产环境中服务的例子,在 JupyterHub 示例仓库中也有一些“hello world”服务的最小化示例。

服务可以在 Hub 外部运行,这意味着它们的启动和停止独立于 Hub,并且必须自行管理 Hub 身份验证令牌等信息。另外,服务也可以由Hub 托管,即由 Hub 启动和停止该进程,并通过环境变量将关键信息传递给服务。

z2jh 中的 Hub 托管服务#

Hub 托管的服务将与 Hub 本身在同一个容器/Pod 中运行。首先,你需要将服务的相关文件安装或复制到你的 Hub 镜像中,这可以通过创建一个派生自 jupyterhub/k8s-hub 的自定义镜像,或者通过 hub.extraFiles 配置来实现。请记住,根据服务的不同,你的 Hub 容器可能需要安装 flask 或 fastapi 等依赖库。在这种情况下,你就需要一个自定义镜像。

除了服务的代码,你还需要修改 Hub 的 Kubernetes Service 对象以包含多个端口,并更新 Hub 的网络策略(Network Policy)。如果你想允许来自所有来源的访问,可以使用 hub.networkPolicy.allowedIngressPorts。否则,如果你想更精确地控制访问,可以使用 hub.networkPolicy.ingress

服务示例#

在下面的代码片段中,我使用了一个自定义镜像,它复制了应用程序代码并安装了 fastapi 服务示例中列出的依赖项。

# Dockerfile
# 3.1.0 is latest stable release at the time of this writing
# Find all tags in https://quay.io/repository/jupyterhub/k8s-hub?tab=tags
FROM quay.io/jupyterhub/k8s-hub:3.1.0

# Depending on version, the k8s-hub image may have installed
# pip packages as root, forcing you to install as root as well
USER root
COPY ./service-fastapi /usr/src/fastapi
RUN python3 -m pip install -r /usr/src/fastapi/requirements.txt

USER ${NB_USER}
# config.yaml

hub:
  image:
    name: myregistry/my-custom-hub-image
    tag: latest

  services:
    fastapi:
      url: http://hub:8181
      command:
        - /home/jovyan/.local/bin/uvicorn
        - app:app
        - --port
        - "8181"
        - --host
        - "0.0.0.0"
        - --app-dir
        - /usr/src/fastapi
      oauth_redirect_uri: https://jupyterhub.mycloud.com/services/fastapi/oauth_callback
      environment:
        PUBLIC_HOST: https://jupyterhub.mycloud.com

  networkPolicy:
    ingress:
      - ports:
          - port: 8181
        from:
          - podSelector:
              matchLabels:
                hub.jupyter.org/network-access-hub: "true"

  service:
    extraPorts:
      - port: 8181
        targetPort: 8181
        name: fastapi

# The proxy.chp.networkPolicy.egress configuration below is required if the
# service should be accessible for users. If it shouldn't be, you should instead
# set the chart configuration services.fastapi.display to false as otherwise
# JupyterHub will provide a broken link in the Services menu for users to go to
# /services/fastapi/.
proxy:
  chp:
    networkPolicy:
      egress:
        - to:
            - podSelector:
                matchLabels:
                  app.kubernetes.io/name: jupyterhub
                  app.kubernetes.io/component: hub
          ports:
            - port: 8181