Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Who this guide is for

🧑‍💻 Are you a JupyterHub user who wants a quick tour of the usage quota system? See the quickstart guide for Users.

🔧 Are you a JupyterHub admin who wants to quickly understand how to deploy the usage quota system? See the quickstart guide for Admins.

Users

Background

Usage quotas are an effective safeguard against excessive resource consumption and spiralling costs, especially in a cloud computing environment. They can be applied to resources such as:

Usage Quota Dashboard

You can view any usage quotas applied to your account with the Usage Quota Dashboard.

Home storage

When you have run out of home storage, you may be unable to launch your server session the next time. If this happens, contact your JupyterHub admin for help with deleting stale data.

Compute

When you have run out of compute quota, your server launch will be denied the next time you try. The compute quota system operates on a rolling window, so your usage expires at a continual rate (rather than a hard reset e.g. at the beginning of the month). A retry time will be displayed when you try to launch a server showing you when compute quota is available to you again. If you require more compute quota, contact your JupyterHub admin for help.

Admins

Prerequisites

This quickstart guide assumes that the reader is running a Zero to JupyterHub deployment with a Prometheus instance scraping metrics fromkube-state-metrics and optionally jupyterhub-home-nfs for home storage quotas (see Explanation - Overview), and has some knowledge of

Installing JupyterHub with jupyterhub-usage-quotas

  1. Create custom Hub image with jupyterhub-usage-quotas installed. See Services — Zero to JupyterHub with Kubernetes documentation for details on how to do this.

    • Make sure you list all of the dependencies you require for the Hub image, e.g. in a requirements.txt file

    • You can install the package with jupyterhub-usage-quotas or you can optionally install the package with jupyterhub-usage-quotas[service] to include the Usage Quota Dashboard

    • See the example below

  2. Build and push your custom Hub image to a registry and make a note of the image tag.

Minimal z2jh configuration example

Authentication

Usage quota policies are applied to user groups, therefore this information needs to be available in a user’s auth_state. This minimal working example assumes a z2jh deployment that uses OAuthenticator to handle authentication, specifically the Generic OAuthenticator. Make sure that you set the appropriate configuration for your authenticator in addition to the minimal example below. See User Group Management for more details.

Home Storage Quotas

If you are using home storage quotas, then make sure that you set the appropriate configuration for jupyterhub-home-nfs in addition to the minimal example below.

Common Configuration

The jupyterhub-usage-quotas library is composed of two main modules:

  1. The manager that enforces compute quotas at server launch time

  2. The service that runs the user-facing usage quota dashboard.

Configuration common to both modules include:

You can mount this common configuration under extraFiles so that they can be referenced by both modules.

Secrets Management

The usage quota system relies on configuring sensitive secrets, such as session keys and credentials, including:

You can also mount this secret configuration under extraFiles so that they can be referenced by both modules.

Minimal Example

# config.yaml

hub:
  image:
    name: myregistry/my-custom-hub-image
    tag: <image-tag>
  config:
    JupyterHub:
      authenticator_class: generic-oauth
    GenericOAuthenticator:
      manage_groups: true
      enable_auth_state: true
      scope:
        - group-0
      auth_state_groups_key: scope
    UsageQuotaManager:
      scope_backup_strategy:
        intersection: min
      policy:
        - resource: memory
          limit:
            value: 1000
            unit: GiB-hours
          window: 7
          scope:
            group:
              - group-0
      failover_open: false
    extraConfig:
      00-usage-quota: |
        from jupyterhub_usage_quotas import setup_usage_quotas
        setup_usage_quotas(c)
    extraFiles:
      usage_quota_config:
        mountPath: /usr/local/etc/jupyterhub/jupyterhub_config.d/jupyterhub_usage_quota_config.py
        stringData: |
          c.UsageConfig.prometheus_url: "http://<prometheus-service-name>.<k8s-prometheus-namespace>.svc.cluster.local"
          c.UsageConfig.hub_namespace: "<k8s-hub-namespace>"
  services:
    usage-quota:
      url: http://hub:9000
      display: false
      oauth_no_confirm: true
      command:
        - python3
        - -m
        - jupyterhub_usage_quotas.services.usage_viewer
          - --config-files=/usr/local/etc/jupyterhub/jupyterhub_config.d/jupyterhub_usage_quota_config.py
          - --config-files=/usr/local/etc/jupyterhub/jupyterhub_config.d/jupyterhub_usage_quota_config_secret.py
  loadRoles:
    usage-quota-service:
      scopes:
        - read:users
      services:
        - usage-quota
      user:
        scopes:
          - self
          - access:services!service=usage-quota
  networkPolicy:
    ingress:
      - ports:
          - port: 9000
        from:
          # Allow traffic from the proxy api pod
          - podSelector:
              matchLabels:
                hub.jupyter.org/network-access-hub: "true"
          # Allow traffic from the hub pod itself for Jupyterhub's internal healthchecks for hub managed services.
          - podSelector:
              matchLabels:
                app.kubernetes.io/component: hub
                app.kubernetes.io/name: jupyterhub
      - ports:
        - port: 8081
        from:
        # Allow traffic from the hub pod itself for oauth calls from the usage-quota service to the hub api.
        - podSelector:
            matchLabels:
              app.kubernetes.io/component: hub
              app.kubernetes.io/name: jupyterhub
  service:
    extraPorts:
      - port: 9000
        targetPort: 9000
        name: usage-quota
  # The proxy.chp.networkPolicy.egress configuration below is required for the usage-quota dashboard service to be accessible for users.
  proxy:
    chp:
      networkPolicy:
        egress:
          - to:
              - podSelector:
                  matchLabels:
                    app.kubernetes.io/name: jupyterhub
                    app.kubernetes.io/component: hub
            ports:
              - port: 9000
# enc-config.yaml
# Note: this contains secrets so make sure you encrypt this file if using a version control system

hub:
  extraFiles:
    usage_quota_config_secret:
      mountPath: /usr/local/etc/jupyterhub/jupyterhub_config.d/jupyterhub_usage_quota_config_secret.py
      stringData: |
        c.UsageConfig.prometheus_auth = {
          "username": "<prometheus_username>",
          "password": "<prometheus_password>",
        },
        c.UsageViewer.session_secret_key: "<use-a-secure-key-in-production>"

See Configuration for a full list of configuration options.