From e3379ebe211d35ca4ed5b3011359f8751356c7fe Mon Sep 17 00:00:00 2001 From: GeorgianaElena Date: Mon, 15 Mar 2021 20:32:26 +0200 Subject: [PATCH] Restructure docs to match the new structure --- docs/configure.md | 297 ------------------- docs/howto/configure/add-hub-domains.md | 36 +++ docs/howto/configure/auth-management.md | 56 ++++ docs/howto/configure/hub-config.md | 17 ++ docs/howto/configure/update-env.md | 22 ++ docs/howto/customize/configure-login-page.md | 9 + docs/{ => howto/customize}/custom-image.md | 2 +- docs/howto/customize/docs-service.md | 32 ++ docs/howto/index.md | 39 +++ docs/howto/operate/add-hub.md | 7 + docs/howto/operate/cmd-access.md | 72 +++++ docs/howto/operate/delete-hub.md | 8 + docs/howto/operate/grafana.md | 7 + docs/howto/operate/index.md | 16 + docs/howto/operate/test-hub.md | 40 +++ docs/index.md | 7 +- docs/operate.md | 147 --------- docs/structure.md | 6 +- docs/topic/cluster-config.md | 14 + docs/topic/defaults.md | 10 + docs/topic/hub-config.md | 26 ++ docs/topic/hub-templates.md | 59 ++++ docs/topic/index.md | 9 + 23 files changed, 487 insertions(+), 451 deletions(-) delete mode 100644 docs/configure.md create mode 100644 docs/howto/configure/add-hub-domains.md create mode 100644 docs/howto/configure/auth-management.md create mode 100644 docs/howto/configure/hub-config.md create mode 100644 docs/howto/configure/update-env.md create mode 100644 docs/howto/customize/configure-login-page.md rename docs/{ => howto/customize}/custom-image.md (99%) create mode 100644 docs/howto/customize/docs-service.md create mode 100644 docs/howto/index.md create mode 100644 docs/howto/operate/add-hub.md create mode 100644 docs/howto/operate/cmd-access.md create mode 100644 docs/howto/operate/delete-hub.md create mode 100644 docs/howto/operate/grafana.md create mode 100644 docs/howto/operate/index.md create mode 100644 docs/howto/operate/test-hub.md delete mode 100644 docs/operate.md create mode 100644 docs/topic/cluster-config.md create mode 100644 docs/topic/defaults.md create mode 100644 docs/topic/hub-config.md create mode 100644 docs/topic/hub-templates.md create mode 100644 docs/topic/index.md diff --git a/docs/configure.md b/docs/configure.md deleted file mode 100644 index 8ce1224fe..000000000 --- a/docs/configure.md +++ /dev/null @@ -1,297 +0,0 @@ -# Cluster configuration - -Information about how to customize and configure each of the cluster (or individual hubs). - -## Cluster configuration reference - -At the top level of `hubs.yaml` is a list of **clusters**. Each cluster is a cloud deployment (for example, a Google project) that can have one or more hubs deployed inside it. - -Clusters have some basic configurability: - -`name` -: A string that uniquely identifies this cluster - -`image_repo` -: The base **user image** that all hubs will use in this cluster. - -`provider` -: The cloud provider for this cluster (e.g. `gcp`). - -## Hub configuration reference - -`clusters.hubs:` is a list of hubs to be deployed in each cluster. -Each hub is a dictionary that can consist of the following keys: - -`name` -: A string that uniquely identifies this hub - -`cluster` -: The cluster where this hub will be deployed. - -`domain` -: Domain this hub should be available at. Currently, must be a subdomain - of a domain that has been pre-configured to point to our cluster. Currently, - that is `..2i2c.cloud` - -`auth0` -: We use [auth0](https://auth0.com/) for authentication, and it supports - many [connections](https://auth0.com/docs/identityproviders). Currently, - only `connector` property is supported - see section on *Authentication* - for more information. - -`config.jupyterhub` -: Any arbitrary [zero to jupyterhub](https://z2jh.jupyter.org) configuration - can be passed here. Most common is auth setup, memory / CPU restrictions, - and max number of active users. See {ref}`config-jupyterhub` for more info. - -## Hub templates -The hubs are configured and deployed using *hub templates*. Because each hub -type can be described by a template, with its own deployment chart, a hierarchy -of hub types can be built and this makes development and usage easier. - -The graphic below, shows the relationship between the hub templates and the other -config files and how they are merged together when deploying a pilot hub. - -```{figure} images/config-flow.png -``` -% The editable version of the diagram is here: https://docs.google.com/presentation/d/1WZKTe5TSDU-5zA4NnNEPsKfgjaBzUqMgdPLTnz-Yb94/edit?usp=sharing - -Currently there are three hub templates available: -- `base-hub` - - The **base-hub template** is the template that the other templates "inherit" and configure. - It provides a base JupyterHub, user storage and culling configuration that satisfies most of the - pilot hubs usage requirements. - -- `ephemeral-hub` - - The **ephemeral-hub template** helps deploying temporary, transient binder-style hubs. - - Doesn't require any user authentication. - - Permits limiting of resources: - * memory / CPU limits - * maximum number of concurrent user servers - - Has more aggressive culling: - - Stops server after 30min of idleness - - Desn't let servers run for more than 8h - - Has no persistent storage - - Doesn't use or configures a home page template - -- `daskhub` - - The **daskhub template** helps deploying dask-enabled hubs. - - Installs [dask-gateway](https://gateway.dask.org/) - - Defaults to using a [PANGEO image](https://pangeo-data.github.io/pangeo-stacks/) - - Enables outgoing SSH - - -### Using the templates to deploy a new hub -To deploy a new hub, you only need to add and configure it through `hubs.yaml` configuration file. -This configuration file allows specifying options like the type of template to use for the hub being added, -the hub domain, how the JupyterHub landing page will look like and authentication preferences. - -Because the templates are structured in a **hierarchical** model, so are their helm charts. -The [jupyterhub helm chart](https://jupyterhub.github.io/helm-chart/) is a subchart of the base-hub and -the base-hub chart along with the [dask-gateway](https://dask.org/dask-gateway-helm-repo/) one are -subcharts of the daskhub. The ephemeral-hub chart also subcharts the base-hub. - -**Visual of the helm-chart hierarchy:** -```{figure} images/helm-charts-hierarchy.png -``` -% The editable version of the diagram is here: https://docs.google.com/presentation/d/1KMyrTd3wdR715tPGuzIHkHqScXBlLpeiksIM2x7EI0g/edit?usp=sharing - -This hierachy is the reason why when adding a new hub using the `daskhub` or the `ephemeral-hub` template, the jupyterhub -specific configuration in `hubs.yaml` needs to be nested under a `base-hub` key, indicating that we are overriding configuration -from the *base-hub/jupyterhub* parent chart. - -Read more about subcharts and how to configure them in the [Helm docs](https://helm.sh/docs/chart_template_guide/subcharts_and_globals/#overriding-values-from-a-parent-chart). - -(config-jupyterhub)= -## Configuring each JupyterHub - -Each JupyterHub can use its own configuration via the `hubs.yaml` file. This configuration exists under `config.jupyterhub`. -This should be a valid [Zero to JupyterHub](https://z2jh.jupyter.org) configuration. For example, to set a custom memory limit for a hub, you would use: - -```yaml -config: - jupyterhub: - singleuser: - memory: - limit: 1G -``` - -Here are a few reference pages for JupyterHub Kubernetes configuration: - -- {ref}`z2jh:user-environment` -- {ref}`z2jh:user-resources` - -## Authentication - -[auth0](https://auth0.com) provides authentication for all hubs here. It can -be configured with many different [connections](https://auth0.com/docs/identityproviders) -that users can authenticate with - such as Google, GitHub, etc. - -So we want to manage authentication by: - -1. Explicitly listing the type of connection we want for this hub, via - `auth0.connection`. Currently common ones are `google-oauth2` for Google & - `github` for GitHub. *Users* of the hub will use this method to log in to - the hub. - - You can set the auth0 connector for a hub with: - - ```yaml - auth0: - connection: google-oauth2 - ``` - - Theoretically, every provider in [this list](https://auth0.com/docs/connections/identity-providers-social) - is supported. However, we've currently only tested this with Google - (`google-oauth2`) and GitHub (`github`) - -2. Explicitly list *admin users* for a given hub. These admin users will be the - only ones allowed to log in to begin with. They can use the JupyterHub - admin interface (available from their hub control panel) to explicitly allow - more users into the hub. This way, we don't need to be involved in explicitly - allowing users into hubs. - - In the admin interface, admin users can add users via a username appropriate - for the auth connector used. For GitHub, it's the username. For Google Auth, - it's the email address. - - You can set the admin interfaces for a hub like this: - - ```yaml - config: - jupyterhub: - auth: - # will be renamed allowedlist in future JupyterHub - whitelist: - users: - # WARNING: THESE USER LISTS MUST MATCH (for now) - - user1@gmail.com - - user2@gmail.com - admin: - users: - # WARNING: THESE USER LISTS MUST MATCH (for now) - - user1@gmail.com - - user2@gmail.com - ``` - -:::{admonition} Switching auth -Switching authentication for a pre-existing hub will simply create new usernames. Any pre-existing users will no longer be able to access their accounts (although administrators will be able to do so). If you have pre-existing users and want to switch the hub authentication, rename the users to the new auth pattern (e.g. convert github handles to emails). -::: - -## Adding additional domains to a hub - -Existing pilot-hubs in the two 2i2c-managed clusters, have a subdomain created and assingned to them on creation, -that respects the following naming convention, based on which domain name and cluster they are part of: - -- `.pilot.2i2c.cloud` - for the ones in the 2i2c cluster and *pilot.2i2c.cloud* domain -- `.cloudbank.2i2c.cloud` - for the ones in the cloudbank cluster and *cloudbank.2i2c.cloud* domain - -But other domains can be easily linked to the same hub in a cluster if needed. - -Assuming there is a hub named `foo` in the `2i2c` cluster and we want to add the `foo.edu` domain to it, one would: - -1. **Point the `foo.edu` domain to the right cluster.** - - Create a [CNAME](https://en.wikipedia.org/wiki/CNAME_record) entry from the new domain, `foo.edu`, that points to the - existing `foo.pilot.2i2c.cloud`, where the `foo` hub already runs. - - This will map the new domain name, `foo.edu`, to the default one `foo.pilot.2i2c.cloud` - *the canonical name* and will - make sure `foo.edu` points to the right cluster, no matter which IP address the cluster has. - -2. **Point the `foo.edu` domain to the right hub.** - - Since all the hubs in a cluster are running at the same IP address, but are available at different subdomains, - we also need a way to specify which hub in this cluster we want the new domain and subsequent requests to point to. - - For this to happen we need to add the new domain as an ingress domain for this hub using the `hubs.yaml` configuration file. - This can be done by adding the new domain to the list in `hubs..domain`: - - ```yaml - - name: foo - cluster: 2i2c - domain: - - foo.pilot.2i2c.cloud # default domain - - foo.edu # additionl domain - (...) - ``` - -## Default options - -Part of being 'low touch' is to provide default options that we think might -work for most people. These are specified in `hub/values.yaml` in the repository. -We list some common ones here. - -1. **Memory Limit** of 1G per student, with a guarantee of 256M. This means that - everyone will be *guaranteed* 256M of memory, and most likely will have access - to 1G of memory. But they can't use more than 1G of memory - their kernels and - processes will die if they use more than this. - -## Updating environment - -The user environments is specified via a `Dockerfile`, under `images/user` in -the git repository. Currently there is no automated image building - so you will -have to manually build & push it after making a change. - -1. Install pre-requisites: - - a. Docker - b. A Python virtual environment. Install `requirements.txt` into it. - c. The `gcloud` tool, authenticated to the `two-eye-two-see` project. - You need to run `gcloud auth configure-docker us-central1-docker.pkg.dev` - once as well. - -2. Make the changes you need to make to the environment, and git commit it. - -3. Run `python3 deploy.py build`. This will build the image and push it to - registry. It will tell you what the generated image tag is. - -4. Update `jupyterhub.singleuser.image.tag` in `hub/values.yaml` with this tag. - -5. Make a commit, make a PR and merge to master! This will deploy all the hubs - with the new image - -## Configuring the hub login page - -Each Hub deployed in a cluster has a collection of metadata about who it is deployed for, and who is responsible for running it. This is used to generate the **log-in page** for each hub and tailor it for the community. - -For an example, see [the log-in page of the staging hub](https://staging.pilot.2i2c.cloud/hub/login). - -The log-in pages are built with [the base template at this repository](https://github.com/2i2c-org/pilot-homepage). Values are inserted into each template based on each hub configuration. - -You may customize the configuration for a hub's homepage at `config.jupyterhub.homepage.templateVars`. Changing these values for a hub will make that hub's landing page update automatically. We recommend [using the `hubs.yaml` file as a reference](https://github.com/2i2c-org/pilot-hubs/blob/master/hubs.yaml). Copy the configuration from another hub, and then modify the contents to fit the new hub that is being configured. - -## Connecting static web content with the hub - -The 2i2c hubs can be configured to provide static web content as a [JupyterHub service](https://jupyterhub.readthedocs.io/en/stable/reference/services.html), available -at `https:///services/docs`. This can be a great tool to provide hub-specific documentation right from inside the hub. - -```{figure} images/docs-service.png -``` - -To enable the docs service service for a hub: - -1. Mark it as *enabled* in `hubs.yaml`, by setting `hubs..config.docs_service.enabled` to *True*. -2. Specify the GitHub repository where the static HTML files are hosted, by setting `hubs..config.docs_service.repo`. -3. Specify the GitHub branch of the respository where the static HTML files are hosted, by setting `hubs..config.docs_service.branch`. - -Example config: - -```yaml - config: - docs_service: - enabled: true - repo: https://github.com/ - branch: -``` - -```{note} - -Depending on what Static Site Generator has been used to generate the website's static content, it **may** or **may not** use relative paths routing by default. -For example, [Sphinx](https://www.sphinx-doc.org/en/master/) handles relative paths by default, whereas, [Hugo](https://gohugo.io/) leaves all [relative URLs unchanged](https://gohugo.io/content-management/urls/#relative-urls). - -However, having relative URLS is a **must** in order for the hub docs service to work. Please check with the docs of your SSG of choice and enable relative URLs if they -aren't enabled already. -``` diff --git a/docs/howto/configure/add-hub-domains.md b/docs/howto/configure/add-hub-domains.md new file mode 100644 index 000000000..37f3a2d13 --- /dev/null +++ b/docs/howto/configure/add-hub-domains.md @@ -0,0 +1,36 @@ +# Add additional domains to a hub + +Existing pilot-hubs in the two 2i2c-managed clusters, have a subdomain created and assingned to them on creation, +that respects the following naming convention, based on which domain name and cluster they are part of: + +- `.pilot.2i2c.cloud` - for the ones in the 2i2c cluster and *pilot.2i2c.cloud* domain +- `.cloudbank.2i2c.cloud` - for the ones in the cloudbank cluster and *cloudbank.2i2c.cloud* domain + +But other domains can be easily linked to the same hub in a cluster if needed. + +Assuming there is a hub named `foo` in the `2i2c` cluster and we want to add the `foo.edu` domain to it, one would: + +1. **Point the `foo.edu` domain to the right cluster.** + + Create a [CNAME](https://en.wikipedia.org/wiki/CNAME_record) entry from the new domain, `foo.edu`, that points to the + existing `foo.pilot.2i2c.cloud`, where the `foo` hub already runs. + + This will map the new domain name, `foo.edu`, to the default one `foo.pilot.2i2c.cloud` - *the canonical name* and will + make sure `foo.edu` points to the right cluster, no matter which IP address the cluster has. + +2. **Point the `foo.edu` domain to the right hub.** + + Since all the hubs in a cluster are running at the same IP address, but are available at different subdomains, + we also need a way to specify which hub in this cluster we want the new domain and subsequent requests to point to. + + For this to happen we need to add the new domain as an ingress domain for this hub using the `hubs.yaml` configuration file. + This can be done by adding the new domain to the list in `hubs..domain`: + + ```yaml + - name: foo + cluster: 2i2c + domain: + - foo.pilot.2i2c.cloud # default domain + - foo.edu # additionl domain + (...) + ``` diff --git a/docs/howto/configure/auth-management.md b/docs/howto/configure/auth-management.md new file mode 100644 index 000000000..3cb0e3786 --- /dev/null +++ b/docs/howto/configure/auth-management.md @@ -0,0 +1,56 @@ +# Manage authentication + +[auth0](https://auth0.com) provides authentication for all hubs here. It can +be configured with many different [connections](https://auth0.com/docs/identityproviders) +that users can authenticate with - such as Google, GitHub, etc. + +So we want to manage authentication by: + +1. Explicitly listing the type of connection we want for this hub, via + `auth0.connection`. Currently common ones are `google-oauth2` for Google & + `github` for GitHub. *Users* of the hub will use this method to log in to + the hub. + + You can set the auth0 connector for a hub with: + + ```yaml + auth0: + connection: google-oauth2 + ``` + + Theoretically, every provider in [this list](https://auth0.com/docs/connections/identity-providers-social) + is supported. However, we've currently only tested this with Google + (`google-oauth2`) and GitHub (`github`) + +2. Explicitly list *admin users* for a given hub. These admin users will be the + only ones allowed to log in to begin with. They can use the JupyterHub + admin interface (available from their hub control panel) to explicitly allow + more users into the hub. This way, we don't need to be involved in explicitly + allowing users into hubs. + + In the admin interface, admin users can add users via a username appropriate + for the auth connector used. For GitHub, it's the username. For Google Auth, + it's the email address. + + You can set the admin interfaces for a hub like this: + + ```yaml + config: + jupyterhub: + auth: + # will be renamed allowedlist in future JupyterHub + whitelist: + users: + # WARNING: THESE USER LISTS MUST MATCH (for now) + - user1@gmail.com + - user2@gmail.com + admin: + users: + # WARNING: THESE USER LISTS MUST MATCH (for now) + - user1@gmail.com + - user2@gmail.com + ``` + +```{admonition} Switching auth +Switching authentication for a pre-existing hub will simply create new usernames. Any pre-existing users will no longer be able to access their accounts (although administrators will be able to do so). If you have pre-existing users and want to switch the hub authentication, rename the users to the new auth pattern (e.g. convert github handles to emails). +``` \ No newline at end of file diff --git a/docs/howto/configure/hub-config.md b/docs/howto/configure/hub-config.md new file mode 100644 index 000000000..10d20f26e --- /dev/null +++ b/docs/howto/configure/hub-config.md @@ -0,0 +1,17 @@ +# Configure each JupyterHub + +Each JupyterHub can use its own configuration via the `hubs.yaml` file. This configuration exists under `config.jupyterhub`. +This should be a valid [Zero to JupyterHub](https://z2jh.jupyter.org) configuration. For example, to set a custom memory limit for a hub, you would use: + +```yaml +config: + jupyterhub: + singleuser: + memory: + limit: 1G +``` + +Here are a few reference pages for JupyterHub Kubernetes configuration: + +- {ref}`z2jh:user-environment` +- {ref}`z2jh:user-resources` \ No newline at end of file diff --git a/docs/howto/configure/update-env.md b/docs/howto/configure/update-env.md new file mode 100644 index 000000000..2054ee2fa --- /dev/null +++ b/docs/howto/configure/update-env.md @@ -0,0 +1,22 @@ +# Update environment + +The user environments is specified via a `Dockerfile`, under `images/user` in +the git repository. Currently there is no automated image building - so you will +have to manually build & push it after making a change. + +1. Install pre-requisites: + * Docker + * A Python virtual environment. Install `requirements.txt` into it. + * The `gcloud` tool, authenticated to the `two-eye-two-see` project. + You need to run `gcloud auth configure-docker us-central1-docker.pkg.dev` + once as well. + +2. Make the changes you need to make to the environment, and git commit it. + +3. Run `python3 deploy.py build`. This will build the image and push it to + registry. It will tell you what the generated image tag is. + +4. Update `jupyterhub.singleuser.image.tag` in `hub/values.yaml` with this tag. + +5. Make a commit, make a PR and merge to master! This will deploy all the hubs + with the new image diff --git a/docs/howto/customize/configure-login-page.md b/docs/howto/customize/configure-login-page.md new file mode 100644 index 000000000..f86266049 --- /dev/null +++ b/docs/howto/customize/configure-login-page.md @@ -0,0 +1,9 @@ +# Configure the hub login page + +Each Hub deployed in a cluster has a collection of metadata about who it is deployed for, and who is responsible for running it. This is used to generate the **log-in page** for each hub and tailor it for the community. + +For an example, see [the log-in page of the staging hub](https://staging.pilot.2i2c.cloud/hub/login). + +The log-in pages are built with [the base template at this repository](https://github.com/2i2c-org/pilot-homepage). Values are inserted into each template based on each hub configuration. + +You may customize the configuration for a hub's homepage at `config.jupyterhub.homepage.templateVars`. Changing these values for a hub will make that hub's landing page update automatically. We recommend [using the `hubs.yaml` file as a reference](https://github.com/2i2c-org/pilot-hubs/blob/master/hubs.yaml). Copy the configuration from another hub, and then modify the contents to fit the new hub that is being configured. diff --git a/docs/custom-image.md b/docs/howto/customize/custom-image.md similarity index 99% rename from docs/custom-image.md rename to docs/howto/customize/custom-image.md index 8a416c78e..d30e08583 100644 --- a/docs/custom-image.md +++ b/docs/howto/customize/custom-image.md @@ -1,4 +1,4 @@ -# Using a custom image +# Use a custom hub image Pilot hubs use an image we curate as the default. This can be replaced with your own custom image fairly easily. However, custom images should be maintained diff --git a/docs/howto/customize/docs-service.md b/docs/howto/customize/docs-service.md new file mode 100644 index 000000000..188803145 --- /dev/null +++ b/docs/howto/customize/docs-service.md @@ -0,0 +1,32 @@ +# Connect static web content with the hub + +The 2i2c hubs can be configured to provide static web content as a [JupyterHub service](https://jupyterhub.readthedocs.io/en/stable/reference/services.html), available +at `https:///services/docs`. This can be a great tool to provide hub-specific documentation right from inside the hub. + +```{figure} ../../images/docs-service.png +``` + +To enable the docs service service for a hub: + +1. Mark it as *enabled* in `hubs.yaml`, by setting `hubs..config.docs_service.enabled` to *True*. +2. Specify the GitHub repository where the static HTML files are hosted, by setting `hubs..config.docs_service.repo`. +3. Specify the GitHub branch of the respository where the static HTML files are hosted, by setting `hubs..config.docs_service.branch`. + +Example config: + +```yaml + config: + docs_service: + enabled: true + repo: https://github.com/ + branch: +``` + +```{note} + +Depending on what Static Site Generator has been used to generate the website's static content, it **may** or **may not** use relative paths routing by default. +For example, [Sphinx](https://www.sphinx-doc.org/en/master/) handles relative paths by default, whereas, [Hugo](https://gohugo.io/) leaves all [relative URLs unchanged](https://gohugo.io/content-management/urls/#relative-urls). + +However, having relative URLS is a **must** in order for the hub docs service to work. Please check with the docs of your SSG of choice and enable relative URLs if they +aren't enabled already. +``` diff --git a/docs/howto/index.md b/docs/howto/index.md new file mode 100644 index 000000000..f85a64ecc --- /dev/null +++ b/docs/howto/index.md @@ -0,0 +1,39 @@ +# How-To Guides +How-To guides answer the question 'How do I...?' for a lot of topics. + +```{toctree} +:hidden: + +configure/hub-config.md +configure/auth-management.md +configure/add-hub-domains.md +configure/update-env.md +customize/custom-image.md +customize/docs-service.md +customize/configure-login-page.md +operate/add-hub.md +operate/cmd-access.md +operate/delete-hub.md +operate/grafana.md +operate/test-hub.md +``` + +## Hub configuration +```{toctree} +configure/hub-config.md +configure/auth-management.md +configure/add-hub-domains.md +configure/update-env.md +``` + +## Hub customization +```{toctree} +customize/custom-image.md +customize/docs-service.md +customize/configure-login-page.md +``` + +## Hub operation +```{toctree} +operate/index.md +``` diff --git a/docs/howto/operate/add-hub.md b/docs/howto/operate/add-hub.md new file mode 100644 index 000000000..fc4f70e6b --- /dev/null +++ b/docs/howto/operate/add-hub.md @@ -0,0 +1,7 @@ +# Add a new hub + +Adding a new hub requires that we do three things: + +1. [Create a new GitHub issue for the hub](https://github.com/2i2c-org/pilot-hubs/issues/new). +2. Create the hub via appending a new entry in the `hubs.yaml` file (see [](../configure/hub-config.md) for more information). +3. Start following [team process](team-process) around operating the hubs. diff --git a/docs/howto/operate/cmd-access.md b/docs/howto/operate/cmd-access.md new file mode 100644 index 000000000..839146f63 --- /dev/null +++ b/docs/howto/operate/cmd-access.md @@ -0,0 +1,72 @@ +# Gain `kubectl` & `helm` access to a hub + +Each of the hubs in the 2i2c Pilot runs on Google Cloud Platform and Kubernetes. +To access the Kubernetes objects (in order to inspect them or make changes), use +the `kubectl` command line tool. + +% TODO: Add something about what helm does here + +## Project Access + +First, you'll need to access the Google Cloud projects on which the hubs run. The most accurate name +of the project can be gleamed from `hubs.yaml` (under `gcp.project` for each cluster entry). Currently, +the projects are: + +| Cluster | Project Name | +| - | - | +| *.pilot.2i2c.cloud | `two-eye-two-see` | +| *.cloudbank.2i2c.cloud | `cb-1003-1696` | + +If you don't have access to these, please get in touch with 2i2c staff. + + +## Commandline tools installation + +You can do all this via [Google Cloud Shell](https://cloud.google.com/shell), +but might be easier to do this on your local machine. You'll need the following +tools installed: + +1. [gcloud](https://cloud.google.com/sdk) +2. [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) +3. [helm](https://helm.sh/) + +## Authenticating + +First, you need to [gcloud auth login](https://cloud.google.com/sdk/docs/authorizing#authorizing_with_a_user_account), +so you can perform `gcloud` operations. Next, you need to do [gcloud auth application-default login](https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login) +so `kubectl` and `helm` could use your auth credentials. + +## Fetch Cluster credentials + +For each cluster, you'll need to fetch credentials at least once with [gcloud container clusters get-credentials](https://cloud.google.com/sdk/gcloud/reference/container/clusters/get-credentials). + +```bash +gcloud container clusters get-credentials --region --project +``` + +You can get authoritative information for ``, `` and `` from +`hubs.yaml`. + +With that, `kubectl` and `helm` should now work! + +## (Optional) Access via Google Cloud Shell + +Instead of setting up the tools & authenticating locally, you can do all this via +[Google Cloud Shell](https://cloud.google.com/shell). It has all the tools installed, +and the authentication done. Instead of doing `gcloud container clusters get-credentials` +yourself, you can instead: + + +1. Go to the [Google Cloud Kubernetes Engine page](https://console.cloud.google.com/kubernetes/list) (for the appropriate project) + +2. Click on `Connect`, as seen in the figure below. + + ````{panels} + ```{figure} ../../images/gcp-k8s-dashboard.png + ``` + --- + ```{figure} ../../images/gcp-run-in-shell.png + ``` + ```` + +3. This will spin up an interactive cloud shell where you have `kubectl` access. diff --git a/docs/howto/operate/delete-hub.md b/docs/howto/operate/delete-hub.md new file mode 100644 index 000000000..85587f903 --- /dev/null +++ b/docs/howto/operate/delete-hub.md @@ -0,0 +1,8 @@ +# Delete a hub + +If you'd like to delete a hub, there are a few steps that we need to take: + +1. **Backup the hub database**. Backup the `jupyterhub.sqlite` db off the hub. +2. **Backup the home directory contents**. Especially if we think that users will want this information in the future (or if we plan to re-deploy a hub elsewhere). +3. **Delete the Helm namespace**. Run `helm -n delete `. +4. **Delete our Authentication entry**. If the hub hasn't been recreated anywhere, remove the entry from `auth0.com` diff --git a/docs/howto/operate/grafana.md b/docs/howto/operate/grafana.md new file mode 100644 index 000000000..9e7339166 --- /dev/null +++ b/docs/howto/operate/grafana.md @@ -0,0 +1,7 @@ +# Access the Hub Grafana Dashboards + +Each 2i2c Hub is set up with [a Prometheus server](https://prometheus.io/) to generate metrics and information about activity on the hub, and each cluster of hubs has a [Grafana deployment](https://grafana.com/) to ingest and visualize this data. + +The Grafana for each cluster can be accessed at `grafana..2i2c.cloud`. +For example, the pilot hubs are accessible at `grafana.pilot.2i2c.cloud`. You'll need +a username and password to access each one. Ask one of the 2i2c team members for access. diff --git a/docs/howto/operate/index.md b/docs/howto/operate/index.md new file mode 100644 index 000000000..2ddb45bb4 --- /dev/null +++ b/docs/howto/operate/index.md @@ -0,0 +1,16 @@ +# Operating the hubs + +Information about operating the hubs, debugging problems, and performing common actions. + +(team-process)= +## Team process for hub development and operation + +See the {ref}`tc:coordination:team-activity`. + +```{toctree} +add-hub.md +cmd-access.md +delete-hub.md +test-hub.md +grafana.md +``` diff --git a/docs/howto/operate/test-hub.md b/docs/howto/operate/test-hub.md new file mode 100644 index 000000000..33dfd9717 --- /dev/null +++ b/docs/howto/operate/test-hub.md @@ -0,0 +1,40 @@ +# Test the hub +You can deploy a new hub, or an existing one using the `deploy.py` script: + +* to deploy a specific hub + ``` bash + python3 deploy.py deploy + ``` + +* to deploy all pilot hubs: + ```bash + python3 deploy.py deploy + ``` + +When using the `deploy.py` script, the hub's heath being deployed is checked by default. + +```{note} +You can skip the health check by passing the `--skip-hub-health-test` flag to the `deploy.py` script. +``` +A hub is marked as "healthy" if it passes the custom template and the health `pytest` tests. + +## The custom template test + +Each pilot-hub has their own personalized JupyterHub login page. This test makes sure that the hub has loaded its custom login template by checking the presence of the instutional logo in the login page. + +```{figure} ../../images/staging-hub-login-page.png +``` + +## The Hub health test + +There are two types of test notebooks are ran on the hub, based on it's type: +* dask specific notebooks - *are ran on the the daskhub hubs* +* simple notebooks - *are ran on all the other types of hubs* + +This test, creates a new hub user called `deployment-service-check`, starts a server for them, and runs the test notebooks. It checks that the notebook runs to completion and the output cells have the expected value. +* If the health check passes, then the user's server is stopped and deleted. +* If the health check fails, then their user server will be left running, but it will get deleted together with the user in the next iteration. + +```{note} +If the `deploy.py` script is used to deploy all pilot hubs at once, then a failed hub health check will halt all further deployments! +``` diff --git a/docs/index.md b/docs/index.md index 77a87de25..37b903a11 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,10 +6,11 @@ All hub configuration is in `hubs.yaml`. You can add a new hub by adding an entry there, and pushing that to github. ```{toctree} +:maxdepth: 2 + structure -configure -operate -custom-image +howto/index +topic/index incidents/index ``` diff --git a/docs/operate.md b/docs/operate.md deleted file mode 100644 index c44648054..000000000 --- a/docs/operate.md +++ /dev/null @@ -1,147 +0,0 @@ -# Operating the hubs - -Information about operating the hubs, debugging problems, and performing common actions. - -(operate:team-process)= -## Team process for hub development and operation - -See the {ref}`tc:coordination:team-activity`. - -## Adding a new hub - -Adding a new hub requires that we do three things: - -1. [Create a new GitHub issue for the hub](https://github.com/2i2c-org/pilot-hubs/issues/new). -2. Create the hub via appending a new entry in the `hubs.yaml` file (see [](configure.md) for more information). -3. Start following [team process](operate:team-process) around operating the hubs. - - -## Gain `kubectl` & `helm` access to a hub - -Each of the hubs in the 2i2c Pilot runs on Google Cloud Platform and Kubernetes. -To access the Kubernetes objects (in order to inspect them or make changes), use -the `kubectl` command line tool. - -% TODO: Add something about what helm does here - -### Project Access - -First, you'll need to access the Google Cloud projects on which the hubs run. The most accurate name -of the project can be gleamed from `hubs.yaml` (under `gcp.project` for each cluster entry). Currently, -the projects are: - -| Cluster | Project Name | -| - | - | -| *.pilot.2i2c.cloud | `two-eye-two-see` | -| *.cloudbank.2i2c.cloud | `cb-1003-1696` | - -If you don't have access to these, please get in touch with 2i2c staff. - -### Commandline tools installation - -You can do all this via [Google Cloud Shell](https://cloud.google.com/shell), -but might be easier to do this on your local machine. You'll need the following -tools installed: - -1. [gcloud](https://cloud.google.com/sdk) -2. [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) -3. [helm](https://helm.sh/) - -### Authenticating - -First, you need to [gcloud auth login](https://cloud.google.com/sdk/docs/authorizing#authorizing_with_a_user_account), -so you can perform `gcloud` operations. Next, you need to do [gcloud auth application-default login](https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login) -so `kubectl` and `helm` could use your auth credentials. - -### Fetch Cluster credentials - -For each cluster, you'll need to fetch credentials at least once with [gcloud container clusters get-credentials](https://cloud.google.com/sdk/gcloud/reference/container/clusters/get-credentials). - -```bash -gcloud container clusters get-credentials --region --project -``` - -You can get authoritative information for ``, `` and `` from -`hubs.yaml`. - -With that, `kubectl` and `helm` should now work! - -### (Optional) Access via Google Cloud Shell - -Instead of setting up the tools & authenticating locally, you can do all this via -[Google Cloud Shell](https://cloud.google.com/shell). It has all the tools installed, -and the authentication done. Instead of doing `gcloud container clusters get-credentials` -yourself, you can instead: - - -1. Go to the [Google Cloud Kubernetes Engine page](https://console.cloud.google.com/kubernetes/list) (for the appropriate project) - -2. Click on `Connect`, as seen in the figure below. - - ````{panels} - ```{figure} images/gcp-k8s-dashboard.png - ``` - --- - ```{figure} images/gcp-run-in-shell.png - ``` - ```` - -3. This will spin up an interactive cloud shell where you have `kubectl` access. - -## Delete a hub - -If you'd like to delete a hub, there are a few steps that we need to take: - -1. **Backup the hub database**. Backup the `jupyterhub.sqlite` db off the hub. -2. **Backup the home directory contents**. Especially if we think that users will want this information in the future (or if we plan to re-deploy a hub elsewhere). -3. **Delete the Helm namespace**. Run `helm -n delete `. -4. **Delete our Authentication entry**. If the hub hasn't been recreated anywhere, remove the entry from `auth0.com` - -## Access the Hub Grafana Dashboards - -Each 2i2c Hub is set up with [a Prometheus server](https://prometheus.io/) to generate metrics and information about activity on the hub, and each cluster of hubs has a [Grafana deployment](https://grafana.com/) to ingest and visualize this data. - -The Grafana for each cluster can be accessed at `grafana..2i2c.cloud`. -For example, the pilot hubs are accessible at `grafana.pilot.2i2c.cloud`. You'll need -a username and password to access each one. Ask one of the 2i2c team members for access. - -## Testing the hub -You can deploy a new hub, or an existing one using the `deploy.py` script: - -* to deploy a specific hub - ``` bash - python3 deploy.py deploy - ``` - -* to deploy all pilot hubs: - ```bash - python3 deploy.py deploy - ``` - -When using the `deploy.py` script, the hub's heath being deployed is checked by default. - -```{note} -You can skip the health check by passing the `--skip-hub-health-test` flag to the `deploy.py` script. -``` -A hub is marked as "healthy" if it passes the custom template and the health `pytest` tests. - -### The custom template test - -Each pilot-hub has their own personalized JupyterHub login page. This test makes sure that the hub has loaded its custom login template by checking the presence of the instutional logo in the login page. - -```{figure} images/staging-hub-login-page.png -``` - -### The Hub health test - -There are two types of test notebooks are ran on the hub, based on it's type: -* dask specific notebooks - *are ran on the the daskhub hubs* -* simple notebooks - *are ran on all the other types of hubs* - -This test, creates a new hub user called `deployment-service-check`, starts a server for them, and runs the test notebooks. It checks that the notebook runs to completion and the output cells have the expected value. -* If the health check passes, then the user's server is stopped and deleted. -* If the health check fails, then their user server will be left running, but it will get deleted together with the user in the next iteration. - -```{note} -If the `deploy.py` script is used to deploy all pilot hubs at once, then a failed hub health check will halt all further deployments! -``` diff --git a/docs/structure.md b/docs/structure.md index c7728eb9d..b8bc18711 100644 --- a/docs/structure.md +++ b/docs/structure.md @@ -39,7 +39,7 @@ We should provide at least the following kinds of documentation: heavily driven by the opinionated choices we have made while building it. 2. **How-to guides** to help users accomplish a specific well defined task, especially if it is something they know how to do in a different system. - The documentation titles should always be of the form **How do I ?** + The documentation titles should always be of the form **How do I `<title>`?** 3. **Component reference** to inform users where to find documentation for the component they might be having issues with. Most users are unfamiliar with the intricate details of what component does what, so might not be @@ -70,7 +70,7 @@ of documentaiton. with a link to documentation for 2i2c engineers . 2. **How-to guides** to help admins accomplish very specific tasks during the course of hub usage. Their titles should always be of the form - **How do I <title>?**. + **How do I `<title>`?**. This documentation should exist in the [2i2c-org/pilot](https://github.com/2i2c-org/pilot) repository, available at [2i2c.org/pilot](https://2i2c.org/pilot/) @@ -93,7 +93,7 @@ Here are some contexts where they would need documentation. pre-requisite knowledge and how it can be acquired. 2. **How-to guides** for performing common tasks that have not been automated yet. Their titles should always be of the form - **How do I <title>?** + **How do I `<title>`?** 3. **Topic guides** 3. **References**, describing in detail parts of our infrastructure and its configuration. This should ideally be kept in the code describing diff --git a/docs/topic/cluster-config.md b/docs/topic/cluster-config.md new file mode 100644 index 000000000..e24b53b36 --- /dev/null +++ b/docs/topic/cluster-config.md @@ -0,0 +1,14 @@ +# Cluster configuration reference + +At the top level of `hubs.yaml` is a list of **clusters**. Each cluster is a cloud deployment (for example, a Google project) that can have one or more hubs deployed inside it. + +Clusters have some basic configurability: + +`name` +: A string that uniquely identifies this cluster + +`image_repo` +: The base **user image** that all hubs will use in this cluster. + +`provider` +: The cloud provider for this cluster (e.g. `gcp`). diff --git a/docs/topic/defaults.md b/docs/topic/defaults.md new file mode 100644 index 000000000..4e5ca6f88 --- /dev/null +++ b/docs/topic/defaults.md @@ -0,0 +1,10 @@ +# Default options + +Part of being 'low touch' is to provide default options that we think might +work for most people. These are specified in `hub/values.yaml` in the repository. +We list some common ones here. + +1. **Memory Limit** of 1G per student, with a guarantee of 256M. This means that + everyone will be *guaranteed* 256M of memory, and most likely will have access + to 1G of memory. But they can't use more than 1G of memory - their kernels and + processes will die if they use more than this. diff --git a/docs/topic/hub-config.md b/docs/topic/hub-config.md new file mode 100644 index 000000000..9e54c4fbc --- /dev/null +++ b/docs/topic/hub-config.md @@ -0,0 +1,26 @@ +# Hub configuration reference + +`clusters.hubs:` is a list of hubs to be deployed in each cluster. +Each hub is a dictionary that can consist of the following keys: + +`name` +: A string that uniquely identifies this hub + +`cluster` +: The cluster where this hub will be deployed. + +`domain` +: Domain this hub should be available at. Currently, must be a subdomain + of a domain that has been pre-configured to point to our cluster. Currently, + that is `.<clustername>.2i2c.cloud` + +`auth0` +: We use [auth0](https://auth0.com/) for authentication, and it supports + many [connections](https://auth0.com/docs/identityproviders). Currently, + only `connector` property is supported - see section on *Authentication* + for more information. + +`config.jupyterhub` +: Any arbitrary [zero to jupyterhub](https://z2jh.jupyter.org) configuration + can be passed here. Most common is auth setup, memory / CPU restrictions, + and max number of active users. See [](../howto/configure/hub-config.md) for more info. \ No newline at end of file diff --git a/docs/topic/hub-templates.md b/docs/topic/hub-templates.md new file mode 100644 index 000000000..68471bb00 --- /dev/null +++ b/docs/topic/hub-templates.md @@ -0,0 +1,59 @@ +# Hub templates +The hubs are configured and deployed using *hub templates*. Because each hub +type can be described by a template, with its own deployment chart, a hierarchy +of hub types can be built and this makes development and usage easier. + +The graphic below, shows the relationship between the hub templates and the other +config files and how they are merged together when deploying a pilot hub. + +```{figure} ../images/config-flow.png +``` +% The editable version of the diagram is here: https://docs.google.com/presentation/d/1WZKTe5TSDU-5zA4NnNEPsKfgjaBzUqMgdPLTnz-Yb94/edit?usp=sharing + +Currently there are three hub templates available: +- `base-hub` + + The **base-hub template** is the template that the other templates "inherit" and configure. + It provides a base JupyterHub, user storage and culling configuration that satisfies most of the + pilot hubs usage requirements. + +- `ephemeral-hub` + + The **ephemeral-hub template** helps deploying temporary, transient binder-style hubs. + - Doesn't require any user authentication. + - Permits limiting of resources: + * memory / CPU limits + * maximum number of concurrent user servers + - Has more aggressive culling: + - Stops server after 30min of idleness + - Desn't let servers run for more than 8h + - Has no persistent storage + - Doesn't use or configures a home page template + +- `daskhub` + + The **daskhub template** helps deploying dask-enabled hubs. + - Installs [dask-gateway](https://gateway.dask.org/) + - Defaults to using a [PANGEO image](https://pangeo-data.github.io/pangeo-stacks/) + - Enables outgoing SSH + +## Use the templates to deploy a new hub +To deploy a new hub, you only need to add and configure it through `hubs.yaml` configuration file. +This configuration file allows specifying options like the type of template to use for the hub being added, +the hub domain, how the JupyterHub landing page will look like and authentication preferences. + +Because the templates are structured in a **hierarchical** model, so are their helm charts. +The [jupyterhub helm chart](https://jupyterhub.github.io/helm-chart/) is a subchart of the base-hub and +the base-hub chart along with the [dask-gateway](https://dask.org/dask-gateway-helm-repo/) one are +subcharts of the daskhub. The ephemeral-hub chart also subcharts the base-hub. + +**Visual of the helm-chart hierarchy:** +```{figure} ../images/helm-charts-hierarchy.png +``` +% The editable version of the diagram is here: https://docs.google.com/presentation/d/1KMyrTd3wdR715tPGuzIHkHqScXBlLpeiksIM2x7EI0g/edit?usp=sharing + +This hierachy is the reason why when adding a new hub using the `daskhub` or the `ephemeral-hub` template, the jupyterhub +specific configuration in `hubs.yaml` needs to be nested under a `base-hub` key, indicating that we are overriding configuration +from the *base-hub/jupyterhub* parent chart. + +Read more about subcharts and how to configure them in the [Helm docs](https://helm.sh/docs/chart_template_guide/subcharts_and_globals/#overriding-values-from-a-parent-chart). \ No newline at end of file diff --git a/docs/topic/index.md b/docs/topic/index.md new file mode 100644 index 000000000..d599ac7f7 --- /dev/null +++ b/docs/topic/index.md @@ -0,0 +1,9 @@ +# Topic Guides +Topic guides provide in-depth explanations of specific topics. + +```{toctree} +cluster-config.md +hub-config.md +defaults.md +hub-templates.md +```