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
Building images
Installing JupyterHub with jupyterhub-usage-quotas¶
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.txtfileYou can install the package with
jupyterhub-usage-quotasor you can optionally install the package withjupyterhub-usage-quotas[service]to include the Usage Quota DashboardSee the example below
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:
The manager that enforces compute quotas at server launch time
The service that runs the user-facing usage quota dashboard.
Configuration common to both modules include:
c.UsageConfig.prometheus_url: the server url of the Prometheus instance that is used as a source of truth for usage datac.UsageConfig.hub_namespace: the Kubernetes namespace where the Hub pod is running
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:
c.UsageConfig.prometheus_auth: credentials for the Prometheus serverc.UsageViewer.secret_session_key: maintain a secure session with the usage quotas dashboard without needing to log in again.
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.