diff --git a/docs/setup_guides/advanced/Makefile b/docs/setup_guides/advanced/Makefile new file mode 100644 index 00000000..11577a0c --- /dev/null +++ b/docs/setup_guides/advanced/Makefile @@ -0,0 +1,56 @@ +# Makefile for the recommended deploymet. +# Before running, make sure to install the prerequisites and update `secrets.yaml` +# with the secret tokens +.PHONY: group cluster dhub clean + +LOCATION?=westeurope +GROUP?=pangeo +CLUSTER?=pangeoCluster +MAX_USER_NODE_COUNT?=10 +MAX_WORKER_NODE_COUNT?=50 + + +group: + az group create --name $(GROUP) --location $(LOCATION) + + +cluster: + az aks create --resource-group $(GROUP) --name $(CLUSTER) --generate-ssh-keys \ + --node-count=1 \ + --nodepool-name core \ + --nodepool-labels hub.jupyter.org/node-purpose=core + + # Add a node-pool: one for the users and Dask schedulers + az aks nodepool add \ + --name users \ + --cluster-name $(CLUSTER) \ + --resource-group $(GROUP) \ + --enable-cluster-autoscaler \ + --node-count 1 \ + --min-count 0 --max-count $(MAX_USER_NODE_COUNT) \ + --node-vm-size Standard_D2s_v3 \ + --labels hub.jupyter.org/node-purpose=user + + # Add a node-pool for Dask workers. + az aks nodepool add \ + --name workers \ + --cluster-name $(CLUSTER) \ + --resource-group $(GROUP) \ + --enable-cluster-autoscaler \ + --node-count 1 \ + --min-count 0 --max-count $(MAX_WORKER_NODE_COUNT) \ + --node-vm-size Standard_D2s_v3 \ + --priority Spot \ + --eviction-policy Delete \ + --spot-max-price -1 \ + --labels="k8s.dask.org/dedicated=worker" + az aks get-credentials --name $(CLUSTER) --resource-group $(GROUP) + +dhub: + helm upgrade --wait --install --create-namespace \ + dask dask/daskhub \ + --namespace=dhub \ + --values=config.yaml + +clean: + az group delete -n $(GROUP) \ No newline at end of file diff --git a/docs/setup_guides/advanced/config.yaml b/docs/setup_guides/advanced/config.yaml new file mode 100644 index 00000000..f649499f --- /dev/null +++ b/docs/setup_guides/advanced/config.yaml @@ -0,0 +1,130 @@ +# file: config.yaml +# This file should not be stored in version control unless it's encrypted. +# Sensitive values are marked a comment "# Sensitive". +# You should update the following fields: +# - [ ] jupyterhub.proxy.secretToken +# - [ ] jupyterhub.proxy.https.hosts +# - [ ] jupyterhub.proxy.https.letsencrypt.contactEmail +# - [ ] jupyterhub.proxy.service.annotations.service.beta.kubernetes.io.azure-dns-label-name +# - [ ] jupyterhub.hub.config.AzureAdOauthenticator.oauth_callback_url +# - [ ] jupyterhub.hub.config.AzureAdOauthenticator.client_id +# - [ ] jupyterhub.hub.config.AzureAdOauthenticator.client_secret +# - [ ] jupyterhub.hub.config.AzureAdOauthenticator.tenant_id +# - [ ] jupyterhub.hub.services.dask-gateway.apiToken +# - [ ] dask-gateway.gateway.auth.jupyterhub.apiToken + +jupyterhub: + proxy: + # output from openssl rand -hex 32 + secretToken: "" # Sensitive + https: + enabled: true + hosts: + # Update this with your hub's name. + # If using AKS to get a DNS name, the first section of this hostname must match the value of + # service.beta.kubernetes.io/azure-dns-label-name. + - "..cloudapp.azure.com" + letsencrypt: + contactEmail: "" + service: + annotations: + # Update this with your hub's name. + service.beta.kubernetes.io/azure-dns-label-name: "" + + hub: + # Disable hub network Policy, so that the dask gateway server API can reach the hub directly + # Not required for dask-gateway>0.9.0 + # https://github.com/dask/helm-chart/issues/142 + networkPolicy: + enabled: false + + services: + dask-gateway: + # output from openssl rand -hex 32. Must match dask-gateway.gateway.auth.jupyterhub.apiToken + apiToken: "" # Sensitive + + config: + # Use our Azure AD App Registration for authentication + # https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app + JupyterHub: + authenticator_class: azuread + AzureAdOAuthenticator: + # Update this with the URL for your hub with /oauth_callback. + # If you're using Azure to obtain the DNS name from AKS, this must match the + oauth_callback_url: "https://..cloudapp.azure.com/hub/oauth_callback" + # Update these with the values for your Azure AD app registration. + client_id: "" + client_secret: "" # Sensitive + tenant_id: "" + + singleuser: + extraEnv: + DASK_GATEWAY__CLUSTER__OPTIONS__IMAGE: '{JUPYTER_IMAGE_SPEC}' + DASK_DISTRIBUTED__DASHBOARD_LINK: '/user/{JUPYTERHUB_USER}/proxy/{port}/status' + DASK_LABEXTENSION__FACTORY__MODULE: 'dask_gateway' + DASK_LABEXTENSION__FACTORY__CLASS: 'GatewayCluster' + +dask-gateway: + gateway: + auth: + jupyterhub: + # output from openssl rand -hex 32. Must match jupyterhub.services.dask-gateway.apiToken + apiToken: "" # Sensitive + + backend: + worker: + # Ensure workers are scheduled on the worker pool + extraPodConfig: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: "k8s.dask.org/dedicated" + operator: "In" + values: + - "worker" + + tolerations: + # allow workers to be scheduled on the worker pool, which has preemptible nodes. + - key: "k8s.dask.org/dedicated" + operator: "Equal" + value: "worker" + effect: "NoSchedule" + - key: "k8s.dask.org_dedicated" + operator: "Equal" + value: "worker" + effect: "NoSchedule" + - key: "kubernetes.azure.com/scalesetpriority" + operator: "Equal" + value: "spot" + effect: "NoSchedule" + + extraConfig: + 01-optionHandler: | + # Configure options to + # 1. Have the default worker image match the singleuser image + # 2. Place bounds on worker CPU and Memory requests + # 3. Accept a mapping of environment variables to pass to workers. + from dask_gateway_server.options import Options, Float, String, Mapping + def cluster_options(user): + def option_handler(options): + if ":" not in options.image: + raise ValueError("When specifying an image you must also provide a tag") + + return { + "worker_cores": 0.88 * min(options.worker_cores / 2, 1), + "worker_cores_limit": options.worker_cores, + "worker_memory": "%fG" % (0.95 * options.worker_memory), + "worker_memory_limit": "%fG" % options.worker_memory, + "image": options.image, + "environment": options.environment, + } + return Options( + Float("worker_cores", 1, min=1, max=16, label="Worker Cores"), + Float("worker_memory", 2, min=1, max=32, label="Worker Memory (GiB)"), + String("image", default="pangeo/pangeo-notebook:latest", label="Image"), + Mapping("environment", {}, label="Environment Variables"), + handler=option_handler, + ) + c.Backend.cluster_options = cluster_options diff --git a/docs/setup_guides/advanced/secrets.yaml b/docs/setup_guides/advanced/secrets.yaml new file mode 100644 index 00000000..e69de29b diff --git a/docs/setup_guides/azure.rst b/docs/setup_guides/azure.rst index b8284e5a..7e47d641 100644 --- a/docs/setup_guides/azure.rst +++ b/docs/setup_guides/azure.rst @@ -1,267 +1,426 @@ Installing Pangeo on Azure --------------------------- +========================== -This guide takes you through the steps necessary to install Pangeo on Microsoft's Azure Cloud Platform. -We'll make use of Azure's Kubernetes as a Service offering, called AKS (Azure Kubernetes Service), -for installing Pangeo on Azure. -Documentation on AKS can be found here: https://docs.microsoft.com/en-gb/azure/aks/. +In this guide, you'll deploy a Pangeo-style JupyterHub on Microsoft Azure. This will deploy a multi-user JupyterHub enabled with Dask for scalable computing. -.. Note:: - This guide lays out only the fundamental steps required to install Pangeo on Azure AKS. - Further work, for example to secure your cluster, is highly advised but not directly - covered here. +We'll use +* `Azure Kubernetes Service `__ (AKS), Azure's managed Kubernetes service +* The `daskhub Helm Chart `__, an easy way to install JupyterHub and Dask-Gateway -Step One: Build Kubernetes service -================================== +We describe two deployment scenarios, a :ref:`simple` and a :ref:`recommended`. If you're new to Azure, Kubernetes, or JupyterHub, then you should try the simple deployment to verify that the basics work, before moving on to the more advanced recommend deployment. -The first step to installing Pangeo on Azure is to set up a Kubernetes service -that can be used to run Pangeo. This can be done either by using the web interface -or by using the Azure commandline interface (CLI). These are both practical options, -so we'll cover each one in turn. +This guide uses the Azure CLI to create the Azure Resources. +Both deployment scenarios include a ``Makefile`` with targets for the AKS cluster and Hub deployment. If you're just looking to deploy a Hub, feel free to use and adapt the Makefiles. If you're looking to build understanding, read through the guide. -Using the web interface -~~~~~~~~~~~~~~~~~~~~~~~ +As an alternative to this guide, you might use `Qhub `_, which provides a higher-level tool to obtain a JupyterHub and Dask deployment on Kubernetes (or HPC). -To use the Azure web interface you must first have a Microsoft account that you -can use to log into the Azure web interface. If you have an existing Microsoft -account (for example, a hotmail.com or outlook.com email address) then you can use -that, or you can create a new account. +.. note:: -Once you have logged into the Azure web interface, navigate to Kubernetes services -and click the blue Add logo in the top left. This will display the Create Kubernetes cluster -wizard. + These examples create the Azure Resources in the West Europe region. This is a good + choice if you wish to access the data from `Microsoft's Planetary Computer `__. + Make sure to deploy your cluster in the same region as the data you'll be accessing. -Work through the wizard customising the Kubernetes service to be created as you -see necessary (all defaults are reasonable, so you should only need to edit the name -of the Kubernetes service to be created). In the last step before -the cluster is created a validation process is run, ensuring that any customizations you have -made will produce a working cluster. At this step you can also download a -template file to make reproducing or automating cluster creation simpler in the future. -Autoscaling -``````````` +Prerequisites +------------- -One benefit of the web interface is that we can easily create an AKS resource that implements -autoscaling via virtual nodes (see https://docs.microsoft.com/en-us/azure/aks/virtual-nodes-portal -for further details on this concept). Virtual nodes are still a preview feature in Azure, so some -limitations currently apply. To enable virtual nodes you need to have followed the setup steps in the -link above and also be using an Azure region where nodes are supported. +We'll assume that you've completed the `prerequisites `__ for creating an AKS cluster. This includes -With both of these requirements met, you can enable virtual nodes for autoscaling your Kubernetes -service. In the Scale tab, ensure that both the Virtual Nodes and VM scale sets selectors are -set to 'Enabled'. +* Obtaining an `Azure Subscription `_. +* Installing and configuring the `Azure CLI `__ +* Installing `kubectl `__ (``az aks install-cli``) +* Installing `Helm `__ -.. note:: +.. _simple: - You cannot create a Kubernetes service with traditional cluster autoscaling using the - web interface. See the next section for details on using the Azure CLI to create a - Kubernetes service with tradtional cluster autoscaling. +Simple deployment +----------------- +This section walks through the simplest possible deployment, but lacks basic features like authentication, HTTPS, and a user-friendly DNS name. We recommend trying this deployment to ensure that the tools work, before deleting things and moving on to the advanced deployment. +You can download the :download:`Makefile ` and :download:`Helm config ` for this deployment. -Using the Azure CLI -~~~~~~~~~~~~~~~~~~~ +Kubernetes Cluster +^^^^^^^^^^^^^^^^^^ -Instructions for downloading and installing the Azure CLI on major Operating Systems -can be found at: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest. -All interactions with the Azure CLI are via the ``az`` command. +Following the `Kubernetes walkthrough `__, we'll use the Azure CLI to create an AKS cluster. -To create a basic Kubernetes service using the Azure CLI: +For ease of reading we'll repeat the steps here, but visit the ``__ to build understanding about what each command does. For ease of cleanup, we recommend creating +a brand-new resource group. -.. code-block:: bash +.. code-block:: console - az aks create \ - --resource-group $RESOURCE_GROUP_NAME \ - --name $AKS_RESOURCE_NAME \ - --kubernetes-version 1.12.6 \ - --node-count 1 \ - --node-vm-size Standard_B8ms + # Create a Resource group + $ az group create --name pangeo --location westeurope + { + "id": "/subscriptions//resourceGroups/pangeo", + "location": "westeurope", + "managedBy": null, + "name": "pangeo", + "properties": { + "provisioningState": "Succeeded" + }, + "tags": null + } -You'll need to specify a name for your Kubernetes service (as ``$AKS_RESOURCE_NAME``) and a -name for an (existing) resource group (as ``$RESOURCE_GROUP_NAME``). Note that here -we've also asked for a medium-sized VM (that is, ``Standard_B8ms``) to host the node -rather than the default. We found that the default node was too small to host all -the pods necessary for the basic Pangeo install created by following this guide. -You can, however, specify any VM size name listed in the links from this page as the value to this key: -https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes. + # Create an AKS cluster + $ az aks create --resource-group pangeo --name pangeoCluster --generate-ssh-keys \ + --node-count=1 --enable-cluster-autoscaler --min-count=1 --max-count=5 -.. note:: - RBAC (Role-Based Access Control) is enabled by default on Kubernetes services set up using - the Azure CLI. If you need to change this default behaviour, you can specify the - ``--disable-rbac`` flag when creating your Kubernetes cluster. + # Get credentials for kubectl / helm + $ az aks get-credentials --name pangeoCluster --resource-group pangeo -The ``az aks create`` command above assumes that you have already set up a resource group -to deploy your Kubernetes service into. If you have not already set up a resource group, -run this command *before* creating your Kubernetes service: +At this point, you should have a Kubernetes Cluster up and running. Verify that things are are working OK with ``kubectl`` -.. code-block:: bash +.. code-block:: console - az group create \ - --name $RESOURCE_GROUP_NAME \ - --location $RESOURCE_REGION \ + $ kubectl get node + NAME STATUS ROLES AGE VERSION + aks-nodepool1-26963941-vmss000000 Ready agent 1m v1.19.11 -The location of the resource group needs to be specified as a single word -programmatic name for an Azure region. A list of available locations can be found -by running the following: +JupyterHub and Dask Gateway +^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. code-block:: bash +Now we're ready to install JupyterHub and Dask Gateway using the `daskhub `__ helm chart. Visit the documentation at https://github.com/dask/helm-chart/tree/main/daskhub for more background. - az account list-locations | grep name -Autoscaling -``````````` +1. Download or update the ``daskhub`` helm chart -To create a Kubernetes service with autoscaling enabled you can add extra keys -to the previous ``az aks create`` command: +.. code-block:: console -.. code-block:: bash + $ helm repo add dask https://helm.dask.org + $ helm repo update - az aks create \ - --resource-group $RESOURCE_GROUP_NAME \ - --name $AKS_RESOURCE_NAME \ - --kubernetes-version 1.12.6 \ - --node-count 1 \ - --node-vm-size Standard_B8ms \ - --enable-vmss \ - --enable-cluster-autoscaler \ - --min-count 1 \ - --max-count 10 +2. Generate two secret tokens: one for JupyterHub's proxy and one for Dask Gateway to act as a JupyterHub service. -You can also update an existing Kubernetes service to add autoscaling: +.. code-block:: console -.. code-block:: bash + $ openssl rand -hex 32 + - az aks update \ - --resource-group $RESOURCE_GROUP_NAME \ - --name $AKS_RESOURCE_NAME \ - --enable-cluster-autoscaler \ - --min-count 1 \ - --max-count 3 + $ openssl rand -hex 32 + -More information on autoscaling with Azure AKS is available here: -https://docs.microsoft.com/en-gb/azure/aks/cluster-autoscaler. +3. Create a configuration file with the customizations to the ``daskhub`` helm chart. We'll call ours ``secrets.yaml``. You should replace ```` and ```` with the outputs of the previous commands. +.. code-block:: yaml -Step Two: Customise cluster -=========================== + # file: secrets.yaml + jupyterhub: + proxy: + # output from openssl rand -hex 32. Must match dask-gateway.gateway.auth.jupyterhub.apiToken + secretToken: "" + + hub: + # Disable hub network Policy, so that the dask gateway server can reach the hub directly + # https://github.com/dask/helm-chart/issues/142 + networkPolicy: + enabled: false + + services: + dask-gateway: + # output from openssl rand -hex 32. Must match dask-gateway.gateway.auth.jupyterhub.apiToken + apiToken: "" + + dask-gateway: + gateway: + auth: + jupyterhub: + # output from openssl rand -hex 32. Must match jupyterhub.services.dask-gateway.apiToken + apiToken: "" + +4. Install ``daskhub``. We'll install it into a new ``dhub`` namespace, but you can use whatever namespace you like. + +.. code-block:: console + + $ helm upgrade --wait --install --create-namespace \ + dask dask/daskhub \ + --namespace=dhub \ + --values=secrets.yaml + Release "dask" does not exist. Installing it now. + NAME: dask + LAST DEPLOYED: Fri Jun 4 14:21:33 2021 + NAMESPACE: dhub + STATUS: deployed + REVISION: 1 + TEST SUITE: None + NOTES: + DaskHub + ------- + + Thank you for installing DaskHub, a multiuser, Dask-enabled JupyterHub! + + Your release is named dask and installed into the namespace dhub. + + + Jupyter Hub + ----------- + + You can find if the hub and proxy is ready by doing: + + kubectl --namespace=dhub 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=dhub get svc proxy-public + + It might take a few minutes for it to appear! + +Now DaskHub is deployed. The instructions printed above demonstrate how to get the IP address of your hub. + +.. warning:: + + This simple deployment doesn't have any kind of authentication. See :ref:`recommended` for how to create a deployment with authentication. + +When you log in and start a notebook sever, you should be able to connect to the Dask Gateway server and create a cluster. + +.. code-block:: python + + >>> from dask_gateway import Gateway + >>> gateway = Gateway() + >>> gateway.list_clusters() + [] + >>> cluster = gateway.new_cluster() + >>> client = cluster.get_client() + >>> cluster.scale(1) + +After a moment, the Dask Scheduler and Worker pods should start up. Check the pods with ``kubectl -n dhub get pods``. + +Cleanup +^^^^^^^ + +The easiest way to clean up the resources is to delete the resource group + +.. code-block:: console + + $ az group delete -n pangeo + + +.. _recommended: + +Recommended Deployment +---------------------- + +This deployment is a bit more more complicated. Compared to the simple deployment, it + +1. Supports HTTPs and uses a hostname rather than IP Address +2. Uses multiple node pools, one per type of worker, with spot (preemptible) nodes for Dask workers to save on costs + +Just like before, we'll create the Azure Resources first, and deploy `daskhub` second. We'll use the following values + +========================== ============= +Name value +========================== ============= +Resource group pangeo +Location westeurope +Cluster name pangeoCluster +Hub Name pangeo-hub +========================== ============= + +Azure Resources +^^^^^^^^^^^^^^^ + +1. Create a Resource Group +"""""""""""""""""""""""""" + +.. code-block:: console + + # Create a Resource group + $ az group create --name pangeo --location westeurope + { + "id": "/subscriptions//resourceGroups/pangeo", + "location": "westeurope", + "managedBy": null, + "name": "pangeo", + "properties": { + "provisioningState": "Succeeded" + }, + "tags": null, + } + +2. Create an App Registration +""""""""""""""""""""""""""""" -With a working Kubernetes service now built we can customise it in readiness for installing Pangeo -on the cluster. At its most basic, this means installing helm and tiller, but other -customisations (such as authentication) can also be added at this stage. -The customisations need to be performed using the Azure CLI. If you don't have the Azure CLI available, -you can either: +To authenticate users, we'll create an Azure AD App registration following `the instructions `__. +In this example, the *sign-in audience* will be **Accounts in this organizational directory only**. This is appropriate when your administering a Hub for other users within your Azure AD tenant. -* follow the steps at the link above to install the Azure CLI locally, or -* use the cloud shell built into the web interface - (click the ``>_`` logo at the right of the blue bar at the top of the web interface). - The cloud shell includes the Azure CLI and a basic implementation of Visual Studio Code editor. +The redirect URI should match where your users will access the Hub. If your organization already has a DNS provider, use that. +Otherwise, you can have Azure handle the DNS for your Hub service automatically, which is what we'll use in this guide. +We're calling our cluster ``pangeo-hub`` and deploying it in West Europe, so the callback URL is ``https://pangeo-hub.westeurope.cloudapp.azure.com/hub/oauth_callback``. +In general the pattern is ``https://..cloudapp.azure.com/hub/oauth_callback``. -Kubernetes credentials -~~~~~~~~~~~~~~~~~~~~~~ +Finally, create a Client Secret to pass to JupyterHub: Under the *Manage* section, select *Certificates and Secrets* then *New client secret*. We'll use the ``Value`` later on. +You will also need the App Registration's ``Client ID`` and ``Tenant ID``, which are available on its main page, under *Essentials*. -Before we can progress we need to acquire kubernetes credentials for our newly-created -AKS resource: +To summarize, we now have our app registration's -.. code-block:: bash +- Client ID +- Tenant ID +- Client Secret +- OAuth callback URL - az aks get-credentials -g $RESOURCE_GROUP_NAME -n $AKS_RESOURCE_NAME --overwrite-existing +For more on authentication see `Authentication and Authorization `__, in particular the section on `Azure AD `__. +3. Create a Kubernetes Cluster +"""""""""""""""""""""""""""""" -You will need to provide the name of the AKS resource that you just created (as ``$AKS_RESOURCE_NAME``) -and the group within which the resource was created (as ``$RESOURCE_GROUP_NAME``). +Now we'll create a Kubernetes cluster. Compared to last time, we'll have three node pools: A "core" pool for JupyterHub pods (the Hub, etc.) and Kubernetes itself, a "user" pool for user pods and Dask schedulers, and a "worker" pool for Dask workers. +.. code-block:: console -Helm and tiller -~~~~~~~~~~~~~~~ + # Create an AKS cluster + $ az aks create --resource-group pangeo --name pangeoCluster --generate-ssh-keys \ + --node-count=1 \ + --nodepool-name core \ + --nodepool-labels hub.jupyter.org/node-purpose=core -Installing helm and tiller allows us to customise our Kubernetes service by applying -helm charts to it. We need to ensure that helm and tiller will work correctly with -RBAC, which is enabled by default on Azure Kubernetes services. + # Add a node-pool: one for the users and Dask schedulers + $ az aks nodepool add \ + --name users \ + --cluster-name pangeoCluster \ + --resource-group pangeo \ + --enable-cluster-autoscaler \ + --node-count 1 \ + --min-count 0 --max-count 10 \ + --node-vm-size Standard_D2s_v3 \ + --labels hub.jupyter.org/node-purpose=user -.. code-block:: bash + # Add a node-pool for Dask workers. + $ az aks nodepool add \ + --name workers \ + --cluster-name pangeoCluster \ + --resource-group pangeo \ + --enable-cluster-autoscaler \ + --node-count 1 \ + --min-count 0 --max-count 50 \ + --node-vm-size Standard_D2s_v3 \ + --priority Spot \ + --eviction-policy Delete \ + --spot-max-price -1 \ + --labels="k8s.dask.org/dedicated=worker" - kubectl apply -f helm_rbac.yaml - helm init --upgrade --service-account tiller --wait +At this point, you should have a functioning Kubernetes Cluster with multiple node-pools. For example -The contents of ``helm_rbac.yaml`` are as follows: +.. code-block:: console -.. code-block:: yaml + $ az aks get-credentials \ + --name pangeoCluster \ + --resource-group pangeo \ + --output table - apiVersion: v1 - kind: ServiceAccount - metadata: - name: tiller - namespace: kube-system - --- - apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRoleBinding - metadata: - name: tiller - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin - subjects: - - kind: ServiceAccount - name: tiller - namespace: kube-system + $ kubectl get node + NAME STATUS ROLES AGE VERSION + aks-core-26963941-vmss000000 Ready agent 15m v1.19.11 + aks-users-26963941-vmss000000 Ready agent 8m19s v1.19.11 + aks-workers-26963941-vmss000000 Ready agent 3m3s v1.19.11 -Step 3: Install Pangeo -====================== +Deploy DaskHub +^^^^^^^^^^^^^^ -Now we can move onto installing Pangeo on our Kubernetes service. This can be done -as follows: +1. Get the Helm chart +""""""""""""""""""""" -.. code-block:: bash +Download or update the ``daskhub`` helm chart. - helm repo add pangeo https://pangeo-data.github.io/helm-chart/ - helm repo update - helm upgrade --install --namespace pangeo pangeo pangeo/pangeo -f pangeo.yaml +.. code-block:: console -The helm chart ``pangeo.yaml`` is the -`Pangeo helm chart `_. The customizations -we made to it are documented in the -`Zero to Jupyterhub `_ -guide. + $ helm repo add dask https://helm.dask.org + $ helm repo update +2. Generate secret tokens +""""""""""""""""""""""""" -Test install -~~~~~~~~~~~~ +We need two secret tokens: one for JupyterHub's proxy and one for Dask Gateway to act as a JupyterHub service. -To test that Pangeo has installed successfully on your Kubernetes service, find -the IP address of the Pangeo proxy: +.. code-block:: console -.. code-block:: bash + $ openssl rand -hex 32 + + + $ openssl rand -hex 32 + - kubectl get service proxy-public --namespace=pangeo +3. Create a configuration file +"""""""""""""""""""""""""""""" -Note that this service can take a long time to start up, so you may need to wait -a while for the IP address of the Pangeo proxy to be displayed. The output of the -above command will read ```` while the service is starting up. +This configuration file is used to customize the deployment with Helm. You can start with the :download:`reference config file`. -Once the service has started up, navigate to the ``EXTERNAL-IP`` address listed -in the output of the above command in your web browser. -If JupyterHub loads then you have successfully installed Pangeo on your Azure Kubernetes service! +.. warning:: + For simplicity, we've included all of the configuration values + in a single `config.yaml` file, including sensitive values. We recommend keeping the sensitive values in a separate, encrypted file + that's decrypted just when deploying. -Autoscaling -~~~~~~~~~~~ +.. literalinclude:: advanced/config.yaml + :language: yaml -If you set up your autoscaling Kubernetes service using the cluster autoscaler then autoscaling -should work with no further customisation neeeded. If instead you set up autoscaling using -virtual nodes and VM scale sets then a little more work is needed. In particular we need to -modify the Pangeo ``worker-template.yaml`` file to add two more key groups to the ``spec`` section -of the yaml: +4. Install ``daskhub`` +"""""""""""""""""""""" -.. code-block:: yaml +We'll install it into a new ``dhub`` namespace, but you can use whatever namespace you like. + +.. code-block:: console + + $ helm upgrade --wait --install --create-namespace \ + dask dask/daskhub \ + --namespace=dhub \ + --values=config.yaml + +Verify that all the pods are running with + +.. code-block:: console + + $ kubectl -n dhub get pod + NAME READY STATUS RESTARTS AGE + api-dask-dask-gateway-947887bf9-f748w 1/1 Running 0 18m + autohttps-66bd64d49b-wskqc 2/2 Running 0 18m + continuous-image-puller-nwq4l 1/1 Running 0 18m + controller-dask-dask-gateway-ccf4595c8-lx2h7 1/1 Running 0 18m + hub-56d584b5b5-7rxvk 1/1 Running 0 18m + proxy-5b4bb9b8bb-q8r7x 1/1 Running 0 18m + traefik-dask-dask-gateway-d9d4cc45c-whmmw 1/1 Running 0 18m + user-scheduler-86c6bc8cd-h6dx2 1/1 Running 0 18m + user-scheduler-86c6bc8cd-hhhbn 1/1 Running 0 18m + +.. note:: + + If you see an HTTPS error accessing the hub, you may need to recreate the ``autohttps`` pod created by JupyterHub. + + .. code-block:: console + + $ kubectl -n dhub delete pod -l app=jupyterhub,component=autohttps + + This will recreate the ``autohttps`` pod and successfully get a TLS certificate so that the Hub can be accessed + over HTTPS. + +When you log in and start a notebook sever, you should be able to connect to the Dask Gateway server and create a cluster. + +.. code-block:: python + + >>> from dask_gateway import Gateway + >>> gateway = Gateway() + >>> gateway.list_clusters() + [] + >>> cluster = gateway.new_cluster() + >>> client = cluster.get_client() + >>> cluster.scale(1) + +After a moment, the Dask Scheduler and Worker pods should start up. Check the pods with ``kubectl -n dhub get pods``. + + +Cleanup +^^^^^^^ + +The easiest way to clean up the resources is to delete the resource group + +.. code-block:: console + + az group delete -n pangeo + +Next steps +---------- - nodeSelector: - kubernetes.io/role: agent - beta.kubernetes.io/os: linux - type: virtual-kubelet - tolerations: - - key: virtual-kubelet.io/provider - operator: Exists - - key: azure.com/aci - effect: NoSchedule +Your AKS cluster and JupyterHub deployments can be customized in various ways. Visit the the `Azure Kubernetes Service overivew `__ for more on AKS, `Zero to JupyterHub with Kubernetes `__ documentation for more on JupyterHub and the JupyterHub helm chart, and `Dask Gateway `__ for more on Dask Gateway. \ No newline at end of file diff --git a/docs/setup_guides/simple/Makefile b/docs/setup_guides/simple/Makefile new file mode 100644 index 00000000..487fdd72 --- /dev/null +++ b/docs/setup_guides/simple/Makefile @@ -0,0 +1,27 @@ +# Makefile for the simple deploymet. +# Before running, make sure to install the prerequisites and update `secrets.yaml` +# with the secret tokens +.PHONY: group cluster dhub clean + +LOCATION?=westeurope +GROUP?=pangeo +CLUSTER?=pangeoCluster +MIN_COUNT?=1 +MAX_COUNT?=3 + +group: + az group create --name $(GROUP) --location $(LOCATION) + +cluster: + az aks create --resource-group $(GROUP) --name $(CLUSTER) --generate-ssh-keys \ + --node-count=1 --enable-cluster-autoscaler --min-count=$(MIN_COUNT) --max-count=$(MAX_COUNT) + az aks get-credentials --name $(CLUSTER) --resource-group $(GROUP) + +dhub: + helm upgrade --wait --install --create-namespace \ + dask dask/daskhub \ + --namespace=dhub \ + --values=secrets.yaml + +clean: + az group delete -n $(GROUP) \ No newline at end of file diff --git a/docs/setup_guides/simple/secrets.yaml b/docs/setup_guides/simple/secrets.yaml new file mode 100644 index 00000000..05785c48 --- /dev/null +++ b/docs/setup_guides/simple/secrets.yaml @@ -0,0 +1,28 @@ +# file: secrets.yaml +# This file should not be stored in version control unless it's encrypted. +# You should update the following fields: +# - [ ] jupyterhub.proxy.secretToken +# - [ ] jupyterhub.hub.services.dask-gateway.apiToken +# - [ ] dask-gateway.gateway.auth.jupyterhub.apiToken +jupyterhub: + proxy: + # output from openssl rand -hex 32. Must match dask-gateway.gateway.auth.jupyterhub.apiToken + secretToken: "" + + hub: + # Disable hub network Policy, so that the dask gateway server can reach the hub directly + # https://github.com/dask/helm-chart/issues/142 + networkPolicy: + enabled: false + + services: + dask-gateway: + # output from openssl rand -hex 32. Must match dask-gateway.gateway.auth.jupyterhub.apiToken + apiToken: "" + +dask-gateway: + gateway: + auth: + jupyterhub: + # output from openssl rand -hex 32. Must match jupyterhub.services.dask-gateway.apiToken + apiToken: "" \ No newline at end of file