From 787830900610f4e8113635a10c751d10f6ad7b9d Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Fri, 14 Aug 2020 21:16:08 -0500 Subject: [PATCH 01/15] DashHub helm chart --- chartpress.yaml | 4 + daskhub/.gitignore | 2 + daskhub/.helmignore | 23 +++ daskhub/Chart.yaml | 25 +++ daskhub/README.md | 177 ++++++++++++++++++++ daskhub/templates/NOTES.txt | 22 +++ daskhub/templates/dask-kubernetes-rbac.yaml | 52 ++++++ daskhub/templates/singleuser-configmap.yaml | 7 + daskhub/values.yaml | 32 ++++ 9 files changed, 344 insertions(+) create mode 100644 daskhub/.gitignore create mode 100644 daskhub/.helmignore create mode 100644 daskhub/Chart.yaml create mode 100644 daskhub/README.md create mode 100644 daskhub/templates/NOTES.txt create mode 100644 daskhub/templates/dask-kubernetes-rbac.yaml create mode 100644 daskhub/templates/singleuser-configmap.yaml create mode 100644 daskhub/values.yaml diff --git a/chartpress.yaml b/chartpress.yaml index 880e585..8767b4b 100644 --- a/chartpress.yaml +++ b/chartpress.yaml @@ -3,3 +3,7 @@ charts: repo: git: dask/helm-chart published: https://helm.dask.org + - name: daskhub + repo: + git: dask/helm-chart + published: https://helm.dask.org diff --git a/daskhub/.gitignore b/daskhub/.gitignore new file mode 100644 index 0000000..d6db12f --- /dev/null +++ b/daskhub/.gitignore @@ -0,0 +1,2 @@ +*.lock +charts diff --git a/daskhub/.helmignore b/daskhub/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/daskhub/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/daskhub/Chart.yaml b/daskhub/Chart.yaml new file mode 100644 index 0000000..e453622 --- /dev/null +++ b/daskhub/Chart.yaml @@ -0,0 +1,25 @@ +apiVersion: v2 +name: daskhub +version: 0.0.1-set.by.chartpress +description: Multi-user JupyterHub and Dask deployment. +dependencies: + - name: jupyterhub + version: "0.9.1" + repository: 'https://jupyterhub.github.io/helm-chart/' + import-values: + - child: rbac + parent: rbac + - name: dask-gateway + version: "0.8.0" + repository: 'https://dask.org/dask-gateway-helm-repo/' +maintainers: + - name: Jacob Tomlinson (Met Office) + email: jacob.tomlinson@informaticslab.co.uk + - name: Joe Hamman (NCAR) + email: jhamman@ucar.edu + - name: Guillaume Eynard-Bontemps (CNES) + email: guillaume.eynard-bontemps@cnes.fr + - name: Erik Sundell + email: erik.i.sundell@gmail.com + - name: Tom Augspurger + email: tom.w.augspurger@gmail.com diff --git a/daskhub/README.md b/daskhub/README.md new file mode 100644 index 0000000..327bf9e --- /dev/null +++ b/daskhub/README.md @@ -0,0 +1,177 @@ +# DaskHub + +This chart provides a multi-user, Dask-Gateway enabled JupyterHub. +It combines the [JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) +and [Dask Gateway](https://gateway.dask.org/) helm charts. + +For single users, a simpler setup is supported by the `dask` helm chart. + +## Chart Details + +This chart will deploy the following + +- A standard Dask Gateway deployment using the Dask Gateway helm chart + configured to use JupyterHub for authentication. +- A standard JupyterHub deployment using the JupyterHub helm chart. + +## Prepare Configuration File + +In this step, we'll prepare a YAML configuration file with the fields +required by the DaskHub helm chart. It will contain some secret +keys, which should not be checked into version control in plaintext. + +We need two random hex strings that will be used as keys, one for +JupyterHub and one for Dask Gateway. + + +Run the following command, and copy the output. This is our `token-1`. + +```console +openssl rand -hex 32 +``` + +Run command again and copy the output. This is our `token-2`. + +```console +openssl rand -hex 32 +``` + +Now substitute those two values for `` and `` below. +Note that `` is used twice, once for `jupyterhub.hub.services.dask-gateway.apiToken`, and a second time for `dask-gateway.gateway.auth.jupyterhub.apiToken`. + + +```yaml +# secrets.yaml +jupyterhub: + proxy: + secretToken: "" + hub: + services: + dask-gateway: + apiToken: "" + +dask-gateway: + gateway: + auth: + jupyterhub: + apiToken: "" +``` + +## Install Dask Hub + +This example installs into the namespace `dhub`. Make sure you're +in the same directory as the `secrets.yaml` file. + +```console +$ helm upgrade --wait --install --render-subchart-notes \ + dhub dask/daskhub \ + --namespace=dhub \ + --version=0.0.1 \ + --values=secrets.yaml +``` + +The output explains how to find the IPs for your JupyterHub and Dask Gateway. + +```console +$ kubectl -n dhub get service +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +api-us-central1b-dhub-dask-gateway ClusterIP 10.43.253.126 8000/TCP 25m +dask-e10f1f0179784a60b0e4c5ba09c1ed44 ClusterIP None 8786/TCP,8787/TCP,8788/TCP 100s +hub ClusterIP 10.43.250.8 8081/TCP 25m +proxy-api ClusterIP 10.43.248.47 8001/TCP 25m +proxy-public LoadBalancer 10.43.244.163 35.224.253.72 443:31356/TCP,80:32352/TCP 25m +traefik-us-central1b-dhub-dask-gateway LoadBalancer 10.43.244.244 35.223.8.79 80:31076/TCP 25m +``` + +JupyterHub is available at the `proxy-public` external ip (35.224.253.72 in this example). +Dask Gateawy is available at `traefik-us-central1b-dhub-dask-gateway` (35.223.8.79). + +## Creating a Dask Cluster + +To create a Dask cluster, connect to the Dask Gateway + +```python +>>> from dask_gateway import Gateway +>>> gateway = dask_gateway.Gateway( +... address="http://35.223.8.79", # traefik-us-central1b-dhub-dask-gateway +... ) +>>> gateway.list_clusters() +[] +``` + +Once connected to the gateway, create a cluster and connect a client. + +```python +>>> cluster = gateway.new_cluster() +>>> client = cluster.get_client() +``` + +## Configuring JupyterHub + +You might want to configure the JupyterHub user environment to remove the need +for users to specify the address and authentication type for Dask Gateawy. +This can be done by setting the following and deploying with helm. + +```yaml +# values.yaml +jupyterhub: + singleuser: + extraEnv: + DASK_GATEWAY__ADDRESS: "http://traefik-dhub-dask-gateway" +``` + +Make sure to change the value to match the release name (we used `dhub`). + +With this, users should be able to connect to the Gateway by simply calling +`gateway = Gateway()`, and create clusters with `cluster = dask_gateway.GatewayCluster()`. + +## Matching the user environment + +Dask Clients will be running the JupyterHub's singleuser environment. To ensure +that the same environment is used for the scheduler and workers, you can provide +it as a Gateway option. + +```yaml +# values.yaml +jupyterhub: + singleuser: + extraEnv: + DASK_GATEWAY__CLUSTER__OPTIONS__IMAGE: '{JUPYTER_IMAGE_SPEC}' + +dask-gateway: + extraConfig: + optionHandler: | + from dask_gateway_server.options import Options, Integer, Float, String + def option_handler(options): + if ":" not in options.image: + raise ValueError("When specifying an image you must also provide a tag") + return { + "image": options.image, + } + c.Backend.cluster_options = Options( + String("image", default="pangeo/base-notebook:2020.07.28", label="Image"), + handler=option_handler, + ) +``` + +The user environment will need to include `dask-gateway`. + +## Using dask-kubernetes instead of Dask Gateway + +Users who don't need Dask Gateway can use dask-kubernetes to manage creating Dask Clusters. To use dask-kubernetes, you should set + +``` +# config.yaml +daskhub: + jupyterhub: + singleuser: + servieAccountName: daskkubernetes + + dask-gateway: + enabled: false + + dask-kubernetes: + enabled: true +``` + +When deploying, helm will create a Kubernetes ServiceAccount, Role, and RoleBinding. This ensures that the pods serving JupyterHub singleusers have the eleveated permissions for starting and stopping pods. diff --git a/daskhub/templates/NOTES.txt b/daskhub/templates/NOTES.txt new file mode 100644 index 0000000..d697fee --- /dev/null +++ b/daskhub/templates/NOTES.txt @@ -0,0 +1,22 @@ +DaskHub +------- + +Thank you for installing DaskHub, a multiuser, Dask-enabled JupyterHub! + +Your release is named {{.Release.Name}} and installed into the namespace {{.Release.Namespace}}. + + +Jupyter Hub +----------- + +You can find if the hub and proxy is ready by doing: + + kubectl --namespace={{.Release.Namespace}} get pod + +and watching for both those pods to be in status 'Ready'. + +You can find the public IP of the JupyterHub by doing: + + kubectl --namespace={{.Release.Namespace}} get svc proxy-public + +It might take a few minutes for it to appear! diff --git a/daskhub/templates/dask-kubernetes-rbac.yaml b/daskhub/templates/dask-kubernetes-rbac.yaml new file mode 100644 index 0000000..33f76c6 --- /dev/null +++ b/daskhub/templates/dask-kubernetes-rbac.yaml @@ -0,0 +1,52 @@ +{{- if and (index .Values "dask-kubernetes" "enabled") .Values.rbac.enabled -}} +kind: ServiceAccount +apiVersion: v1 +metadata: + name: daskkubernetes + namespace: {{ .Release.Namespace }} + labels: + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + component: daskkubernetes + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + +--- + +kind: Role +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: daskkubernetes + namespace: {{ .Release.Namespace }} + labels: + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + component: daskkubernetes + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} +rules: +- apiGroups: [""] # "" indicates the core API group + resources: ["pods", "services"] + verbs: ["get", "list", "watch", "create", "delete"] +- apiGroups: [""] # "" indicates the core API group + resources: ["pods/log"] + verbs: ["get", "list"] + +--- + +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: daskkubernetes + namespace: {{ .Release.Namespace }} + labels: + chart: {{ .Chart.Name }}-{{ .Chart.Version }} + component: daskkubernetes + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} +subjects: +- kind: ServiceAccount + name: daskkubernetes +roleRef: + kind: Role + name: daskkubernetes + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/daskhub/templates/singleuser-configmap.yaml b/daskhub/templates/singleuser-configmap.yaml new file mode 100644 index 0000000..d642cf7 --- /dev/null +++ b/daskhub/templates/singleuser-configmap.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: daskhub-config +data: + DASK_GATEWAY__AUTH__TYPE: "jupyterhub" + DASK_GATEWAY__ADDRESS: "traefik-{{ .Release.Name }}-dask-gateway" diff --git a/daskhub/values.yaml b/daskhub/values.yaml new file mode 100644 index 0000000..b5cc626 --- /dev/null +++ b/daskhub/values.yaml @@ -0,0 +1,32 @@ +# DaskHub configuration values +# ---------------------------- +# Create and use roles and service accounts on an RBAC enabled cluster. +rbac: + enabled: true + +jupyterhub: + # JupyterHub configuration goes here. + # See https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/master/jupyterhub/values.yaml + singleuser: + image: + name: pangeo/base-notebook + tag: 2020.07.28 + defaultUrl: "/lab" + extraEnv: + DASK_GATEWAY__AUTH__TYPE: "jupyterhub" + +dask-gateway: + # Enabling dask-gateway will install Dask Gateway as a dependency. + enabled: true + # Futher Dask Gateway configuration goes here + # See https://github.com/dask/dask-gateway/blob/master/resources/helm/dask-gateway/values.yaml + gateway: + auth: + type: jupyterhub + +dask-kubernetes: + # Use dask-kubernetes, rather than Dask Gateway, for creating Dask Clusters. + # Enabling this also requires + # 1. Setting `jupyterhub.singleuser.serviceAccountName: daskkubernetes`. + # 2. Ensuring that `dask-kubernetes` is in your singleuser environment. + enabled: false From 5cd660cda68b27f1524e198934dd32df9a77c97d Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Tue, 18 Aug 2020 14:53:45 -0500 Subject: [PATCH 02/15] Update Jacob's email --- daskhub/Chart.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daskhub/Chart.yaml b/daskhub/Chart.yaml index e453622..ec50636 100644 --- a/daskhub/Chart.yaml +++ b/daskhub/Chart.yaml @@ -13,8 +13,8 @@ dependencies: version: "0.8.0" repository: 'https://dask.org/dask-gateway-helm-repo/' maintainers: - - name: Jacob Tomlinson (Met Office) - email: jacob.tomlinson@informaticslab.co.uk + - name: Jacob Tomlinson (Nvidia) + email: jtomlinson@nvidia.com - name: Joe Hamman (NCAR) email: jhamman@ucar.edu - name: Guillaume Eynard-Bontemps (CNES) From 21d8ebba91583fd20a3edc1c4f4a42e0687ef261 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Thu, 20 Aug 2020 14:45:27 -0500 Subject: [PATCH 03/15] wip --- daskhub/README.md | 32 +++++++++++--- daskhub/templates/daskhub-configmap.yaml | 15 +++++++ daskhub/templates/singleuser-configmap.yaml | 7 --- daskhub/values.yaml | 49 +++++++++++++++++++++ 4 files changed, 90 insertions(+), 13 deletions(-) create mode 100644 daskhub/templates/daskhub-configmap.yaml delete mode 100644 daskhub/templates/singleuser-configmap.yaml diff --git a/daskhub/README.md b/daskhub/README.md index 327bf9e..5b4fa85 100644 --- a/daskhub/README.md +++ b/daskhub/README.md @@ -10,9 +10,11 @@ For single users, a simpler setup is supported by the `dask` helm chart. This chart will deploy the following -- A standard Dask Gateway deployment using the Dask Gateway helm chart +- A standard Dask Gateway deployment using the Dask Gateway helm chart, configured to use JupyterHub for authentication. -- A standard JupyterHub deployment using the JupyterHub helm chart. +- A standard JupyterHub deployment using the JupyterHub helm chart, + configured proxy Dask Gateway requests and set Dask Gateway-related + environment variables. ## Prepare Configuration File @@ -23,17 +25,16 @@ keys, which should not be checked into version control in plaintext. We need two random hex strings that will be used as keys, one for JupyterHub and one for Dask Gateway. - Run the following command, and copy the output. This is our `token-1`. ```console -openssl rand -hex 32 +openssl rand -hex 32 # generate token-1 ``` Run command again and copy the output. This is our `token-2`. ```console -openssl rand -hex 32 +openssl rand -hex 32 # generate token-2 ``` Now substitute those two values for `` and `` below. @@ -41,7 +42,7 @@ Note that `` is used twice, once for `jupyterhub.hub.services.dask-gate ```yaml -# secrets.yaml +# file: secrets.yaml jupyterhub: proxy: secretToken: "" @@ -57,6 +58,25 @@ dask-gateway: apiToken: "" ``` +If you wish to access the Dask Dashboard (and why wouldn't you?), you'll also +need to specify the hostname users will access your JupyterHub at. If you don't +have that, then specify the IP address. This will let users access the dashboard +from their browser. + +```yaml +# file: config.yaml +jupyterhub: + proxy: + hosts: + - "" + service: + loadBalancerIP: "" +``` + +If you don't have an IP for your JupyterHub yet (if, say, you're letting +kubernetes assign it for you), then you may need to leave this blank and +do a secondary `helm install`. + ## Install Dask Hub This example installs into the namespace `dhub`. Make sure you're diff --git a/daskhub/templates/daskhub-configmap.yaml b/daskhub/templates/daskhub-configmap.yaml new file mode 100644 index 0000000..89eaadb --- /dev/null +++ b/daskhub/templates/daskhub-configmap.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: daskhub-config +data: + {{ if .Values.jupyterhub.proxy.https.enabled }} + DASK_GATEWAY__ADDRESS: "http://{{ .Values.jupyterhub.proxy.https.hosts | first }}/services/dask-gateway/" + {{ else if .Values.jupyterhub.proyx.service.loadBalancerIP }} + {{ else if .Values.jupyterhub.proyx.service.loadBalancerIP }} + DASK_GATEWAY__ADDRESS: "http://{{ .Values.jupyterhub.proxy.service.loadBalancerIP }}/services/dask-gateway/" + {{ else }} + DASK_GATEWAY__ADDRESS: "http://traefik-{{ .Release.Name }}-dask-gateway.{{ .Release.Namespace }}" + {{ end }} + DASK_GATEWAY__PROXY_ADDRESS: "gateway://traefik-{{ .Release.Name }}-dask-gateway.{{ .Release.Namespace }}:80" + DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL: "http://traefik-{{ .Release.Name }}-dask-gateway.{{ .Release.Namespace }}" diff --git a/daskhub/templates/singleuser-configmap.yaml b/daskhub/templates/singleuser-configmap.yaml deleted file mode 100644 index d642cf7..0000000 --- a/daskhub/templates/singleuser-configmap.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: daskhub-config -data: - DASK_GATEWAY__AUTH__TYPE: "jupyterhub" - DASK_GATEWAY__ADDRESS: "traefik-{{ .Release.Name }}-dask-gateway" diff --git a/daskhub/values.yaml b/daskhub/values.yaml index b5cc626..4cbc360 100644 --- a/daskhub/values.yaml +++ b/daskhub/values.yaml @@ -7,7 +7,49 @@ rbac: jupyterhub: # JupyterHub configuration goes here. # See https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/master/jupyterhub/values.yaml + proxy: + service: + loadBalancerIP: "34.66.194.106" + hub: + # These environment variables are declared in templates/daskhub-configmap.yaml + # They are eventually set in the singleuser environment. + extraEnv: + - name: DASK_GATEWAY__ADDRESS + valueFrom: + configMapKeyRef: + name: daskhub-config + key: DASK_GATEWAY__ADDRESS + - name: DASK_GATEWAY__PROXY_ADDRESS + valueFrom: + configMapKeyRef: + name: daskhub-config + key: DASK_GATEWAY__PROXY_ADDRESS + - name: DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL + valueFrom: + configMapKeyRef: + name: daskhub-config + key: DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL + + extraConfig: + 00-add-dask-gateway-values: | + import os + + # Adds a few variables to singluser.ExtraEnv which depend on the release name. + for key in ["DASK_GATEWAY__ADDRESS", "DASK_GATEWAY__PROXY_ADDRESS"]: + c.KubeSpawner.environment[key] = os.environ[key] + + # Adds Dask Gateway as a JupyterHub service to make the gateway available at + # {HUB_URL}/services/dask-gateway + for service in c.JupyterHub.services: + if service["name"] == "dask-gateway": + print("Adding dask-gateway service URL") + service["url"] = os.environ["DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL"] + break + else: + print("dask-gateway service not found. Did you set jupyterhub.hub.services.dask-gateway.apiToken?") + singleuser: + # The singleuser image should contain Dask Gateway for users to start Dask clusters. image: name: pangeo/base-notebook tag: 2020.07.28 @@ -21,8 +63,15 @@ dask-gateway: # Futher Dask Gateway configuration goes here # See https://github.com/dask/dask-gateway/blob/master/resources/helm/dask-gateway/values.yaml gateway: + # Users connect to the Gateway through the JupyterHub service. + prefix: "/services/dask-gateway" auth: type: jupyterhub + traefik: + service: + # We are using Dask Gateway behind a JupyterHub service. To access Dask Gateway + # from outside the JupyterHub, this must be changed to a LoadBalancer. + type: ClusterIP dask-kubernetes: # Use dask-kubernetes, rather than Dask Gateway, for creating Dask Clusters. From f0ef24fe6bb51f4be25f73fb809d5a7296ff6bb5 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Fri, 21 Aug 2020 15:17:59 -0500 Subject: [PATCH 04/15] updated --- daskhub/README.md | 2 +- daskhub/templates/daskhub-configmap.yaml | 16 ++++++++-------- daskhub/values.yaml | 16 ++++++++++------ 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/daskhub/README.md b/daskhub/README.md index 5b4fa85..ad7f485 100644 --- a/daskhub/README.md +++ b/daskhub/README.md @@ -77,7 +77,7 @@ If you don't have an IP for your JupyterHub yet (if, say, you're letting kubernetes assign it for you), then you may need to leave this blank and do a secondary `helm install`. -## Install Dask Hub +## Install DaskHub This example installs into the namespace `dhub`. Make sure you're in the same directory as the `secrets.yaml` file. diff --git a/daskhub/templates/daskhub-configmap.yaml b/daskhub/templates/daskhub-configmap.yaml index 89eaadb..64d5414 100644 --- a/daskhub/templates/daskhub-configmap.yaml +++ b/daskhub/templates/daskhub-configmap.yaml @@ -3,13 +3,13 @@ kind: ConfigMap metadata: name: daskhub-config data: - {{ if .Values.jupyterhub.proxy.https.enabled }} - DASK_GATEWAY__ADDRESS: "http://{{ .Values.jupyterhub.proxy.https.hosts | first }}/services/dask-gateway/" - {{ else if .Values.jupyterhub.proyx.service.loadBalancerIP }} - {{ else if .Values.jupyterhub.proyx.service.loadBalancerIP }} - DASK_GATEWAY__ADDRESS: "http://{{ .Values.jupyterhub.proxy.service.loadBalancerIP }}/services/dask-gateway/" - {{ else }} - DASK_GATEWAY__ADDRESS: "http://traefik-{{ .Release.Name }}-dask-gateway.{{ .Release.Namespace }}" - {{ end }} DASK_GATEWAY__PROXY_ADDRESS: "gateway://traefik-{{ .Release.Name }}-dask-gateway.{{ .Release.Namespace }}:80" DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL: "http://traefik-{{ .Release.Name }}-dask-gateway.{{ .Release.Namespace }}" + # Try to detect the gateway address through a few means. + {{ if .Values.jupyterhub.proxy.https.hosts }} + DASK_GATEWAY__ADDRESS: "https://{{ .Values.jupyterhub.proxy.https.hosts | first }}/services/dask-gateway" + {{ else if .Values.jupyterhub.proxy.service.loadBalancerIP }} + DASK_GATEWAY__ADDRESS: "http://{{ .Values.jupyterhub.proxy.service.loadBalancerIP }}/services/dask-gateway" + {{ else }} + DASK_GATEWAY__ADDRESS: "http://proxy-public/services/dask-gateway" + {{ end }} diff --git a/daskhub/values.yaml b/daskhub/values.yaml index 4cbc360..ce854aa 100644 --- a/daskhub/values.yaml +++ b/daskhub/values.yaml @@ -7,9 +7,6 @@ rbac: jupyterhub: # JupyterHub configuration goes here. # See https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/master/jupyterhub/values.yaml - proxy: - service: - loadBalancerIP: "34.66.194.106" hub: # These environment variables are declared in templates/daskhub-configmap.yaml # They are eventually set in the singleuser environment. @@ -32,6 +29,12 @@ jupyterhub: extraConfig: 00-add-dask-gateway-values: | + # We need to set two a few things + # On the Hub: + # - Add the Gateway URL to the service. + # On the singleuser + # - DASK_GATEWAY_ADDRESS: {{ HUB_URL }}/servcies/dask-gateway/ + # - DASK_GATEWAY__PROXY_ADDRESS: gateway://traefik-{{ RELEASE_NAME }}-dask-gateway.{{ NAMESPACE }} import os # Adds a few variables to singluser.ExtraEnv which depend on the release name. @@ -42,9 +45,10 @@ jupyterhub: # {HUB_URL}/services/dask-gateway for service in c.JupyterHub.services: if service["name"] == "dask-gateway": - print("Adding dask-gateway service URL") - service["url"] = os.environ["DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL"] - break + if not service.get("url", None): + print("Adding dask-gateway service URL") + service["url"] = os.environ["DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL"] + break else: print("dask-gateway service not found. Did you set jupyterhub.hub.services.dask-gateway.apiToken?") From 679ec6f7a5c1f58e8d2dc0207a42a7a5a7ab5940 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Fri, 21 Aug 2020 15:24:46 -0500 Subject: [PATCH 05/15] updates --- daskhub/README.md | 73 ++++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 48 deletions(-) diff --git a/daskhub/README.md b/daskhub/README.md index ad7f485..a4635d3 100644 --- a/daskhub/README.md +++ b/daskhub/README.md @@ -58,24 +58,23 @@ dask-gateway: apiToken: "" ``` -If you wish to access the Dask Dashboard (and why wouldn't you?), you'll also -need to specify the hostname users will access your JupyterHub at. If you don't -have that, then specify the IP address. This will let users access the dashboard -from their browser. - +If your users wish to access Dask dashboards, you'll also need to specify the +public hostname or IP address of the hub . + ```yaml # file: config.yaml jupyterhub: proxy: - hosts: - - "" + https: + hosts: + - "daskhub.example.com" service: - loadBalancerIP: "" + loadBalancerIP: "35.202.158.223" ``` If you don't have an IP for your JupyterHub yet (if, say, you're letting -kubernetes assign it for you), then you may need to leave this blank and -do a secondary `helm install`. +Kubernetes assign it for you), then you may need to leave this blank and +do a secondary `helm install` with the value set once it's known. ## Install DaskHub @@ -93,18 +92,22 @@ $ helm upgrade --wait --install --render-subchart-notes \ The output explains how to find the IPs for your JupyterHub and Dask Gateway. ```console -$ kubectl -n dhub get service -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -api-us-central1b-dhub-dask-gateway ClusterIP 10.43.253.126 8000/TCP 25m -dask-e10f1f0179784a60b0e4c5ba09c1ed44 ClusterIP None 8786/TCP,8787/TCP,8788/TCP 100s -hub ClusterIP 10.43.250.8 8081/TCP 25m -proxy-api ClusterIP 10.43.248.47 8001/TCP 25m -proxy-public LoadBalancer 10.43.244.163 35.224.253.72 443:31356/TCP,80:32352/TCP 25m -traefik-us-central1b-dhub-dask-gateway LoadBalancer 10.43.244.244 35.223.8.79 80:31076/TCP 25m +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +proxy-public LoadBalancer 10.43.249.239 35.202.158.223 443:31587/TCP,80:30500/TCP 2m40s ``` -JupyterHub is available at the `proxy-public` external ip (35.224.253.72 in this example). -Dask Gateawy is available at `traefik-us-central1b-dhub-dask-gateway` (35.223.8.79). +JupyterHub is available at the `proxy-public` external ip (35.202.158.223 in this example). +Note, that this value needs to be set as the `jupyterhub.proxy.service.loadBalancerIP`. + +```yaml +# file: config.yaml +jupyterhub: + proxy: + service: + loadBalancerIP: "35.202.158.223" +``` + +Be sure to (re)deploy helm with this value set to enable the Dask dashboard. ## Creating a Dask Cluster @@ -112,9 +115,7 @@ To create a Dask cluster, connect to the Dask Gateway ```python >>> from dask_gateway import Gateway ->>> gateway = dask_gateway.Gateway( -... address="http://35.223.8.79", # traefik-us-central1b-dhub-dask-gateway -... ) +>>> gateway = dask_gateway.Gateway() >>> gateway.list_clusters() [] ``` @@ -126,25 +127,6 @@ Once connected to the gateway, create a cluster and connect a client. >>> client = cluster.get_client() ``` -## Configuring JupyterHub - -You might want to configure the JupyterHub user environment to remove the need -for users to specify the address and authentication type for Dask Gateawy. -This can be done by setting the following and deploying with helm. - -```yaml -# values.yaml -jupyterhub: - singleuser: - extraEnv: - DASK_GATEWAY__ADDRESS: "http://traefik-dhub-dask-gateway" -``` - -Make sure to change the value to match the release name (we used `dhub`). - -With this, users should be able to connect to the Gateway by simply calling -`gateway = Gateway()`, and create clusters with `cluster = dask_gateway.GatewayCluster()`. - ## Matching the user environment Dask Clients will be running the JupyterHub's singleuser environment. To ensure @@ -152,12 +134,7 @@ that the same environment is used for the scheduler and workers, you can provide it as a Gateway option. ```yaml -# values.yaml -jupyterhub: - singleuser: - extraEnv: - DASK_GATEWAY__CLUSTER__OPTIONS__IMAGE: '{JUPYTER_IMAGE_SPEC}' - +# config.yaml dask-gateway: extraConfig: optionHandler: | From f56c785dae520dd4305c42647517025f883fffac Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 24 Aug 2020 14:32:25 -0500 Subject: [PATCH 06/15] public address --- daskhub/README.md | 13 +++++++++++-- daskhub/templates/daskhub-configmap.yaml | 13 ++++++++----- daskhub/values.yaml | 15 ++++++++++++++- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/daskhub/README.md b/daskhub/README.md index a4635d3..048c67b 100644 --- a/daskhub/README.md +++ b/daskhub/README.md @@ -63,6 +63,8 @@ public hostname or IP address of the hub . ```yaml # file: config.yaml +jupyterhubPublicHost: "https://daskhub.example.com" + jupyterhub: proxy: https: @@ -71,6 +73,10 @@ jupyterhub: service: loadBalancerIP: "35.202.158.223" ``` + +Notice that we tell both `daskhub` and `jupyterhub` the public host for the +JupyterHub. If you just specify `jupyterhub.proxy.https.hosts`, then daskhub +will *try* to guess the URL for you, but we might get it wrong. If you don't have an IP for your JupyterHub yet (if, say, you're letting Kubernetes assign it for you), then you may need to leave this blank and @@ -86,7 +92,8 @@ $ helm upgrade --wait --install --render-subchart-notes \ dhub dask/daskhub \ --namespace=dhub \ --version=0.0.1 \ - --values=secrets.yaml + --values=secrets.yaml \ + --values=config.yaml ``` The output explains how to find the IPs for your JupyterHub and Dask Gateway. @@ -101,13 +108,15 @@ Note, that this value needs to be set as the `jupyterhub.proxy.service.loadBalan ```yaml # file: config.yaml +jupyterhubPublicHost: "http://35.202.158.223" + jupyterhub: proxy: service: loadBalancerIP: "35.202.158.223" ``` -Be sure to (re)deploy helm with this value set to enable the Dask dashboard. +Be sure to (re)deploy with helm with this value set to enable the Dask dashboard. ## Creating a Dask Cluster diff --git a/daskhub/templates/daskhub-configmap.yaml b/daskhub/templates/daskhub-configmap.yaml index 64d5414..ca68b3f 100644 --- a/daskhub/templates/daskhub-configmap.yaml +++ b/daskhub/templates/daskhub-configmap.yaml @@ -3,13 +3,16 @@ kind: ConfigMap metadata: name: daskhub-config data: + DASK_GATEWAY__ADDRESS: "http://proxy-public/services/dask-gateway" DASK_GATEWAY__PROXY_ADDRESS: "gateway://traefik-{{ .Release.Name }}-dask-gateway.{{ .Release.Namespace }}:80" DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL: "http://traefik-{{ .Release.Name }}-dask-gateway.{{ .Release.Namespace }}" - # Try to detect the gateway address through a few means. - {{ if .Values.jupyterhub.proxy.https.hosts }} - DASK_GATEWAY__ADDRESS: "https://{{ .Values.jupyterhub.proxy.https.hosts | first }}/services/dask-gateway" + # Try to detect the gateway public address through a few means. + {{ if .Values.jupyterhubPublicHost }} + DASK_GATEWAY__PUBLIC_ADDRESS: "{{ .Values.jupyterhubPublicHost }}/services/dask-gateway/" + {{ else if .Values.jupyterhub.proxy.https.hosts }} + DASK_GATEWAY__PUBLIC_ADDRESS: "https://{{ .Values.jupyterhub.proxy.https.hosts | first }}/services/dask-gateway/" {{ else if .Values.jupyterhub.proxy.service.loadBalancerIP }} - DASK_GATEWAY__ADDRESS: "http://{{ .Values.jupyterhub.proxy.service.loadBalancerIP }}/services/dask-gateway" + DASK_GATEWAY__PUBLIC_ADDRESS: "http://{{ .Values.jupyterhub.proxy.service.loadBalancerIP }}/services/dask-gateway/" {{ else }} - DASK_GATEWAY__ADDRESS: "http://proxy-public/services/dask-gateway" + DASK_GATEWAY__PUBLIC_ADDRESS: "" {{ end }} diff --git a/daskhub/values.yaml b/daskhub/values.yaml index ce854aa..73ed48c 100644 --- a/daskhub/values.yaml +++ b/daskhub/values.yaml @@ -4,6 +4,13 @@ rbac: enabled: true +# The public URL (including protocol) for your JupyterHub deployment. +# If set, this provides a simple way to set the Dask Gateway public +# address for users to access their Dask dashboards. If not set, +# we'll try to guess it. +# example: https://daskhub.pangeo.io +jupyterhubPublicHost: nil + jupyterhub: # JupyterHub configuration goes here. # See https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/master/jupyterhub/values.yaml @@ -21,6 +28,11 @@ jupyterhub: configMapKeyRef: name: daskhub-config key: DASK_GATEWAY__PROXY_ADDRESS + - name: DASK_GATEWAY__PUBLIC_ADDRESS + valueFrom: + configMapKeyRef: + name: daskhub-config + key: DASK_GATEWAY__PUBLIC_ADDRESS - name: DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL valueFrom: configMapKeyRef: @@ -38,7 +50,8 @@ jupyterhub: import os # Adds a few variables to singluser.ExtraEnv which depend on the release name. - for key in ["DASK_GATEWAY__ADDRESS", "DASK_GATEWAY__PROXY_ADDRESS"]: + for key in ["DASK_GATEWAY__ADDRESS", "DASK_GATEWAY__PROXY_ADDRESS", + "DASK_GATEWAY__PUBLIC_ADDRESS"]: c.KubeSpawner.environment[key] = os.environ[key] # Adds Dask Gateway as a JupyterHub service to make the gateway available at From 0efaf331b7b8561ce73c1b9eb6f3911872a5ab03 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 24 Aug 2020 14:49:26 -0500 Subject: [PATCH 07/15] add frigate --- README.md | 32 +++++++- daskhub/.frigate | 193 ++++++++++++++++++++++++++++++++++++++++++++++ daskhub/README.md | 32 +++++++- 3 files changed, 255 insertions(+), 2 deletions(-) mode change 120000 => 100644 README.md create mode 100644 daskhub/.frigate diff --git a/README.md b/README.md deleted file mode 120000 index bb1d736..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -dask/README.md \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..06760f8 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +Dask Helm Charts +================ + +This repository contains Dask's two helm charts. + +- [dask](./dask/README.md): Install Dask on Kubernetes for a single user with Jupyter and dask-kubernetes. +- [daskhub](./daskhub/README.md): Install Dask on Kubernetes for multiple users with JupyterHub and Dask Gateway. + +## Quickstart -- singleuser + +Users deploying Dask for a single user should use the `dask/dask` helm chart. + +``` +helm repo add dask https://helm.dask.org/ +helm repo update +helm install --name my-release dask/dask +``` + +See [dask](./dask/README.md) for more. + +## Quickstart -- multiuser + +Users deploying Dask for multiple users should use the `dask/daskhub` helm chart. + +``` +helm repo add dask https://helm.dask.org/ +helm repo update +helm install --name my-release dask/daskhub +``` + +See [daskhub](./daskhub/README.md) for more. diff --git a/daskhub/.frigate b/daskhub/.frigate new file mode 100644 index 0000000..6368468 --- /dev/null +++ b/daskhub/.frigate @@ -0,0 +1,193 @@ +{% extends "markdown.jinja2" %} + +{% block description -%} +[![Travis Build Status](https://travis-ci.com/dask/helm-chart.svg?branch=master)](https://travis-ci.com/dask/helm-chart) +[![Chart version](https://img.shields.io/badge/dynamic/yaml?url=https://helm.dask.org/index.yaml&label=chart&query=$.entries.daskhub[:1].version&color=277A9F)](https://helm.dask.org/) +[![Dask version](https://img.shields.io/badge/dynamic/yaml?url=https://helm.dask.org/index.yaml&label=Dask&query=$.entries.daskhub[:1].appVersion&color=D67548)](https://helm.dask.org/) + +This chart provides a multi-user, Dask-Gateway enabled JupyterHub. +It combines the [JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) +and [Dask Gateway](https://gateway.dask.org/) helm charts. + +For single users, a simpler setup is supported by the `dask` helm chart. + +## Chart Details + +This chart will deploy the following + +- A standard Dask Gateway deployment using the Dask Gateway helm chart, + configured to use JupyterHub for authentication. +- A standard JupyterHub deployment using the JupyterHub helm chart, + configured proxy Dask Gateway requests and set Dask Gateway-related + environment variables. + +## Prepare Configuration File + +In this step, we'll prepare a YAML configuration file with the fields +required by the DaskHub helm chart. It will contain some secret +keys, which should not be checked into version control in plaintext. + +We need two random hex strings that will be used as keys, one for +JupyterHub and one for Dask Gateway. + +Run the following command, and copy the output. This is our `token-1`. + +```console +openssl rand -hex 32 # generate token-1 +``` + +Run command again and copy the output. This is our `token-2`. + +```console +openssl rand -hex 32 # generate token-2 +``` + +Now substitute those two values for `` and `` below. +Note that `` is used twice, once for `jupyterhub.hub.services.dask-gateway.apiToken`, and a second time for `dask-gateway.gateway.auth.jupyterhub.apiToken`. + + +```yaml +# file: secrets.yaml +jupyterhub: + proxy: + secretToken: "" + hub: + services: + dask-gateway: + apiToken: "" + +dask-gateway: + gateway: + auth: + jupyterhub: + apiToken: "" +``` + +If your users wish to access Dask dashboards, you'll also need to specify the +public hostname or IP address of the hub . + +```yaml +# file: config.yaml +jupyterhubPublicHost: "https://daskhub.example.com" + +jupyterhub: + proxy: + https: + hosts: + - "daskhub.example.com" + service: + loadBalancerIP: "35.202.158.223" +``` + +Notice that we tell both `daskhub` and `jupyterhub` the public host for the +JupyterHub. If you just specify `jupyterhub.proxy.https.hosts`, then daskhub +will *try* to guess the URL for you, but we might get it wrong. + +If you don't have an IP for your JupyterHub yet (if, say, you're letting +Kubernetes assign it for you), then you may need to leave this blank and +do a secondary `helm install` with the value set once it's known. + +## Install DaskHub + +This example installs into the namespace `dhub`. Make sure you're +in the same directory as the `secrets.yaml` file. + +```console +$ helm upgrade --wait --install --render-subchart-notes \ + dhub dask/daskhub \ + --namespace=dhub \ + --version=0.0.1 \ + --values=secrets.yaml \ + --values=config.yaml +``` + +The output explains how to find the IPs for your JupyterHub and Dask Gateway. + +```console +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +proxy-public LoadBalancer 10.43.249.239 35.202.158.223 443:31587/TCP,80:30500/TCP 2m40s +``` + +JupyterHub is available at the `proxy-public` external ip (35.202.158.223 in this example). +Note, that this value needs to be set as the `jupyterhub.proxy.service.loadBalancerIP`. + +```yaml +# file: config.yaml +jupyterhubPublicHost: "http://35.202.158.223" + +jupyterhub: + proxy: + service: + loadBalancerIP: "35.202.158.223" +``` + +Be sure to (re)deploy with helm with this value set to enable the Dask dashboard. + +## Creating a Dask Cluster + +To create a Dask cluster, connect to the Dask Gateway + +```python +>>> from dask_gateway import Gateway +>>> gateway = dask_gateway.Gateway() +>>> gateway.list_clusters() +[] +``` + +Once connected to the gateway, create a cluster and connect a client. + +```python +>>> cluster = gateway.new_cluster() +>>> client = cluster.get_client() +``` + +## Matching the user environment + +Dask Clients will be running the JupyterHub's singleuser environment. To ensure +that the same environment is used for the scheduler and workers, you can provide +it as a Gateway option. + +```yaml +# config.yaml +dask-gateway: + extraConfig: + optionHandler: | + from dask_gateway_server.options import Options, Integer, Float, String + def option_handler(options): + if ":" not in options.image: + raise ValueError("When specifying an image you must also provide a tag") + return { + "image": options.image, + } + c.Backend.cluster_options = Options( + String("image", default="pangeo/base-notebook:2020.07.28", label="Image"), + handler=option_handler, + ) +``` + +The user environment will need to include `dask-gateway`. + +## Using dask-kubernetes instead of Dask Gateway + +Users who don't need Dask Gateway can use dask-kubernetes to manage creating Dask Clusters. To use dask-kubernetes, you should set + +``` +# config.yaml +daskhub: + jupyterhub: + singleuser: + servieAccountName: daskkubernetes + + dask-gateway: + enabled: false + + dask-kubernetes: + enabled: true +``` + +When deploying, helm will create a Kubernetes ServiceAccount, Role, and RoleBinding. This ensures that the pods serving JupyterHub singleusers have the eleveated permissions for starting and stopping pods. + +{%- endblock %} + +{% block credits -%} +{%- endblock %} diff --git a/daskhub/README.md b/daskhub/README.md index 048c67b..aaedee7 100644 --- a/daskhub/README.md +++ b/daskhub/README.md @@ -1,4 +1,10 @@ -# DaskHub + +Daskhub +=========== + +[![Travis Build Status](https://travis-ci.com/dask/helm-chart.svg?branch=master)](https://travis-ci.com/dask/helm-chart) +[![Chart version](https://img.shields.io/badge/dynamic/yaml?url=https://helm.dask.org/index.yaml&label=chart&query=$.entries.daskhub[:1].version&color=277A9F)](https://helm.dask.org/) +[![Dask version](https://img.shields.io/badge/dynamic/yaml?url=https://helm.dask.org/index.yaml&label=Dask&query=$.entries.daskhub[:1].appVersion&color=D67548)](https://helm.dask.org/) This chart provides a multi-user, Dask-Gateway enabled JupyterHub. It combines the [JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) @@ -181,3 +187,27 @@ daskhub: ``` When deploying, helm will create a Kubernetes ServiceAccount, Role, and RoleBinding. This ensures that the pods serving JupyterHub singleusers have the eleveated permissions for starting and stopping pods. +## Configuration + +The following table lists the configurable parameters of the Daskhub chart and their default values. + +| Parameter | Description | Default | +| ------------------------ | ----------------------- | -------------- | +| `rbac.enabled` | | `true` | +| `jupyterhubPublicHost` | | `"nil"` | +| `jupyterhub.hub.extraEnv` | | `[{"name": "DASK_GATEWAY__ADDRESS", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASK_GATEWAY__ADDRESS"}}}, {"name": "DASK_GATEWAY__PROXY_ADDRESS", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASK_GATEWAY__PROXY_ADDRESS"}}}, {"name": "DASK_GATEWAY__PUBLIC_ADDRESS", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASK_GATEWAY__PUBLIC_ADDRESS"}}}, {"name": "DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL"}}}]` | +| `jupyterhub.hub.extraConfig.00-add-dask-gateway-values` | | `"# We need to set two a few things\n# On the Hub:\n# - Add the Gateway URL to the service.\n# On the singleuser\n# - DASK_GATEWAY_ADDRESS: {{ HUB_URL }}/servcies/dask-gateway/\n# - DASK_GATEWAY__PROXY_ADDRESS: gateway://traefik-{{ RELEASE_NAME }}-dask-gateway.{{ NAMESPACE }}\nimport os\n\n# Adds a few variables to singluser.ExtraEnv which depend on the release name.\nfor key in [\"DASK_GATEWAY__ADDRESS\", \"DASK_GATEWAY__PROXY_ADDRESS\",\n \"DASK_GATEWAY__PUBLIC_ADDRESS\"]:\n c.KubeSpawner.environment[key] = os.environ[key]\n\n# Adds Dask Gateway as a JupyterHub service to make the gateway available at\n# {HUB_URL}/services/dask-gateway\nfor service in c.JupyterHub.services:\n if service[\"name\"] == \"dask-gateway\":\n if not service.get(\"url\", None):\n print(\"Adding dask-gateway service URL\")\n service[\"url\"] = os.environ[\"DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL\"]\n break\nelse:\n print(\"dask-gateway service not found. Did you set jupyterhub.hub.services.dask-gateway.apiToken?\")\n"` | +| `jupyterhub.singleuser.image.name` | | `"pangeo/base-notebook"` | +| `jupyterhub.singleuser.image.tag` | | `"2020.07.28"` | +| `jupyterhub.singleuser.defaultUrl` | | `"/lab"` | +| `jupyterhub.singleuser.extraEnv.DASK_GATEWAY__AUTH__TYPE` | | `"jupyterhub"` | +| `dask-gateway.enabled` | | `true` | +| `dask-gateway.gateway.prefix` | | `"/services/dask-gateway"` | +| `dask-gateway.gateway.auth.type` | | `"jupyterhub"` | +| `dask-gateway.traefik.service.type` | | `"ClusterIP"` | +| `dask-kubernetes.enabled` | | `false` | + + + + + From fc9e4cedc02402979b1c29e95344fdca152f6323 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 24 Aug 2020 15:13:34 -0500 Subject: [PATCH 08/15] Fixups --- .travis.yml | 2 ++ daskhub/.frigate | 26 ------------------- daskhub/Chart.yaml | 1 + daskhub/README.md | 32 +++--------------------- daskhub/templates/daskhub-configmap.yaml | 10 -------- daskhub/values.yaml | 18 +++---------- 6 files changed, 10 insertions(+), 79 deletions(-) diff --git a/.travis.yml b/.travis.yml index b225fdf..b0bf1da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,8 @@ install: script: - helm lint dask + - helm lint daskhub --set 'dask-gateway.gateway.auth.jupyterhub.apiToken=foo' --set 'jupyterhub.proxy.secretToken=foo' + deploy: - provider: script diff --git a/daskhub/.frigate b/daskhub/.frigate index 6368468..c6e3548 100644 --- a/daskhub/.frigate +++ b/daskhub/.frigate @@ -63,30 +63,6 @@ dask-gateway: apiToken: "" ``` -If your users wish to access Dask dashboards, you'll also need to specify the -public hostname or IP address of the hub . - -```yaml -# file: config.yaml -jupyterhubPublicHost: "https://daskhub.example.com" - -jupyterhub: - proxy: - https: - hosts: - - "daskhub.example.com" - service: - loadBalancerIP: "35.202.158.223" -``` - -Notice that we tell both `daskhub` and `jupyterhub` the public host for the -JupyterHub. If you just specify `jupyterhub.proxy.https.hosts`, then daskhub -will *try* to guess the URL for you, but we might get it wrong. - -If you don't have an IP for your JupyterHub yet (if, say, you're letting -Kubernetes assign it for you), then you may need to leave this blank and -do a secondary `helm install` with the value set once it's known. - ## Install DaskHub This example installs into the namespace `dhub`. Make sure you're @@ -113,8 +89,6 @@ Note, that this value needs to be set as the `jupyterhub.proxy.service.loadBalan ```yaml # file: config.yaml -jupyterhubPublicHost: "http://35.202.158.223" - jupyterhub: proxy: service: diff --git a/daskhub/Chart.yaml b/daskhub/Chart.yaml index ec50636..48e1b7d 100644 --- a/daskhub/Chart.yaml +++ b/daskhub/Chart.yaml @@ -1,5 +1,6 @@ apiVersion: v2 name: daskhub +icon: https://avatars3.githubusercontent.com/u/17131925?v=3&s=200 version: 0.0.1-set.by.chartpress description: Multi-user JupyterHub and Dask deployment. dependencies: diff --git a/daskhub/README.md b/daskhub/README.md index aaedee7..dda6398 100644 --- a/daskhub/README.md +++ b/daskhub/README.md @@ -64,30 +64,6 @@ dask-gateway: apiToken: "" ``` -If your users wish to access Dask dashboards, you'll also need to specify the -public hostname or IP address of the hub . - -```yaml -# file: config.yaml -jupyterhubPublicHost: "https://daskhub.example.com" - -jupyterhub: - proxy: - https: - hosts: - - "daskhub.example.com" - service: - loadBalancerIP: "35.202.158.223" -``` - -Notice that we tell both `daskhub` and `jupyterhub` the public host for the -JupyterHub. If you just specify `jupyterhub.proxy.https.hosts`, then daskhub -will *try* to guess the URL for you, but we might get it wrong. - -If you don't have an IP for your JupyterHub yet (if, say, you're letting -Kubernetes assign it for you), then you may need to leave this blank and -do a secondary `helm install` with the value set once it's known. - ## Install DaskHub This example installs into the namespace `dhub`. Make sure you're @@ -114,8 +90,6 @@ Note, that this value needs to be set as the `jupyterhub.proxy.service.loadBalan ```yaml # file: config.yaml -jupyterhubPublicHost: "http://35.202.158.223" - jupyterhub: proxy: service: @@ -194,12 +168,12 @@ The following table lists the configurable parameters of the Daskhub chart and t | Parameter | Description | Default | | ------------------------ | ----------------------- | -------------- | | `rbac.enabled` | | `true` | -| `jupyterhubPublicHost` | | `"nil"` | -| `jupyterhub.hub.extraEnv` | | `[{"name": "DASK_GATEWAY__ADDRESS", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASK_GATEWAY__ADDRESS"}}}, {"name": "DASK_GATEWAY__PROXY_ADDRESS", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASK_GATEWAY__PROXY_ADDRESS"}}}, {"name": "DASK_GATEWAY__PUBLIC_ADDRESS", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASK_GATEWAY__PUBLIC_ADDRESS"}}}, {"name": "DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL"}}}]` | -| `jupyterhub.hub.extraConfig.00-add-dask-gateway-values` | | `"# We need to set two a few things\n# On the Hub:\n# - Add the Gateway URL to the service.\n# On the singleuser\n# - DASK_GATEWAY_ADDRESS: {{ HUB_URL }}/servcies/dask-gateway/\n# - DASK_GATEWAY__PROXY_ADDRESS: gateway://traefik-{{ RELEASE_NAME }}-dask-gateway.{{ NAMESPACE }}\nimport os\n\n# Adds a few variables to singluser.ExtraEnv which depend on the release name.\nfor key in [\"DASK_GATEWAY__ADDRESS\", \"DASK_GATEWAY__PROXY_ADDRESS\",\n \"DASK_GATEWAY__PUBLIC_ADDRESS\"]:\n c.KubeSpawner.environment[key] = os.environ[key]\n\n# Adds Dask Gateway as a JupyterHub service to make the gateway available at\n# {HUB_URL}/services/dask-gateway\nfor service in c.JupyterHub.services:\n if service[\"name\"] == \"dask-gateway\":\n if not service.get(\"url\", None):\n print(\"Adding dask-gateway service URL\")\n service[\"url\"] = os.environ[\"DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL\"]\n break\nelse:\n print(\"dask-gateway service not found. Did you set jupyterhub.hub.services.dask-gateway.apiToken?\")\n"` | +| `jupyterhub.hub.extraEnv` | | `[{"name": "DASK_GATEWAY__ADDRESS", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASK_GATEWAY__ADDRESS"}}}, {"name": "DASK_GATEWAY__PROXY_ADDRESS", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASK_GATEWAY__PROXY_ADDRESS"}}}, {"name": "DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL"}}}]` | +| `jupyterhub.hub.extraConfig.00-add-dask-gateway-values` | | `"# We need to set two a few things\n# On the Hub:\n# - Add the Gateway URL to the service.\n# On the singleuser\n# - DASK_GATEWAY_ADDRESS: {{ HUB_URL }}/servcies/dask-gateway/\n# - DASK_GATEWAY__PROXY_ADDRESS: gateway://traefik-{{ RELEASE_NAME }}-dask-gateway.{{ NAMESPACE }}\nimport os\n\n# Adds a few variables to singluser.ExtraEnv which depend on the release name.\nfor key in [\"DASK_GATEWAY__ADDRESS\", \"DASK_GATEWAY__PROXY_ADDRESS\"]:\n c.KubeSpawner.environment[key] = os.environ[key]\n\n# Adds Dask Gateway as a JupyterHub service to make the gateway available at\n# {HUB_URL}/services/dask-gateway\nfor service in c.JupyterHub.services:\n if service[\"name\"] == \"dask-gateway\":\n if not service.get(\"url\", None):\n print(\"Adding dask-gateway service URL\")\n service[\"url\"] = os.environ[\"DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL\"]\n break\nelse:\n print(\"dask-gateway service not found. Did you set jupyterhub.hub.services.dask-gateway.apiToken?\")\n"` | | `jupyterhub.singleuser.image.name` | | `"pangeo/base-notebook"` | | `jupyterhub.singleuser.image.tag` | | `"2020.07.28"` | | `jupyterhub.singleuser.defaultUrl` | | `"/lab"` | +| `jupyterhub.singleuser.extraEnv.DASK_GATEWAY__PUBLIC_ADDRESS` | | `"/services/dask-gateway/"` | | `jupyterhub.singleuser.extraEnv.DASK_GATEWAY__AUTH__TYPE` | | `"jupyterhub"` | | `dask-gateway.enabled` | | `true` | | `dask-gateway.gateway.prefix` | | `"/services/dask-gateway"` | diff --git a/daskhub/templates/daskhub-configmap.yaml b/daskhub/templates/daskhub-configmap.yaml index ca68b3f..5014142 100644 --- a/daskhub/templates/daskhub-configmap.yaml +++ b/daskhub/templates/daskhub-configmap.yaml @@ -6,13 +6,3 @@ data: DASK_GATEWAY__ADDRESS: "http://proxy-public/services/dask-gateway" DASK_GATEWAY__PROXY_ADDRESS: "gateway://traefik-{{ .Release.Name }}-dask-gateway.{{ .Release.Namespace }}:80" DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL: "http://traefik-{{ .Release.Name }}-dask-gateway.{{ .Release.Namespace }}" - # Try to detect the gateway public address through a few means. - {{ if .Values.jupyterhubPublicHost }} - DASK_GATEWAY__PUBLIC_ADDRESS: "{{ .Values.jupyterhubPublicHost }}/services/dask-gateway/" - {{ else if .Values.jupyterhub.proxy.https.hosts }} - DASK_GATEWAY__PUBLIC_ADDRESS: "https://{{ .Values.jupyterhub.proxy.https.hosts | first }}/services/dask-gateway/" - {{ else if .Values.jupyterhub.proxy.service.loadBalancerIP }} - DASK_GATEWAY__PUBLIC_ADDRESS: "http://{{ .Values.jupyterhub.proxy.service.loadBalancerIP }}/services/dask-gateway/" - {{ else }} - DASK_GATEWAY__PUBLIC_ADDRESS: "" - {{ end }} diff --git a/daskhub/values.yaml b/daskhub/values.yaml index 73ed48c..5ff9cfe 100644 --- a/daskhub/values.yaml +++ b/daskhub/values.yaml @@ -4,13 +4,6 @@ rbac: enabled: true -# The public URL (including protocol) for your JupyterHub deployment. -# If set, this provides a simple way to set the Dask Gateway public -# address for users to access their Dask dashboards. If not set, -# we'll try to guess it. -# example: https://daskhub.pangeo.io -jupyterhubPublicHost: nil - jupyterhub: # JupyterHub configuration goes here. # See https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/master/jupyterhub/values.yaml @@ -28,11 +21,6 @@ jupyterhub: configMapKeyRef: name: daskhub-config key: DASK_GATEWAY__PROXY_ADDRESS - - name: DASK_GATEWAY__PUBLIC_ADDRESS - valueFrom: - configMapKeyRef: - name: daskhub-config - key: DASK_GATEWAY__PUBLIC_ADDRESS - name: DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL valueFrom: configMapKeyRef: @@ -50,8 +38,7 @@ jupyterhub: import os # Adds a few variables to singluser.ExtraEnv which depend on the release name. - for key in ["DASK_GATEWAY__ADDRESS", "DASK_GATEWAY__PROXY_ADDRESS", - "DASK_GATEWAY__PUBLIC_ADDRESS"]: + for key in ["DASK_GATEWAY__ADDRESS", "DASK_GATEWAY__PROXY_ADDRESS"]: c.KubeSpawner.environment[key] = os.environ[key] # Adds Dask Gateway as a JupyterHub service to make the gateway available at @@ -72,6 +59,9 @@ jupyterhub: tag: 2020.07.28 defaultUrl: "/lab" extraEnv: + # Sets the Dask dashboard link. + DASK_GATEWAY__PUBLIC_ADDRESS: "/services/dask-gateway/" + # Authenticate Gateway requests via JupyterHub. DASK_GATEWAY__AUTH__TYPE: "jupyterhub" dask-gateway: From 08dcabd5ddfae146bfd28f871a5ae5874795f27c Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 24 Aug 2020 15:15:32 -0500 Subject: [PATCH 09/15] fixup --- .github/workflows/frigate.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/frigate.yml b/.github/workflows/frigate.yml index 5cb06a9..a758895 100644 --- a/.github/workflows/frigate.yml +++ b/.github/workflows/frigate.yml @@ -17,7 +17,7 @@ jobs: run: | python -m pip install --upgrade pip pip install frigate - - name: Check README is up to date + - name: Check that dask README is up to date run: | frigate gen dask > dask/README.md if git status --porcelain dask/README.md | grep .; then @@ -26,3 +26,12 @@ jobs: echo "In both cases please run `frigate gen dask > dask/README.md`." exit 1 fi + - name: Check that daskhub README is up to date + run: | + frigate gen daskhub > daskhub/README.md + if git status --porcelain dask/README.md | grep .; then + echo "README is out of date. Either you have modified README.md directly or you've modified values.yaml or Chart.yaml without generating the README." + echo "If you have modified with README.md please make those changes in dask/.frigate." + echo "In both cases please run `frigate gen dask > dask/README.md`." + exit 1 + fi From 35774cc33ba815788ec37a382d2327534d50884e Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 24 Aug 2020 15:16:30 -0500 Subject: [PATCH 10/15] fixup --- .github/workflows/frigate.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/frigate.yml b/.github/workflows/frigate.yml index a758895..e3b83af 100644 --- a/.github/workflows/frigate.yml +++ b/.github/workflows/frigate.yml @@ -29,9 +29,9 @@ jobs: - name: Check that daskhub README is up to date run: | frigate gen daskhub > daskhub/README.md - if git status --porcelain dask/README.md | grep .; then + if git status --porcelain daskhub/README.md | grep .; then echo "README is out of date. Either you have modified README.md directly or you've modified values.yaml or Chart.yaml without generating the README." - echo "If you have modified with README.md please make those changes in dask/.frigate." - echo "In both cases please run `frigate gen dask > dask/README.md`." + echo "If you have modified with README.md please make those changes in daskhub/.frigate." + echo "In both cases please run `frigate gen daskhub > daskhub/README.md`." exit 1 fi From 9439ef157726a970544ab4b3a88c89f47068adab Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 24 Aug 2020 15:18:31 -0500 Subject: [PATCH 11/15] badges --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 06760f8..3843f46 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ +[![Travis Build Status](https://travis-ci.com/dask/helm-chart.svg?branch=master)](https://travis-ci.com/dask/helm-chart) +[![Dask Chart version](https://img.shields.io/badge/dynamic/yaml?url=https://helm.dask.org/index.yaml&label=chart&query=$.entries.dask[:1].version&color=277A9F)](https://helm.dask.org/) +[![DaskHub Chart version](https://img.shields.io/badge/dynamic/yaml?url=https://helm.dask.org/index.yaml&label=chart&query=$.entries.daskhub[:1].version&color=277A9F)](https://helm.dask.org/) +[![Dask version](https://img.shields.io/badge/dynamic/yaml?url=https://helm.dask.org/index.yaml&label=Dask&query=$.entries.daskhub[:1].appVersion&color=D67548)](https://helm.dask.org/) + + + Dask Helm Charts ================ @@ -6,7 +13,7 @@ This repository contains Dask's two helm charts. - [dask](./dask/README.md): Install Dask on Kubernetes for a single user with Jupyter and dask-kubernetes. - [daskhub](./daskhub/README.md): Install Dask on Kubernetes for multiple users with JupyterHub and Dask Gateway. -## Quickstart -- singleuser +## Single-user Quickstart Users deploying Dask for a single user should use the `dask/dask` helm chart. @@ -18,7 +25,7 @@ helm install --name my-release dask/dask See [dask](./dask/README.md) for more. -## Quickstart -- multiuser +## Multi-user Quickstart Users deploying Dask for multiple users should use the `dask/daskhub` helm chart. From 0d40979ea0b822406f9e372c5ca491546eafc823 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 24 Aug 2020 15:21:34 -0500 Subject: [PATCH 12/15] helm 3 --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b0bf1da..f15ef2b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,7 @@ python: - "3.6" install: - - curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash - - helm init --client-only + - curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get-helm-3 | bash - pip install chartpress==0.4.2 script: From 92816d96b2cdb37efb3a3a5075e6a7ce9a235a63 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Tue, 25 Aug 2020 08:45:14 -0500 Subject: [PATCH 13/15] Update matching env --- daskhub/.frigate | 5 +++++ daskhub/README.md | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/daskhub/.frigate b/daskhub/.frigate index c6e3548..bad536f 100644 --- a/daskhub/.frigate +++ b/daskhub/.frigate @@ -123,6 +123,11 @@ it as a Gateway option. ```yaml # config.yaml +jupyterhub: + singleuser: + extraEnv: + DASK_GATEWAY__CLUSTER__OPTIONS__IMAGE: '{JUPYTER_IMAGE_SPEC}' + dask-gateway: extraConfig: optionHandler: | diff --git a/daskhub/README.md b/daskhub/README.md index dda6398..29b0f12 100644 --- a/daskhub/README.md +++ b/daskhub/README.md @@ -124,6 +124,11 @@ it as a Gateway option. ```yaml # config.yaml +jupyterhub: + singleuser: + extraEnv: + DASK_GATEWAY__CLUSTER__OPTIONS__IMAGE: '{JUPYTER_IMAGE_SPEC}' + dask-gateway: extraConfig: optionHandler: | From 5354f085904ea816971cd8f8e647f57a20f0674d Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Tue, 25 Aug 2020 08:50:06 -0500 Subject: [PATCH 14/15] Fixups --- daskhub/.frigate | 31 ++++++++++++------------------- daskhub/README.md | 31 ++++++++++++------------------- 2 files changed, 24 insertions(+), 38 deletions(-) diff --git a/daskhub/.frigate b/daskhub/.frigate index bad536f..d71cacf 100644 --- a/daskhub/.frigate +++ b/daskhub/.frigate @@ -80,41 +80,34 @@ $ helm upgrade --wait --install --render-subchart-notes \ The output explains how to find the IPs for your JupyterHub and Dask Gateway. ```console +$ kubectl -n dhub get service proxy-public NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE proxy-public LoadBalancer 10.43.249.239 35.202.158.223 443:31587/TCP,80:30500/TCP 2m40s ``` JupyterHub is available at the `proxy-public` external ip (35.202.158.223 in this example). -Note, that this value needs to be set as the `jupyterhub.proxy.service.loadBalancerIP`. - -```yaml -# file: config.yaml -jupyterhub: - proxy: - service: - loadBalancerIP: "35.202.158.223" -``` - -Be sure to (re)deploy with helm with this value set to enable the Dask dashboard. ## Creating a Dask Cluster -To create a Dask cluster, connect to the Dask Gateway +To create a Dask cluster users can create a `dask_gateway.GatewayCluster`. ```python ->>> from dask_gateway import Gateway ->>> gateway = dask_gateway.Gateway() ->>> gateway.list_clusters() -[] +>>> from dask_gateway import GatewayCluster +>>> cluster = gateway.new_cluster() +>>> client = cluster.get_client() ``` -Once connected to the gateway, create a cluster and connect a client. +If necessary (say to set options, create clusters that outlive the notebook session, etc.), +users can connect to the Gateway + ```python ->>> cluster = gateway.new_cluster() ->>> client = cluster.get_client() +>>> from dask_gateway import Gateway +>>> gateway = Gateway() ``` +See https://gateway.dask.org/ for more on using Dask Gateway. + ## Matching the user environment Dask Clients will be running the JupyterHub's singleuser environment. To ensure diff --git a/daskhub/README.md b/daskhub/README.md index 29b0f12..53746ed 100644 --- a/daskhub/README.md +++ b/daskhub/README.md @@ -81,41 +81,34 @@ $ helm upgrade --wait --install --render-subchart-notes \ The output explains how to find the IPs for your JupyterHub and Dask Gateway. ```console +$ kubectl -n dhub get service proxy-public NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE proxy-public LoadBalancer 10.43.249.239 35.202.158.223 443:31587/TCP,80:30500/TCP 2m40s ``` JupyterHub is available at the `proxy-public` external ip (35.202.158.223 in this example). -Note, that this value needs to be set as the `jupyterhub.proxy.service.loadBalancerIP`. - -```yaml -# file: config.yaml -jupyterhub: - proxy: - service: - loadBalancerIP: "35.202.158.223" -``` - -Be sure to (re)deploy with helm with this value set to enable the Dask dashboard. ## Creating a Dask Cluster -To create a Dask cluster, connect to the Dask Gateway +To create a Dask cluster users can create a `dask_gateway.GatewayCluster`. ```python ->>> from dask_gateway import Gateway ->>> gateway = dask_gateway.Gateway() ->>> gateway.list_clusters() -[] +>>> from dask_gateway import GatewayCluster +>>> cluster = gateway.new_cluster() +>>> client = cluster.get_client() ``` -Once connected to the gateway, create a cluster and connect a client. +If necessary (say to set options, create clusters that outlive the notebook session, etc.), +users can connect to the Gateway + ```python ->>> cluster = gateway.new_cluster() ->>> client = cluster.get_client() +>>> from dask_gateway import Gateway +>>> gateway = Gateway() ``` +See https://gateway.dask.org/ for more on using Dask Gateway. + ## Matching the user environment Dask Clients will be running the JupyterHub's singleuser environment. To ensure From dc875f58fb641c41dbc36da32558d488db1b3647 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Tue, 25 Aug 2020 09:58:18 -0500 Subject: [PATCH 15/15] formatting for frigate --- daskhub/README.md | 22 +++++++++++----------- daskhub/values.yaml | 35 +++++++++++------------------------ 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/daskhub/README.md b/daskhub/README.md index 53746ed..9c3ecd8 100644 --- a/daskhub/README.md +++ b/daskhub/README.md @@ -165,18 +165,18 @@ The following table lists the configurable parameters of the Daskhub chart and t | Parameter | Description | Default | | ------------------------ | ----------------------- | -------------- | -| `rbac.enabled` | | `true` | -| `jupyterhub.hub.extraEnv` | | `[{"name": "DASK_GATEWAY__ADDRESS", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASK_GATEWAY__ADDRESS"}}}, {"name": "DASK_GATEWAY__PROXY_ADDRESS", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASK_GATEWAY__PROXY_ADDRESS"}}}, {"name": "DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL"}}}]` | -| `jupyterhub.hub.extraConfig.00-add-dask-gateway-values` | | `"# We need to set two a few things\n# On the Hub:\n# - Add the Gateway URL to the service.\n# On the singleuser\n# - DASK_GATEWAY_ADDRESS: {{ HUB_URL }}/servcies/dask-gateway/\n# - DASK_GATEWAY__PROXY_ADDRESS: gateway://traefik-{{ RELEASE_NAME }}-dask-gateway.{{ NAMESPACE }}\nimport os\n\n# Adds a few variables to singluser.ExtraEnv which depend on the release name.\nfor key in [\"DASK_GATEWAY__ADDRESS\", \"DASK_GATEWAY__PROXY_ADDRESS\"]:\n c.KubeSpawner.environment[key] = os.environ[key]\n\n# Adds Dask Gateway as a JupyterHub service to make the gateway available at\n# {HUB_URL}/services/dask-gateway\nfor service in c.JupyterHub.services:\n if service[\"name\"] == \"dask-gateway\":\n if not service.get(\"url\", None):\n print(\"Adding dask-gateway service URL\")\n service[\"url\"] = os.environ[\"DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL\"]\n break\nelse:\n print(\"dask-gateway service not found. Did you set jupyterhub.hub.services.dask-gateway.apiToken?\")\n"` | -| `jupyterhub.singleuser.image.name` | | `"pangeo/base-notebook"` | +| `rbac.enabled` | Create and use roles and service accounts on an rbac-enabled cluster. | `true` | +| `jupyterhub.hub.extraEnv` | Configure jupyterhub to work with dask gateway. | `[{"name": "DASK_GATEWAY__ADDRESS", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASK_GATEWAY__ADDRESS"}}}, {"name": "DASK_GATEWAY__PROXY_ADDRESS", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASK_GATEWAY__PROXY_ADDRESS"}}}, {"name": "DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL", "valueFrom": {"configMapKeyRef": {"name": "daskhub-config", "key": "DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL"}}}]` | +| `jupyterhub.hub.extraConfig.00-add-dask-gateway-values` | | `"import os\n\n# Adds a few variables to singluser.ExtraEnv which depend on the release name.\nfor key in [\"DASK_GATEWAY__ADDRESS\", \"DASK_GATEWAY__PROXY_ADDRESS\"]:\n c.KubeSpawner.environment[key] = os.environ[key]\n\n# Adds Dask Gateway as a JupyterHub service to make the gateway available at\n# {HUB_URL}/services/dask-gateway\nfor service in c.JupyterHub.services:\n if service[\"name\"] == \"dask-gateway\":\n if not service.get(\"url\", None):\n print(\"Adding dask-gateway service URL\")\n service[\"url\"] = os.environ[\"DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL\"]\n break\nelse:\n print(\"dask-gateway service not found. Did you set jupyterhub.hub.services.dask-gateway.apiToken?\")\n"` | +| `jupyterhub.singleuser.image.name` | Image to use for singleuser environment. must include dask-gateyway. | `"pangeo/base-notebook"` | | `jupyterhub.singleuser.image.tag` | | `"2020.07.28"` | -| `jupyterhub.singleuser.defaultUrl` | | `"/lab"` | -| `jupyterhub.singleuser.extraEnv.DASK_GATEWAY__PUBLIC_ADDRESS` | | `"/services/dask-gateway/"` | -| `jupyterhub.singleuser.extraEnv.DASK_GATEWAY__AUTH__TYPE` | | `"jupyterhub"` | -| `dask-gateway.enabled` | | `true` | -| `dask-gateway.gateway.prefix` | | `"/services/dask-gateway"` | -| `dask-gateway.gateway.auth.type` | | `"jupyterhub"` | -| `dask-gateway.traefik.service.type` | | `"ClusterIP"` | +| `jupyterhub.singleuser.defaultUrl` | Use jupyterlab by defualt. | `"/lab"` | +| `jupyterhub.singleuser.extraEnv.DASK_GATEWAY__PUBLIC_ADDRESS` | Sets the dask dashboard link in cluster and client reprs. | `"/services/dask-gateway/"` | +| `jupyterhub.singleuser.extraEnv.DASK_GATEWAY__AUTH__TYPE` | Use jupyterhub to authenticate with dask gateway. | `"jupyterhub"` | +| `dask-gateway.enabled` | Enabling dask-gateway will install dask gateway as a dependency. | `true` | +| `dask-gateway.gateway.prefix` | Users connect to the gateway through the jupyterhub service. | `"/services/dask-gateway"` | +| `dask-gateway.gateway.auth.type` | Use jupyterhub to authenticate with dask gateway | `"jupyterhub"` | +| `dask-gateway.traefik.service.type` | Access dask gateway through jupyterhub. to access the gateway from outside jupyterhub, this must be changed to a `loadbalancer`. | `"ClusterIP"` | | `dask-kubernetes.enabled` | | `false` | diff --git a/daskhub/values.yaml b/daskhub/values.yaml index 5ff9cfe..b24fd96 100644 --- a/daskhub/values.yaml +++ b/daskhub/values.yaml @@ -1,8 +1,7 @@ # DaskHub configuration values # ---------------------------- -# Create and use roles and service accounts on an RBAC enabled cluster. rbac: - enabled: true + enabled: true # Create and use roles and service accounts on an RBAC-enabled cluster. jupyterhub: # JupyterHub configuration goes here. @@ -10,7 +9,7 @@ jupyterhub: hub: # These environment variables are declared in templates/daskhub-configmap.yaml # They are eventually set in the singleuser environment. - extraEnv: + extraEnv: # Configure JupyterHub to work with Dask Gateway. - name: DASK_GATEWAY__ADDRESS valueFrom: configMapKeyRef: @@ -28,13 +27,8 @@ jupyterhub: key: DASKHUB_JUPYTERHUB_SERVICE_GATEWAY_URL extraConfig: + # Register Dask Gateway service and setup singleuser environment. 00-add-dask-gateway-values: | - # We need to set two a few things - # On the Hub: - # - Add the Gateway URL to the service. - # On the singleuser - # - DASK_GATEWAY_ADDRESS: {{ HUB_URL }}/servcies/dask-gateway/ - # - DASK_GATEWAY__PROXY_ADDRESS: gateway://traefik-{{ RELEASE_NAME }}-dask-gateway.{{ NAMESPACE }} import os # Adds a few variables to singluser.ExtraEnv which depend on the release name. @@ -53,32 +47,25 @@ jupyterhub: print("dask-gateway service not found. Did you set jupyterhub.hub.services.dask-gateway.apiToken?") singleuser: - # The singleuser image should contain Dask Gateway for users to start Dask clusters. image: - name: pangeo/base-notebook + name: pangeo/base-notebook # Image to use for singleuser environment. Must include dask-gateyway. tag: 2020.07.28 - defaultUrl: "/lab" + defaultUrl: "/lab" # Use jupyterlab by defualt. extraEnv: - # Sets the Dask dashboard link. - DASK_GATEWAY__PUBLIC_ADDRESS: "/services/dask-gateway/" - # Authenticate Gateway requests via JupyterHub. - DASK_GATEWAY__AUTH__TYPE: "jupyterhub" + DASK_GATEWAY__PUBLIC_ADDRESS: "/services/dask-gateway/" # Sets the Dask dashboard link in cluster and client reprs. + DASK_GATEWAY__AUTH__TYPE: "jupyterhub" # Use JupyterHub to authenticate with Dask Gateway. dask-gateway: - # Enabling dask-gateway will install Dask Gateway as a dependency. - enabled: true + enabled: true # Enabling dask-gateway will install Dask Gateway as a dependency. # Futher Dask Gateway configuration goes here # See https://github.com/dask/dask-gateway/blob/master/resources/helm/dask-gateway/values.yaml gateway: - # Users connect to the Gateway through the JupyterHub service. - prefix: "/services/dask-gateway" + prefix: "/services/dask-gateway" # Users connect to the Gateway through the JupyterHub service. auth: - type: jupyterhub + type: jupyterhub # Use JupyterHub to authenticate with Dask Gateway traefik: service: - # We are using Dask Gateway behind a JupyterHub service. To access Dask Gateway - # from outside the JupyterHub, this must be changed to a LoadBalancer. - type: ClusterIP + type: ClusterIP # Access Dask Gateway through JupyterHub. To access the Gateway from outside JupyterHub, this must be changed to a `LoadBalancer`. dask-kubernetes: # Use dask-kubernetes, rather than Dask Gateway, for creating Dask Clusters.