diff --git a/jupyter/base/charts/jupyterhub/Chart.yaml b/jupyter/base/charts/jupyterhub/Chart.yaml index eaa3033..8cee39a 100644 --- a/jupyter/base/charts/jupyterhub/Chart.yaml +++ b/jupyter/base/charts/jupyterhub/Chart.yaml @@ -1,27 +1,27 @@ annotations: artifacthub.io/images: | - - image: quay.io/jupyterhub/configurable-http-proxy:4.6.1 + - image: quay.io/jupyterhub/configurable-http-proxy:4.6.2 name: configurable-http-proxy - - image: quay.io/jupyterhub/k8s-hub:3.2.1 + - image: quay.io/jupyterhub/k8s-hub:4.0.0 name: k8s-hub - - image: quay.io/jupyterhub/k8s-image-awaiter:3.2.1 + - image: quay.io/jupyterhub/k8s-image-awaiter:4.0.0 name: k8s-image-awaiter - - image: quay.io/jupyterhub/k8s-network-tools:3.2.1 + - image: quay.io/jupyterhub/k8s-network-tools:4.0.0 name: k8s-network-tools - - image: quay.io/jupyterhub/k8s-secret-sync:3.2.1 + - image: quay.io/jupyterhub/k8s-secret-sync:4.0.0 name: k8s-secret-sync - - image: quay.io/jupyterhub/k8s-singleuser-sample:3.2.1 + - image: quay.io/jupyterhub/k8s-singleuser-sample:4.0.0 name: k8s-singleuser-sample - - image: registry.k8s.io/kube-scheduler:v1.26.11 + - image: registry.k8s.io/kube-scheduler:v1.30.6 name: kube-scheduler - - image: registry.k8s.io/pause:3.9 + - image: registry.k8s.io/pause:3.10 name: pause - - image: registry.k8s.io/pause:3.9 + - image: registry.k8s.io/pause:3.10 name: pause - - image: traefik:v2.10.5 + - image: traefik:v3.2.0 name: traefik apiVersion: v2 -appVersion: 4.0.2 +appVersion: 5.2.1 description: Multi-user Jupyter installation home: https://z2jh.jupyter.org icon: https://hub.jupyter.org/helm-chart/images/hublogo.svg @@ -29,7 +29,7 @@ keywords: - jupyter - jupyterhub - z2jh -kubeVersion: '>=1.23.0-0' +kubeVersion: '>=1.28.0-0' maintainers: - email: erik@sundellopensource.se name: Erik Sundell @@ -38,4 +38,4 @@ maintainers: name: jupyterhub sources: - https://github.com/jupyterhub/zero-to-jupyterhub-k8s -version: 3.2.1 +version: 4.0.0 diff --git a/jupyter/base/charts/jupyterhub/files/hub/jupyterhub_config.py b/jupyter/base/charts/jupyterhub/files/hub/jupyterhub_config.py index 7047173..ad742ed 100644 --- a/jupyter/base/charts/jupyterhub/files/hub/jupyterhub_config.py +++ b/jupyter/base/charts/jupyterhub/files/hub/jupyterhub_config.py @@ -107,28 +107,35 @@ c.JupyterHub.hub_connect_url = ( ) # implement common labels -# this duplicates the jupyterhub.commonLabels helper +# This mimics the jupyterhub.commonLabels helper, but declares managed-by to +# kubespawner instead of helm. +# +# The labels app and release are old labels enabled to be deleted in z2jh 5, but +# for now retained to avoid a breaking change in z2jh 4 that would force user +# server restarts. Restarts would be required because NetworkPolicy resources +# must select old/new pods with labels that then needs to be seen on both +# old/new pods, and we want these resources to keep functioning for old/new user +# server pods during an upgrade. +# common_labels = c.KubeSpawner.common_labels = {} -common_labels["app"] = get_config( +common_labels["app.kubernetes.io/name"] = common_labels["app"] = get_config( "nameOverride", default=get_config("Chart.Name", "jupyterhub"), ) -common_labels["heritage"] = "jupyterhub" +release = get_config("Release.Name") +if release: + common_labels["app.kubernetes.io/instance"] = common_labels["release"] = release chart_name = get_config("Chart.Name") chart_version = get_config("Chart.Version") if chart_name and chart_version: - common_labels["chart"] = "{}-{}".format( - chart_name, - chart_version.replace("+", "_"), + common_labels["helm.sh/chart"] = common_labels["chart"] = ( + f"{chart_name}-{chart_version.replace('+', '_')}" ) -release = get_config("Release.Name") -if release: - common_labels["release"] = release +common_labels["app.kubernetes.io/managed-by"] = "kubespawner" c.KubeSpawner.namespace = os.environ.get("POD_NAMESPACE", "default") # Max number of consecutive failures before the Hub restarts itself -# requires jupyterhub 0.9.2 set_config_if_not_none( c.Spawner, "consecutive_failure_limit", @@ -249,7 +256,8 @@ if tolerations: storage_type = get_config("singleuser.storage.type") if storage_type == "dynamic": pvc_name_template = get_config("singleuser.storage.dynamic.pvcNameTemplate") - c.KubeSpawner.pvc_name_template = pvc_name_template + if pvc_name_template: + c.KubeSpawner.pvc_name_template = pvc_name_template volume_name_template = get_config("singleuser.storage.dynamic.volumeNameTemplate") c.KubeSpawner.storage_pvc_ensure = True set_config_if_not_none( @@ -268,13 +276,14 @@ if storage_type == "dynamic": c.KubeSpawner.volumes = [ { "name": volume_name_template, - "persistentVolumeClaim": {"claimName": pvc_name_template}, + "persistentVolumeClaim": {"claimName": "{pvc_name}"}, } ] c.KubeSpawner.volume_mounts = [ { "mountPath": get_config("singleuser.storage.homeMountPath"), "name": volume_name_template, + "subPath": get_config("singleuser.storage.dynamic.subPath"), } ] elif storage_type == "static": diff --git a/jupyter/base/charts/jupyterhub/files/hub/z2jh.py b/jupyter/base/charts/jupyterhub/files/hub/z2jh.py index 3735169..f4d7be6 100644 --- a/jupyter/base/charts/jupyterhub/files/hub/z2jh.py +++ b/jupyter/base/charts/jupyterhub/files/hub/z2jh.py @@ -3,6 +3,7 @@ Utility methods for use in jupyterhub_config.py and dynamic subconfigs. Methods here can be imported by extraConfig in values.yaml """ + import os from collections.abc import Mapping from functools import lru_cache diff --git a/jupyter/base/charts/jupyterhub/templates/_helpers.tpl b/jupyter/base/charts/jupyterhub/templates/_helpers.tpl index 5cc5e6d..693bd65 100644 --- a/jupyter/base/charts/jupyterhub/templates/_helpers.tpl +++ b/jupyter/base/charts/jupyterhub/templates/_helpers.tpl @@ -48,7 +48,6 @@ - commonLabels | uses appLabel - labels | uses commonLabels - matchLabels | uses labels - - podCullerSelector | uses matchLabels ## Example usage @@ -112,31 +111,62 @@ {{- /* jupyterhub.commonLabels: Foundation for "jupyterhub.labels". - Provides labels: app, release, (chart and heritage). + + Provides old labels: + app + release + chart (omitted for matchLabels) + heritage (omitted for matchLabels) + Provides modern labels (omitted for matchLabels): + app.kubernetes.io/name ("app") + app.kubernetes.io/instance ("release") + helm.sh/chart ("chart") + app.kubernetes.io/managed-by ("heritage") */}} {{- define "jupyterhub.commonLabels" -}} -app: {{ .appLabel | default (include "jupyterhub.appLabel" .) }} -release: {{ .Release.Name }} +app: {{ .appLabel | default (include "jupyterhub.appLabel" .) | quote }} +release: {{ .Release.Name | quote }} {{- if not .matchLabels }} chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} -heritage: {{ .heritageLabel | default .Release.Service }} +heritage: {{ .Release.Service }} +app.kubernetes.io/name: {{ .appLabel | default (include "jupyterhub.appLabel" .) | quote }} +app.kubernetes.io/instance: {{ .Release.Name | quote }} +helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} {{- end }} {{- /* jupyterhub.labels: - Provides labels: component, app, release, (chart and heritage). + Provides old labels: + component + app + release + chart (omitted for matchLabels) + heritage (omitted for matchLabels) + Provides modern labels (omitted for matchLabels): + app.kubernetes.io/component ("component") + app.kubernetes.io/name ("app") + app.kubernetes.io/instance release ("release") + helm.sh/chart ("chart") + app.kubernetes.io/managed-by ("heritage") */}} {{- define "jupyterhub.labels" -}} component: {{ include "jupyterhub.componentLabel" . }} +{{- if not .matchLabels }} +app.kubernetes.io/component: {{ include "jupyterhub.componentLabel" . }} +{{- end }} {{ include "jupyterhub.commonLabels" . }} {{- end }} {{- /* jupyterhub.matchLabels: - Used to provide pod selection labels: component, app, release. + Provides old labels: + component + app + release */}} {{- define "jupyterhub.matchLabels" -}} {{- $_ := merge (dict "matchLabels" true) . -}} diff --git a/jupyter/base/charts/jupyterhub/templates/hub/deployment.yaml b/jupyter/base/charts/jupyterhub/templates/hub/deployment.yaml index 359e981..53eb355 100644 --- a/jupyter/base/charts/jupyterhub/templates/hub/deployment.yaml +++ b/jupyter/base/charts/jupyterhub/templates/hub/deployment.yaml @@ -5,7 +5,7 @@ metadata: labels: {{- include "jupyterhub.labels" . | nindent 4 }} spec: - {{- if typeIs "int" .Values.hub.revisionHistoryLimit }} + {{- if not (typeIs "" .Values.hub.revisionHistoryLimit) }} revisionHistoryLimit: {{ .Values.hub.revisionHistoryLimit }} {{- end }} replicas: 1 @@ -97,9 +97,6 @@ spec: {{- . | toYaml | nindent 8 }} {{- end }} containers: - {{- with .Values.hub.extraContainers }} - {{- . | toYaml | nindent 8 }} - {{- end }} - name: hub image: {{ .Values.hub.image.name }}:{{ .Values.hub.image.tag }} {{- with .Values.hub.command }} @@ -244,6 +241,9 @@ spec: path: {{ .Values.hub.baseUrl | trimSuffix "/" }}/hub/health port: http {{- end }} + {{- with .Values.hub.extraContainers }} + {{- . | toYaml | nindent 8 }} + {{- end }} {{- with .Values.hub.extraPodSpec }} {{- . | toYaml | nindent 6 }} {{- end }} diff --git a/jupyter/base/charts/jupyterhub/templates/hub/secret.yaml b/jupyter/base/charts/jupyterhub/templates/hub/secret.yaml index 851bda0..d1d0c80 100644 --- a/jupyter/base/charts/jupyterhub/templates/hub/secret.yaml +++ b/jupyter/base/charts/jupyterhub/templates/hub/secret.yaml @@ -8,7 +8,7 @@ type: Opaque data: {{- $values := merge dict .Values }} {{- /* also passthrough subset of Chart / Release */}} - {{- $_ := set $values "Chart" (dict "Name" .Chart.Name "Version" .Chart.Version) }} + {{- $_ := set $values "Chart" (dict "Name" .Chart.Name "Version" .Chart.Version "AppVersion" .Chart.AppVersion) }} {{- $_ := set $values "Release" (pick .Release "Name" "Namespace" "Service") }} values.yaml: {{ $values | toYaml | b64enc | quote }} diff --git a/jupyter/base/charts/jupyterhub/templates/hub/service.yaml b/jupyter/base/charts/jupyterhub/templates/hub/service.yaml index 13f80b5..5dcc0af 100644 --- a/jupyter/base/charts/jupyterhub/templates/hub/service.yaml +++ b/jupyter/base/charts/jupyterhub/templates/hub/service.yaml @@ -31,6 +31,9 @@ spec: {{- with .Values.hub.service.ports.nodePort }} nodePort: {{ . }} {{- end }} + {{- with .Values.hub.service.ports.appProtocol }} + appProtocol: {{ . }} + {{- end }} {{- with .Values.hub.service.extraPorts }} {{- . | toYaml | nindent 4 }} diff --git a/jupyter/base/charts/jupyterhub/templates/image-puller/_helpers-daemonset.tpl b/jupyter/base/charts/jupyterhub/templates/image-puller/_helpers-daemonset.tpl index 610f8bd..16213b0 100644 --- a/jupyter/base/charts/jupyterhub/templates/image-puller/_helpers-daemonset.tpl +++ b/jupyter/base/charts/jupyterhub/templates/image-puller/_helpers-daemonset.tpl @@ -34,7 +34,7 @@ spec: type: RollingUpdate rollingUpdate: maxUnavailable: 100% - {{- if typeIs "int" .Values.prePuller.revisionHistoryLimit }} + {{- if not (typeIs "" .Values.prePuller.revisionHistoryLimit) }} revisionHistoryLimit: {{ .Values.prePuller.revisionHistoryLimit }} {{- end }} template: diff --git a/jupyter/base/charts/jupyterhub/templates/ingress.yaml b/jupyter/base/charts/jupyterhub/templates/ingress.yaml index 91f96f4..090b2ed 100644 --- a/jupyter/base/charts/jupyterhub/templates/ingress.yaml +++ b/jupyter/base/charts/jupyterhub/templates/ingress.yaml @@ -24,6 +24,9 @@ spec: name: {{ include "jupyterhub.proxy-public.fullname" $ }} port: name: http + {{- with $.Values.ingress.extraPaths }} + {{- . | toYaml | nindent 10 }} + {{- end }} {{- if $host }} host: {{ $host | quote }} {{- end }} diff --git a/jupyter/base/charts/jupyterhub/templates/proxy/autohttps/deployment.yaml b/jupyter/base/charts/jupyterhub/templates/proxy/autohttps/deployment.yaml index f76f3ef..53e0736 100644 --- a/jupyter/base/charts/jupyterhub/templates/proxy/autohttps/deployment.yaml +++ b/jupyter/base/charts/jupyterhub/templates/proxy/autohttps/deployment.yaml @@ -8,7 +8,7 @@ metadata: labels: {{- include "jupyterhub.labels" . | nindent 4 }} spec: - {{- if typeIs "int" .Values.proxy.traefik.revisionHistoryLimit }} + {{- if not (typeIs "" .Values.proxy.traefik.revisionHistoryLimit) }} revisionHistoryLimit: {{ .Values.proxy.traefik.revisionHistoryLimit }} {{- end }} replicas: 1 @@ -130,10 +130,10 @@ spec: {{- end }} args: - watch-save - - --label=app={{ include "jupyterhub.appLabel" . }} - - --label=release={{ .Release.Name }} - - --label=chart={{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - - --label=heritage=secret-sync + - --label=app.kubernetes.io/name={{ include "jupyterhub.appLabel" . }} + - --label=app.kubernetes.io/instance={{ .Release.Name }} + - --label=helm.sh/chart={{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + - --label=app.kubernetes.io/managed-by=secret-sync - {{ include "jupyterhub.proxy-public-tls.fullname" . }} - acme.json - /etc/acme/acme.json diff --git a/jupyter/base/charts/jupyterhub/templates/proxy/deployment.yaml b/jupyter/base/charts/jupyterhub/templates/proxy/deployment.yaml index 2b35382..d5a9878 100644 --- a/jupyter/base/charts/jupyterhub/templates/proxy/deployment.yaml +++ b/jupyter/base/charts/jupyterhub/templates/proxy/deployment.yaml @@ -7,7 +7,7 @@ metadata: labels: {{- include "jupyterhub.labels" . | nindent 4 }} spec: - {{- if typeIs "int" .Values.proxy.chp.revisionHistoryLimit }} + {{- if not (typeIs "" .Values.proxy.chp.revisionHistoryLimit) }} revisionHistoryLimit: {{ .Values.proxy.chp.revisionHistoryLimit }} {{- end }} replicas: 1 @@ -100,6 +100,9 @@ spec: {{- if .Values.debug.enabled }} - --log-level=debug {{- end }} + {{- if .Values.hub.config.JupyterHub.subdomain_host }} + - --host-routing + {{- end }} {{- range .Values.proxy.chp.extraCommandLineFlags }} - {{ tpl . $ }} {{- end }} diff --git a/jupyter/base/charts/jupyterhub/templates/scheduling/user-placeholder/statefulset.yaml b/jupyter/base/charts/jupyterhub/templates/scheduling/user-placeholder/statefulset.yaml index e0f6f59..7f2c785 100644 --- a/jupyter/base/charts/jupyterhub/templates/scheduling/user-placeholder/statefulset.yaml +++ b/jupyter/base/charts/jupyterhub/templates/scheduling/user-placeholder/statefulset.yaml @@ -16,7 +16,7 @@ metadata: {{- include "jupyterhub.labels" . | nindent 4 }} spec: podManagementPolicy: Parallel - {{- if typeIs "int" .Values.scheduling.userPlaceholder.revisionHistoryLimit }} + {{- if not (typeIs "" .Values.scheduling.userPlaceholder.revisionHistoryLimit) }} revisionHistoryLimit: {{ .Values.scheduling.userPlaceholder.revisionHistoryLimit }} {{- end }} replicas: {{ .Values.scheduling.userPlaceholder.replicas }} diff --git a/jupyter/base/charts/jupyterhub/templates/scheduling/user-scheduler/configmap.yaml b/jupyter/base/charts/jupyterhub/templates/scheduling/user-scheduler/configmap.yaml index 0f142b0..a96acb8 100644 --- a/jupyter/base/charts/jupyterhub/templates/scheduling/user-scheduler/configmap.yaml +++ b/jupyter/base/charts/jupyterhub/templates/scheduling/user-scheduler/configmap.yaml @@ -10,26 +10,14 @@ data: This is configuration of a k8s official kube-scheduler binary running in the user-scheduler. - The config version and kube-scheduler binary version has a fallback for k8s - clusters versioned v1.23 or lower because: - - - v1 / v1beta3 config requires kube-scheduler binary >=1.25 / >=1.23 - - kube-scheduler binary >=1.25 requires storage.k8s.io/v1/CSIStorageCapacity - available first in k8s >=1.24 - ref: https://kubernetes.io/docs/reference/scheduling/config/ ref: https://kubernetes.io/docs/reference/config-api/kube-scheduler-config.v1/ - ref: https://kubernetes.io/docs/reference/config-api/kube-scheduler-config.v1beta3/ */}} config.yaml: | - {{- if semverCompare ">=1.24.0-0" .Capabilities.KubeVersion.Version }} apiVersion: kubescheduler.config.k8s.io/v1 - {{- else }} - apiVersion: kubescheduler.config.k8s.io/v1beta3 - {{- end }} kind: KubeSchedulerConfiguration leaderElection: - resourceLock: endpointsleases + resourceLock: leases resourceName: {{ include "jupyterhub.user-scheduler-lock.fullname" . }} resourceNamespace: "{{ .Release.Namespace }}" profiles: diff --git a/jupyter/base/charts/jupyterhub/templates/scheduling/user-scheduler/deployment.yaml b/jupyter/base/charts/jupyterhub/templates/scheduling/user-scheduler/deployment.yaml index 5baf4f4..e73c8ac 100644 --- a/jupyter/base/charts/jupyterhub/templates/scheduling/user-scheduler/deployment.yaml +++ b/jupyter/base/charts/jupyterhub/templates/scheduling/user-scheduler/deployment.yaml @@ -6,7 +6,7 @@ metadata: labels: {{- include "jupyterhub.labels" . | nindent 4 }} spec: - {{- if typeIs "int" .Values.scheduling.userScheduler.revisionHistoryLimit }} + {{- if not (typeIs "" .Values.scheduling.userScheduler.revisionHistoryLimit) }} revisionHistoryLimit: {{ .Values.scheduling.userScheduler.revisionHistoryLimit }} {{- end }} replicas: {{ .Values.scheduling.userScheduler.replicas }} @@ -50,17 +50,7 @@ spec: {{- end }} containers: - name: kube-scheduler - {{- if semverCompare ">=1.24.0-0" .Capabilities.KubeVersion.Version }} image: {{ .Values.scheduling.userScheduler.image.name }}:{{ .Values.scheduling.userScheduler.image.tag }} - {{- else }} - # WARNING: The tag of this image is hardcoded, and the - # "scheduling.userScheduler.image.tag" configuration of the - # Helm chart that generated this resource manifest isn't - # respected. If you install the Helm chart in a k8s cluster - # versioned 1.24 or higher, your configuration will be - # respected. - image: {{ .Values.scheduling.userScheduler.image.name }}:v1.23.14 - {{- end }} {{- with .Values.scheduling.userScheduler.image.pullPolicy }} imagePullPolicy: {{ . }} {{- end }} diff --git a/jupyter/base/charts/jupyterhub/templates/scheduling/user-scheduler/rbac.yaml b/jupyter/base/charts/jupyterhub/templates/scheduling/user-scheduler/rbac.yaml index 7e188c7..22a65eb 100644 --- a/jupyter/base/charts/jupyterhub/templates/scheduling/user-scheduler/rbac.yaml +++ b/jupyter/base/charts/jupyterhub/templates/scheduling/user-scheduler/rbac.yaml @@ -20,8 +20,12 @@ rules: # - changed in 1.21: get/list/watch permission for namespace, # csidrivers, csistoragecapacities was added. # - unchanged between 1.22 and 1.27 + # - changed in 1.28: permissions to get/update lock endpoint resource + # removed + # - unchanged between 1.28 and 1.30 + # - (1.31 is known to bring some changes below) # - # ref: https://github.com/kubernetes/kubernetes/blob/v1.27.0/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml#L736-L892 + # ref: https://github.com/kubernetes/kubernetes/blob/v1.30.0/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml#L721-L862 - apiGroups: - "" - events.k8s.io @@ -46,21 +50,6 @@ rules: verbs: - get - update - - apiGroups: - - "" - resources: - - endpoints - verbs: - - create - - apiGroups: - - "" - resourceNames: - - {{ include "jupyterhub.user-scheduler-lock.fullname" . }} - resources: - - endpoints - verbs: - - get - - update - apiGroups: - "" resources: @@ -183,9 +172,9 @@ rules: # Copied from the system:volume-scheduler ClusterRole of the k8s version # matching the kube-scheduler binary we use. # - # NOTE: These rules have not changed between 1.12 and 1.27. + # NOTE: These rules have not changed between 1.12 and 1.29. # - # ref: https://github.com/kubernetes/kubernetes/blob/v1.27.0/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml#L1311-L1338 + # ref: https://github.com/kubernetes/kubernetes/blob/v1.29.0/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml#L1283-L1310 - apiGroups: - "" resources: diff --git a/jupyter/base/charts/jupyterhub/values.schema.json b/jupyter/base/charts/jupyterhub/values.schema.json index 044819b..b44b2be 100644 --- a/jupyter/base/charts/jupyterhub/values.schema.json +++ b/jupyter/base/charts/jupyterhub/values.schema.json @@ -1 +1 @@ -{"$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "additionalProperties": false, "required": ["imagePullSecrets", "hub", "proxy", "singleuser", "ingress", "prePuller", "custom", "cull", "debug", "rbac", "global"], "properties": {"enabled": {"type": ["boolean", "null"]}, "fullnameOverride": {"type": ["string", "null"]}, "nameOverride": {"type": ["string", "null"]}, "imagePullSecret": {"type": "object", "required": ["create"], "if": {"properties": {"create": {"const": true}}}, "then": {"additionalProperties": false, "required": ["registry", "username", "password"], "description": "This is configuration to create a k8s Secret resource of `type:\nkubernetes.io/dockerconfigjson`, with credentials to pull images from a\nprivate image registry. If you opt to do so, it will be available for use\nby all pods in their respective `spec.imagePullSecrets` alongside other\nk8s Secrets defined in `imagePullSecrets` or the pod respective\n`...image.pullSecrets` configuration.\n\nIn other words, using this configuration option can automate both the\notherwise manual creation of a k8s Secret and the otherwise manual\nconfiguration to reference this k8s Secret in all the pods of the Helm\nchart.\n\n```sh\n# you won't need to create a k8s Secret manually...\nkubectl create secret docker-registry image-pull-secret \\\n --docker-server= \\\n --docker-username= \\\n --docker-email= \\\n --docker-password=\n```\n\nIf you just want to let all Pods reference an existing secret, use the\n[`imagePullSecrets`](schema_imagePullSecrets) configuration instead.\n", "properties": {"create": {"type": "boolean", "description": "Toggle the creation of the k8s Secret with provided credentials to\naccess a private image registry.\n"}, "automaticReferenceInjection": {"type": "boolean", "description": "Toggle the automatic reference injection of the created Secret to all\npods' `spec.imagePullSecrets` configuration.\n"}, "registry": {"type": "string", "description": "Name of the private registry you want to create a credential set for.\nIt will default to Docker Hub's image registry.\n\nExamples:\n - https://index.docker.io/v1/\n - quay.io\n - eu.gcr.io\n - alexmorreale.privatereg.net\n"}, "username": {"type": "string", "description": "Name of the user you want to use to connect to your private registry.\n\nFor external gcr.io, you will use the `_json_key`.\n\nExamples:\n - alexmorreale\n - alex@pfc.com\n - _json_key\n"}, "password": {"type": "string", "description": "Password for the private image registry's user.\n\nExamples:\n - plaintextpassword\n - abc123SECRETzyx098\n\nFor gcr.io registries the password will be a big JSON blob for a\nGoogle cloud service account, it should look something like below.\n\n```yaml\npassword: |-\n {\n \"type\": \"service_account\",\n \"project_id\": \"jupyter-se\",\n \"private_key_id\": \"f2ba09118a8d3123b3321bd9a7d6d0d9dc6fdb85\",\n ...\n }\n```\n"}, "email": {"type": ["string", "null"], "description": "Specification of an email is most often not required, but it is\nsupported.\n"}}}}, "imagePullSecrets": {"type": "array"}, "hub": {"type": "object", "additionalProperties": false, "required": ["baseUrl"], "properties": {"revisionHistoryLimit": {"type": ["integer", "null"], "minimum": 0}, "config": {"type": "object", "additionalProperties": true}, "extraFiles": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "object", "additionalProperties": false, "required": ["mountPath"], "oneOf": [{"required": ["data"]}, {"required": ["stringData"]}, {"required": ["binaryData"]}], "properties": {"mountPath": {"type": "string"}, "data": {"type": "object", "additionalProperties": true}, "stringData": {"type": "string"}, "binaryData": {"type": "string"}, "mode": {"type": "number"}}}}}, "baseUrl": {"type": "string"}, "command": {"type": "array"}, "args": {"type": "array"}, "cookieSecret": {"type": ["string", "null"]}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "networkPolicy": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "ingress": {"type": "array"}, "egress": {"type": "array"}, "egressAllowRules": {"type": "object", "additionalProperties": false, "properties": {"cloudMetadataServer": {"type": "boolean"}, "dnsPortsCloudMetadataServer": {"type": "boolean"}, "dnsPortsKubeSystemNamespace": {"type": "boolean"}, "dnsPortsPrivateIPs": {"type": "boolean"}, "nonPrivateIPs": {"type": "boolean"}, "privateIPs": {"type": "boolean"}}}, "interNamespaceAccessLabels": {"enum": ["accept", "ignore"]}, "allowedIngressPorts": {"type": "array"}}}, "db": {"type": "object", "additionalProperties": false, "properties": {"type": {"enum": ["sqlite-pvc", "sqlite-memory", "mysql", "postgres", "other"]}, "pvc": {"type": "object", "additionalProperties": false, "required": ["storage"], "properties": {"annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "selector": {"type": "object", "additionalProperties": true}, "storage": {"type": "string"}, "accessModes": {"type": "array", "items": {"type": ["string", "null"]}}, "storageClassName": {"type": ["string", "null"]}, "subPath": {"type": ["string", "null"]}}}, "upgrade": {"type": ["boolean", "null"]}, "url": {"type": ["string", "null"]}, "password": {"type": ["string", "null"]}}}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "initContainers": {"type": "array"}, "extraEnv": {"type": ["object", "array"], "additionalProperties": true}, "extraConfig": {"type": "object", "additionalProperties": true}, "fsGid": {"type": ["integer", "null"], "minimum": 0}, "service": {"type": "object", "additionalProperties": false, "properties": {"type": {"enum": ["ClusterIP", "NodePort", "LoadBalancer", "ExternalName"]}, "ports": {"type": "object", "additionalProperties": false, "properties": {"nodePort": {"type": ["integer", "null"], "minimum": 0}}}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "extraPorts": {"type": "array"}, "loadBalancerIP": {"type": ["string", "null"]}}}, "pdb": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "maxUnavailable": {"type": ["integer", "null"]}, "minAvailable": {"type": ["integer", "null"]}}}, "existingSecret": {"type": ["string", "null"]}, "nodeSelector": {"type": "object", "additionalProperties": true}, "tolerations": {"type": "array"}, "activeServerLimit": {"type": ["integer", "null"]}, "allowNamedServers": {"type": ["boolean", "null"]}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "authenticatePrometheus": {"type": ["boolean", "null"]}, "concurrentSpawnLimit": {"type": ["integer", "null"]}, "consecutiveFailureLimit": {"type": ["integer", "null"]}, "podSecurityContext": {"additionalProperties": true}, "containerSecurityContext": {"type": "object", "additionalProperties": true}, "deploymentStrategy": {"type": "object", "additionalProperties": false, "properties": {"rollingUpdate": {"type": ["string", "null"]}, "type": {"type": ["string", "null"]}}}, "extraContainers": {"type": "array"}, "extraVolumeMounts": {"type": "array"}, "extraVolumes": {"type": "array"}, "livenessProbe": {"type": "object", "additionalProperties": true, "required": ["enabled"], "if": {"properties": {"enabled": {"const": true}}}, "then": {"description": "This config option is like the k8s native specification of a\ncontainer probe, except that it also supports an `enabled` boolean\nflag.\n\nSee [the k8s\ndocumentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#probe-v1-core)\nfor more details.\n"}}, "readinessProbe": {"type": "object", "additionalProperties": true, "required": ["enabled"], "if": {"properties": {"enabled": {"const": true}}}, "then": {"description": "This config option is like the k8s native specification of a\ncontainer probe, except that it also supports an `enabled` boolean\nflag.\n\nSee [the k8s\ndocumentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#probe-v1-core)\nfor more details.\n"}}, "namedServerLimitPerUser": {"type": ["integer", "null"]}, "redirectToServer": {"type": ["boolean", "null"]}, "resources": {"type": "object", "additionalProperties": true}, "lifecycle": {"type": "object", "additionalProperties": false, "properties": {"postStart": {"type": "object", "additionalProperties": true}, "preStop": {"type": "object", "additionalProperties": true}}}, "services": {"type": "object", "additionalProperties": true, "properties": {"name": {"type": "string"}, "admin": {"type": "boolean"}, "command": {"type": ["string", "array"]}, "url": {"type": "string"}, "api_token": {"type": ["string", "null"]}, "apiToken": {"type": ["string", "null"]}}}, "loadRoles": {"type": "object", "additionalProperties": true}, "shutdownOnLogout": {"type": ["boolean", "null"]}, "templatePaths": {"type": "array"}, "templateVars": {"type": "object", "additionalProperties": true}, "serviceAccount": {"type": "object", "required": ["create"], "additionalProperties": false, "properties": {"create": {"type": "boolean"}, "name": {"type": ["string", "null"]}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}}}, "extraPodSpec": {"type": "object", "additionalProperties": true}}}, "proxy": {"type": "object", "additionalProperties": false, "properties": {"chp": {"type": "object", "additionalProperties": false, "properties": {"revisionHistoryLimit": {"type": ["integer", "null"], "minimum": 0}, "networkPolicy": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "ingress": {"type": "array"}, "egress": {"type": "array"}, "egressAllowRules": {"type": "object", "additionalProperties": false, "properties": {"cloudMetadataServer": {"type": "boolean"}, "dnsPortsCloudMetadataServer": {"type": "boolean"}, "dnsPortsKubeSystemNamespace": {"type": "boolean"}, "dnsPortsPrivateIPs": {"type": "boolean"}, "nonPrivateIPs": {"type": "boolean"}, "privateIPs": {"type": "boolean"}}}, "interNamespaceAccessLabels": {"enum": ["accept", "ignore"]}, "allowedIngressPorts": {"type": "array"}}}, "extraCommandLineFlags": {"type": "array"}, "extraEnv": {"type": ["object", "array"], "additionalProperties": true}, "pdb": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "maxUnavailable": {"type": ["integer", "null"]}, "minAvailable": {"type": ["integer", "null"]}}}, "nodeSelector": {"type": "object", "additionalProperties": true}, "tolerations": {"type": "array"}, "containerSecurityContext": {"type": "object", "additionalProperties": true}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "livenessProbe": {"type": "object", "additionalProperties": true, "required": ["enabled"], "if": {"properties": {"enabled": {"const": true}}}, "then": {"description": "This config option is like the k8s native specification of a\ncontainer probe, except that it also supports an `enabled` boolean\nflag.\n\nSee [the k8s\ndocumentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#probe-v1-core)\nfor more details.\n"}}, "readinessProbe": {"type": "object", "additionalProperties": true, "required": ["enabled"], "if": {"properties": {"enabled": {"const": true}}}, "then": {"description": "This config option is like the k8s native specification of a\ncontainer probe, except that it also supports an `enabled` boolean\nflag.\n\nSee [the k8s\ndocumentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#probe-v1-core)\nfor more details.\n"}}, "resources": {"type": "object", "additionalProperties": true}, "defaultTarget": {"type": ["string", "null"]}, "errorTarget": {"type": ["string", "null"]}, "extraPodSpec": {"type": "object", "additionalProperties": true}}}, "secretToken": {"type": ["string", "null"]}, "service": {"type": "object", "additionalProperties": false, "properties": {"type": {"enum": ["ClusterIP", "NodePort", "LoadBalancer", "ExternalName"]}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "nodePorts": {"type": "object", "additionalProperties": false, "properties": {"http": {"type": ["integer", "null"]}, "https": {"type": ["integer", "null"]}}}, "disableHttpPort": {"type": "boolean"}, "extraPorts": {"type": "array"}, "loadBalancerIP": {"type": ["string", "null"]}, "loadBalancerSourceRanges": {"type": "array"}}}, "https": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": ["boolean", "null"]}, "type": {"enum": [null, "", "letsencrypt", "manual", "offload", "secret"]}, "letsencrypt": {"type": "object", "additionalProperties": false, "properties": {"contactEmail": {"type": ["string", "null"]}, "acmeServer": {"type": ["string", "null"]}}}, "manual": {"type": "object", "additionalProperties": false, "properties": {"key": {"type": ["string", "null"]}, "cert": {"type": ["string", "null"]}}}, "secret": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": ["string", "null"]}, "key": {"type": ["string", "null"]}, "crt": {"type": ["string", "null"]}}}, "hosts": {"type": "array"}}}, "traefik": {"type": "object", "additionalProperties": false, "properties": {"revisionHistoryLimit": {"type": ["integer", "null"], "minimum": 0}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "networkPolicy": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "ingress": {"type": "array"}, "egress": {"type": "array"}, "egressAllowRules": {"type": "object", "additionalProperties": false, "properties": {"cloudMetadataServer": {"type": "boolean"}, "dnsPortsCloudMetadataServer": {"type": "boolean"}, "dnsPortsKubeSystemNamespace": {"type": "boolean"}, "dnsPortsPrivateIPs": {"type": "boolean"}, "nonPrivateIPs": {"type": "boolean"}, "privateIPs": {"type": "boolean"}}}, "interNamespaceAccessLabels": {"enum": ["accept", "ignore"]}, "allowedIngressPorts": {"type": "array"}}}, "extraInitContainers": {"type": "array"}, "extraEnv": {"type": ["object", "array"], "additionalProperties": true}, "pdb": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "maxUnavailable": {"type": ["integer", "null"]}, "minAvailable": {"type": ["integer", "null"]}}}, "nodeSelector": {"type": "object", "additionalProperties": true}, "tolerations": {"type": "array"}, "containerSecurityContext": {"type": "object", "additionalProperties": true}, "extraDynamicConfig": {"type": "object", "additionalProperties": true}, "extraPorts": {"type": "array"}, "extraStaticConfig": {"type": "object", "additionalProperties": true}, "extraVolumes": {"type": "array"}, "extraVolumeMounts": {"type": "array"}, "hsts": {"type": "object", "additionalProperties": false, "required": ["includeSubdomains", "maxAge", "preload"], "properties": {"includeSubdomains": {"type": "boolean"}, "maxAge": {"type": "integer"}, "preload": {"type": "boolean"}}}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "resources": {"type": "object", "additionalProperties": true}, "serviceAccount": {"type": "object", "required": ["create"], "additionalProperties": false, "properties": {"create": {"type": "boolean"}, "name": {"type": ["string", "null"]}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}}}, "extraPodSpec": {"type": "object", "additionalProperties": true}}}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "deploymentStrategy": {"type": "object", "additionalProperties": false, "properties": {"rollingUpdate": {"type": ["string", "null"]}, "type": {"type": ["string", "null"]}}}, "secretSync": {"type": "object", "additionalProperties": false, "properties": {"containerSecurityContext": {"type": "object", "additionalProperties": true}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "resources": {"type": "object", "additionalProperties": true}}}}}, "singleuser": {"type": "object", "additionalProperties": false, "properties": {"networkPolicy": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "ingress": {"type": "array"}, "egress": {"type": "array"}, "egressAllowRules": {"type": "object", "additionalProperties": false, "properties": {"cloudMetadataServer": {"type": "boolean"}, "dnsPortsCloudMetadataServer": {"type": "boolean"}, "dnsPortsKubeSystemNamespace": {"type": "boolean"}, "dnsPortsPrivateIPs": {"type": "boolean"}, "nonPrivateIPs": {"type": "boolean"}, "privateIPs": {"type": "boolean"}}}, "interNamespaceAccessLabels": {"enum": ["accept", "ignore"]}, "allowedIngressPorts": {"type": "array"}}}, "podNameTemplate": {"type": ["string", "null"]}, "cpu": {"type": "object", "additionalProperties": false, "properties": {"limit": {"type": ["number", "null"]}, "guarantee": {"type": ["number", "null"]}}}, "memory": {"type": "object", "additionalProperties": false, "properties": {"limit": {"type": ["number", "string", "null"]}, "guarantee": {"type": ["number", "string", "null"]}}}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "initContainers": {"type": "array"}, "profileList": {"type": "array"}, "extraFiles": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "object", "additionalProperties": false, "required": ["mountPath"], "oneOf": [{"required": ["data"]}, {"required": ["stringData"]}, {"required": ["binaryData"]}], "properties": {"mountPath": {"type": "string"}, "data": {"type": "object", "additionalProperties": true}, "stringData": {"type": "string"}, "binaryData": {"type": "string"}, "mode": {"type": "number"}}}}}, "extraEnv": {"type": ["object", "array"], "additionalProperties": true}, "nodeSelector": {"type": "object", "additionalProperties": true}, "extraTolerations": {"type": "array"}, "extraNodeAffinity": {"type": "object", "additionalProperties": false, "properties": {"required": {"type": "array"}, "preferred": {"type": "array"}}}, "extraPodAffinity": {"type": "object", "additionalProperties": false, "properties": {"required": {"type": "array"}, "preferred": {"type": "array"}}}, "extraPodAntiAffinity": {"type": "object", "additionalProperties": false, "properties": {"required": {"type": "array"}, "preferred": {"type": "array"}}}, "cloudMetadata": {"type": "object", "additionalProperties": false, "required": ["blockWithIptables", "ip"], "properties": {"blockWithIptables": {"type": "boolean"}, "ip": {"type": "string"}}}, "cmd": {"type": ["array", "string", "null"]}, "defaultUrl": {"type": ["string", "null"]}, "events": {"type": ["boolean", "null"]}, "extraAnnotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "extraContainers": {"type": "array"}, "extraLabels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "extraPodConfig": {"type": "object", "additionalProperties": true}, "extraResource": {"type": "object", "additionalProperties": false, "properties": {"guarantees": {"type": "object", "additionalProperties": true}, "limits": {"type": "object", "additionalProperties": true}}}, "fsGid": {"type": ["integer", "null"]}, "lifecycleHooks": {"type": "object", "additionalProperties": false, "properties": {"postStart": {"type": "object", "additionalProperties": true}, "preStop": {"type": "object", "additionalProperties": true}}}, "networkTools": {"type": "object", "additionalProperties": false, "properties": {"image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "resources": {"type": "object", "additionalProperties": true}}}, "serviceAccountName": {"type": ["string", "null"]}, "startTimeout": {"type": ["integer", "null"]}, "storage": {"type": "object", "additionalProperties": false, "required": ["type", "homeMountPath"], "properties": {"capacity": {"type": ["string", "null"]}, "dynamic": {"type": "object", "additionalProperties": false, "properties": {"pvcNameTemplate": {"type": ["string", "null"]}, "storageAccessModes": {"type": "array", "items": {"type": ["string", "null"]}}, "storageClass": {"type": ["string", "null"]}, "volumeNameTemplate": {"type": ["string", "null"]}}}, "extraLabels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "extraVolumeMounts": {"type": "array"}, "extraVolumes": {"type": "array"}, "homeMountPath": {"type": "string"}, "static": {"type": "object", "additionalProperties": false, "properties": {"pvcName": {"type": ["string", "null"]}, "subPath": {"type": ["string", "null"]}}}, "type": {"enum": ["dynamic", "static", "none"]}}}, "allowPrivilegeEscalation": {"type": ["boolean", "null"]}, "uid": {"type": ["integer", "null"]}}}, "scheduling": {"type": "object", "additionalProperties": false, "properties": {"userScheduler": {"type": "object", "additionalProperties": false, "required": ["enabled", "plugins", "pluginConfig", "logLevel"], "properties": {"enabled": {"type": "boolean"}, "revisionHistoryLimit": {"type": ["integer", "null"], "minimum": 0}, "replicas": {"type": "integer"}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "pdb": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "maxUnavailable": {"type": ["integer", "null"]}, "minAvailable": {"type": ["integer", "null"]}}}, "nodeSelector": {"type": "object", "additionalProperties": true}, "tolerations": {"type": "array"}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "containerSecurityContext": {"type": "object", "additionalProperties": true}, "logLevel": {"type": "integer"}, "plugins": {"type": "object", "additionalProperties": true}, "pluginConfig": {"type": "array"}, "resources": {"type": "object", "additionalProperties": true}, "serviceAccount": {"type": "object", "required": ["create"], "additionalProperties": false, "properties": {"create": {"type": "boolean"}, "name": {"type": ["string", "null"]}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}}}, "extraPodSpec": {"type": "object", "additionalProperties": true}}}, "podPriority": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "globalDefault": {"type": "boolean"}, "defaultPriority": {"type": "integer"}, "imagePullerPriority": {"type": "integer"}, "userPlaceholderPriority": {"type": "integer"}}}, "userPlaceholder": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "revisionHistoryLimit": {"type": ["integer", "null"], "minimum": 0}, "replicas": {"type": "integer"}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "resources": {"type": "object", "additionalProperties": true}, "containerSecurityContext": {"type": "object", "additionalProperties": true}}}, "corePods": {"type": "object", "additionalProperties": false, "properties": {"tolerations": {"type": "array"}, "nodeAffinity": {"type": "object", "additionalProperties": false, "properties": {"matchNodePurpose": {"enum": ["ignore", "prefer", "require"]}}}}}, "userPods": {"type": "object", "additionalProperties": false, "properties": {"tolerations": {"type": "array"}, "nodeAffinity": {"type": "object", "additionalProperties": false, "properties": {"matchNodePurpose": {"enum": ["ignore", "prefer", "require"]}}}}}}}, "ingress": {"type": "object", "additionalProperties": false, "required": ["enabled"], "properties": {"enabled": {"type": "boolean"}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "ingressClassName": {"type": ["string", "null"]}, "hosts": {"type": "array"}, "pathSuffix": {"type": ["string", "null"]}, "pathType": {"enum": ["Prefix", "Exact", "ImplementationSpecific"]}, "tls": {"type": "array"}}}, "prePuller": {"type": "object", "additionalProperties": false, "required": ["hook", "continuous"], "properties": {"revisionHistoryLimit": {"type": ["integer", "null"], "minimum": 0}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "resources": {"type": "object", "additionalProperties": true}, "extraTolerations": {"type": "array"}, "hook": {"type": "object", "additionalProperties": false, "required": ["enabled"], "properties": {"enabled": {"type": "boolean"}, "pullOnlyOnChanges": {"type": "boolean"}, "podSchedulingWaitDuration": {"type": "integer"}, "nodeSelector": {"type": "object", "additionalProperties": true}, "tolerations": {"type": "array"}, "containerSecurityContext": {"type": "object", "additionalProperties": true}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "resources": {"type": "object", "additionalProperties": true}, "serviceAccount": {"type": "object", "required": ["create"], "additionalProperties": false, "properties": {"create": {"type": "boolean"}, "name": {"type": ["string", "null"]}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}}}}}, "continuous": {"type": "object", "additionalProperties": false, "required": ["enabled"], "properties": {"enabled": {"type": "boolean"}}}, "pullProfileListImages": {"type": "boolean"}, "extraImages": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}}}}}, "containerSecurityContext": {"type": "object", "additionalProperties": true}, "pause": {"type": "object", "additionalProperties": false, "properties": {"containerSecurityContext": {"type": "object", "additionalProperties": true}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}}}}}, "custom": {"type": "object", "additionalProperties": true}, "cull": {"type": "object", "additionalProperties": false, "required": ["enabled"], "properties": {"enabled": {"type": "boolean"}, "users": {"type": ["boolean", "null"]}, "adminUsers": {"type": ["boolean", "null"]}, "removeNamedServers": {"type": ["boolean", "null"]}, "timeout": {"type": ["integer", "null"]}, "every": {"type": ["integer", "null"]}, "concurrency": {"type": ["integer", "null"]}, "maxAge": {"type": ["integer", "null"]}}}, "debug": {"type": "object", "additionalProperties": false, "required": ["enabled"], "properties": {"enabled": {"type": "boolean"}}}, "rbac": {"type": "object", "additionalProperties": false, "required": ["create"], "properties": {"enabled": {"type": "boolean"}, "create": {"type": "boolean"}}}, "global": {"type": "object", "additionalProperties": true, "properties": {"safeToShowValues": {"type": "boolean"}}}}} \ No newline at end of file +{"$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "additionalProperties": false, "required": ["imagePullSecrets", "hub", "proxy", "singleuser", "ingress", "prePuller", "custom", "cull", "debug", "rbac", "global"], "properties": {"enabled": {"type": ["boolean", "null"]}, "fullnameOverride": {"type": ["string", "null"]}, "nameOverride": {"type": ["string", "null"]}, "imagePullSecret": {"type": "object", "required": ["create"], "if": {"properties": {"create": {"const": true}}}, "then": {"additionalProperties": false, "required": ["registry", "username", "password"], "description": "This is configuration to create a k8s Secret resource of `type:\nkubernetes.io/dockerconfigjson`, with credentials to pull images from a\nprivate image registry. If you opt to do so, it will be available for use\nby all pods in their respective `spec.imagePullSecrets` alongside other\nk8s Secrets defined in `imagePullSecrets` or the pod respective\n`...image.pullSecrets` configuration.\n\nIn other words, using this configuration option can automate both the\notherwise manual creation of a k8s Secret and the otherwise manual\nconfiguration to reference this k8s Secret in all the pods of the Helm\nchart.\n\n```sh\n# you won't need to create a k8s Secret manually...\nkubectl create secret docker-registry image-pull-secret \\\n --docker-server= \\\n --docker-username= \\\n --docker-email= \\\n --docker-password=\n```\n\nIf you just want to let all Pods reference an existing secret, use the\n[`imagePullSecrets`](schema_imagePullSecrets) configuration instead.\n", "properties": {"create": {"type": "boolean", "description": "Toggle the creation of the k8s Secret with provided credentials to\naccess a private image registry.\n"}, "automaticReferenceInjection": {"type": "boolean", "description": "Toggle the automatic reference injection of the created Secret to all\npods' `spec.imagePullSecrets` configuration.\n"}, "registry": {"type": "string", "description": "Name of the private registry you want to create a credential set for.\nIt will default to Docker Hub's image registry.\n\nExamples:\n - https://index.docker.io/v1/\n - quay.io\n - eu.gcr.io\n - alexmorreale.privatereg.net\n"}, "username": {"type": "string", "description": "Name of the user you want to use to connect to your private registry.\n\nFor external gcr.io, you will use the `_json_key`.\n\nExamples:\n - alexmorreale\n - alex@pfc.com\n - _json_key\n"}, "password": {"type": "string", "description": "Password for the private image registry's user.\n\nExamples:\n - plaintextpassword\n - abc123SECRETzyx098\n\nFor gcr.io registries the password will be a big JSON blob for a\nGoogle cloud service account, it should look something like below.\n\n```yaml\npassword: |-\n {\n \"type\": \"service_account\",\n \"project_id\": \"jupyter-se\",\n \"private_key_id\": \"f2ba09118a8d3123b3321bd9a7d6d0d9dc6fdb85\",\n ...\n }\n```\n"}, "email": {"type": ["string", "null"], "description": "Specification of an email is most often not required, but it is\nsupported.\n"}}}}, "imagePullSecrets": {"type": "array"}, "hub": {"type": "object", "additionalProperties": false, "required": ["baseUrl"], "properties": {"revisionHistoryLimit": {"type": ["integer", "null"], "minimum": 0}, "config": {"type": "object", "additionalProperties": true, "properties": {"JupyterHub": {"type": "object", "additionalProperties": true, "properties": {"subdomain_host": {"type": "string"}}}}}, "extraFiles": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "object", "additionalProperties": false, "required": ["mountPath"], "oneOf": [{"required": ["data"]}, {"required": ["stringData"]}, {"required": ["binaryData"]}], "properties": {"mountPath": {"type": "string"}, "data": {"type": "object", "additionalProperties": true}, "stringData": {"type": "string"}, "binaryData": {"type": "string"}, "mode": {"type": "number"}}}}}, "baseUrl": {"type": "string"}, "command": {"type": "array"}, "args": {"type": "array"}, "cookieSecret": {"type": ["string", "null"]}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "networkPolicy": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "ingress": {"type": "array"}, "egress": {"type": "array"}, "egressAllowRules": {"type": "object", "additionalProperties": false, "properties": {"cloudMetadataServer": {"type": "boolean"}, "dnsPortsCloudMetadataServer": {"type": "boolean"}, "dnsPortsKubeSystemNamespace": {"type": "boolean"}, "dnsPortsPrivateIPs": {"type": "boolean"}, "nonPrivateIPs": {"type": "boolean"}, "privateIPs": {"type": "boolean"}}}, "interNamespaceAccessLabels": {"enum": ["accept", "ignore"]}, "allowedIngressPorts": {"type": "array"}}}, "db": {"type": "object", "additionalProperties": false, "properties": {"type": {"enum": ["sqlite-pvc", "sqlite-memory", "mysql", "postgres", "other"]}, "pvc": {"type": "object", "additionalProperties": false, "required": ["storage"], "properties": {"annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "selector": {"type": "object", "additionalProperties": true}, "storage": {"type": "string"}, "accessModes": {"type": "array", "items": {"type": ["string", "null"]}}, "storageClassName": {"type": ["string", "null"]}, "subPath": {"type": ["string", "null"]}}}, "upgrade": {"type": ["boolean", "null"]}, "url": {"type": ["string", "null"]}, "password": {"type": ["string", "null"]}}}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "initContainers": {"type": "array"}, "extraEnv": {"type": ["object", "array"], "additionalProperties": true}, "extraConfig": {"type": "object", "additionalProperties": true}, "fsGid": {"type": ["integer", "null"], "minimum": 0}, "service": {"type": "object", "additionalProperties": false, "properties": {"type": {"enum": ["ClusterIP", "NodePort", "LoadBalancer", "ExternalName"]}, "ports": {"type": "object", "additionalProperties": false, "properties": {"appProtocol": {"type": ["string", "null"]}, "nodePort": {"type": ["integer", "null"], "minimum": 0}}}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "extraPorts": {"type": "array"}, "loadBalancerIP": {"type": ["string", "null"]}}}, "pdb": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "maxUnavailable": {"type": ["integer", "null"]}, "minAvailable": {"type": ["integer", "null"]}}}, "existingSecret": {"type": ["string", "null"]}, "nodeSelector": {"type": "object", "additionalProperties": true}, "tolerations": {"type": "array"}, "activeServerLimit": {"type": ["integer", "null"]}, "allowNamedServers": {"type": ["boolean", "null"]}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "authenticatePrometheus": {"type": ["boolean", "null"]}, "concurrentSpawnLimit": {"type": ["integer", "null"]}, "consecutiveFailureLimit": {"type": ["integer", "null"]}, "podSecurityContext": {"additionalProperties": true}, "containerSecurityContext": {"type": "object", "additionalProperties": true}, "deploymentStrategy": {"type": "object", "additionalProperties": false, "properties": {"rollingUpdate": {"type": ["string", "null"]}, "type": {"type": ["string", "null"]}}}, "extraContainers": {"type": "array"}, "extraVolumeMounts": {"type": "array"}, "extraVolumes": {"type": "array"}, "livenessProbe": {"type": "object", "additionalProperties": true, "required": ["enabled"], "if": {"properties": {"enabled": {"const": true}}}, "then": {"description": "This config option is like the k8s native specification of a\ncontainer probe, except that it also supports an `enabled` boolean\nflag.\n\nSee [the k8s\ndocumentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#probe-v1-core)\nfor more details.\n"}}, "readinessProbe": {"type": "object", "additionalProperties": true, "required": ["enabled"], "if": {"properties": {"enabled": {"const": true}}}, "then": {"description": "This config option is like the k8s native specification of a\ncontainer probe, except that it also supports an `enabled` boolean\nflag.\n\nSee [the k8s\ndocumentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#probe-v1-core)\nfor more details.\n"}}, "namedServerLimitPerUser": {"type": ["integer", "null"]}, "redirectToServer": {"type": ["boolean", "null"]}, "resources": {"type": "object", "additionalProperties": true}, "lifecycle": {"type": "object", "additionalProperties": false, "properties": {"postStart": {"type": "object", "additionalProperties": true}, "preStop": {"type": "object", "additionalProperties": true}}}, "services": {"type": "object", "additionalProperties": true, "properties": {"name": {"type": "string"}, "admin": {"type": "boolean"}, "command": {"type": ["string", "array"]}, "url": {"type": "string"}, "api_token": {"type": ["string", "null"]}, "apiToken": {"type": ["string", "null"]}}}, "loadRoles": {"type": "object", "additionalProperties": true}, "shutdownOnLogout": {"type": ["boolean", "null"]}, "templatePaths": {"type": "array"}, "templateVars": {"type": "object", "additionalProperties": true}, "serviceAccount": {"type": "object", "required": ["create"], "additionalProperties": false, "properties": {"create": {"type": "boolean"}, "name": {"type": ["string", "null"]}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}}}, "extraPodSpec": {"type": "object", "additionalProperties": true}}}, "proxy": {"type": "object", "additionalProperties": false, "properties": {"chp": {"type": "object", "additionalProperties": false, "properties": {"revisionHistoryLimit": {"type": ["integer", "null"], "minimum": 0}, "networkPolicy": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "ingress": {"type": "array"}, "egress": {"type": "array"}, "egressAllowRules": {"type": "object", "additionalProperties": false, "properties": {"cloudMetadataServer": {"type": "boolean"}, "dnsPortsCloudMetadataServer": {"type": "boolean"}, "dnsPortsKubeSystemNamespace": {"type": "boolean"}, "dnsPortsPrivateIPs": {"type": "boolean"}, "nonPrivateIPs": {"type": "boolean"}, "privateIPs": {"type": "boolean"}}}, "interNamespaceAccessLabels": {"enum": ["accept", "ignore"]}, "allowedIngressPorts": {"type": "array"}}}, "extraCommandLineFlags": {"type": "array"}, "extraEnv": {"type": ["object", "array"], "additionalProperties": true}, "pdb": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "maxUnavailable": {"type": ["integer", "null"]}, "minAvailable": {"type": ["integer", "null"]}}}, "nodeSelector": {"type": "object", "additionalProperties": true}, "tolerations": {"type": "array"}, "containerSecurityContext": {"type": "object", "additionalProperties": true}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "livenessProbe": {"type": "object", "additionalProperties": true, "required": ["enabled"], "if": {"properties": {"enabled": {"const": true}}}, "then": {"description": "This config option is like the k8s native specification of a\ncontainer probe, except that it also supports an `enabled` boolean\nflag.\n\nSee [the k8s\ndocumentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#probe-v1-core)\nfor more details.\n"}}, "readinessProbe": {"type": "object", "additionalProperties": true, "required": ["enabled"], "if": {"properties": {"enabled": {"const": true}}}, "then": {"description": "This config option is like the k8s native specification of a\ncontainer probe, except that it also supports an `enabled` boolean\nflag.\n\nSee [the k8s\ndocumentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#probe-v1-core)\nfor more details.\n"}}, "resources": {"type": "object", "additionalProperties": true}, "defaultTarget": {"type": ["string", "null"]}, "errorTarget": {"type": ["string", "null"]}, "extraPodSpec": {"type": "object", "additionalProperties": true}}}, "secretToken": {"type": ["string", "null"]}, "service": {"type": "object", "additionalProperties": false, "properties": {"type": {"enum": ["ClusterIP", "NodePort", "LoadBalancer", "ExternalName"]}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "nodePorts": {"type": "object", "additionalProperties": false, "properties": {"http": {"type": ["integer", "null"]}, "https": {"type": ["integer", "null"]}}}, "disableHttpPort": {"type": "boolean"}, "extraPorts": {"type": "array"}, "loadBalancerIP": {"type": ["string", "null"]}, "loadBalancerSourceRanges": {"type": "array"}}}, "https": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": ["boolean", "null"]}, "type": {"enum": [null, "", "letsencrypt", "manual", "offload", "secret"]}, "letsencrypt": {"type": "object", "additionalProperties": false, "properties": {"contactEmail": {"type": ["string", "null"]}, "acmeServer": {"type": ["string", "null"]}}}, "manual": {"type": "object", "additionalProperties": false, "properties": {"key": {"type": ["string", "null"]}, "cert": {"type": ["string", "null"]}}}, "secret": {"type": "object", "additionalProperties": false, "properties": {"name": {"type": ["string", "null"]}, "key": {"type": ["string", "null"]}, "crt": {"type": ["string", "null"]}}}, "hosts": {"type": "array"}}}, "traefik": {"type": "object", "additionalProperties": false, "properties": {"revisionHistoryLimit": {"type": ["integer", "null"], "minimum": 0}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "networkPolicy": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "ingress": {"type": "array"}, "egress": {"type": "array"}, "egressAllowRules": {"type": "object", "additionalProperties": false, "properties": {"cloudMetadataServer": {"type": "boolean"}, "dnsPortsCloudMetadataServer": {"type": "boolean"}, "dnsPortsKubeSystemNamespace": {"type": "boolean"}, "dnsPortsPrivateIPs": {"type": "boolean"}, "nonPrivateIPs": {"type": "boolean"}, "privateIPs": {"type": "boolean"}}}, "interNamespaceAccessLabels": {"enum": ["accept", "ignore"]}, "allowedIngressPorts": {"type": "array"}}}, "extraInitContainers": {"type": "array"}, "extraEnv": {"type": ["object", "array"], "additionalProperties": true}, "pdb": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "maxUnavailable": {"type": ["integer", "null"]}, "minAvailable": {"type": ["integer", "null"]}}}, "nodeSelector": {"type": "object", "additionalProperties": true}, "tolerations": {"type": "array"}, "containerSecurityContext": {"type": "object", "additionalProperties": true}, "extraDynamicConfig": {"type": "object", "additionalProperties": true}, "extraPorts": {"type": "array"}, "extraStaticConfig": {"type": "object", "additionalProperties": true}, "extraVolumes": {"type": "array"}, "extraVolumeMounts": {"type": "array"}, "hsts": {"type": "object", "additionalProperties": false, "required": ["includeSubdomains", "maxAge", "preload"], "properties": {"includeSubdomains": {"type": "boolean"}, "maxAge": {"type": "integer"}, "preload": {"type": "boolean"}}}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "resources": {"type": "object", "additionalProperties": true}, "serviceAccount": {"type": "object", "required": ["create"], "additionalProperties": false, "properties": {"create": {"type": "boolean"}, "name": {"type": ["string", "null"]}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}}}, "extraPodSpec": {"type": "object", "additionalProperties": true}}}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "deploymentStrategy": {"type": "object", "additionalProperties": false, "properties": {"rollingUpdate": {"type": ["string", "null"]}, "type": {"type": ["string", "null"]}}}, "secretSync": {"type": "object", "additionalProperties": false, "properties": {"containerSecurityContext": {"type": "object", "additionalProperties": true}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "resources": {"type": "object", "additionalProperties": true}}}}}, "singleuser": {"type": "object", "additionalProperties": false, "properties": {"networkPolicy": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "ingress": {"type": "array"}, "egress": {"type": "array"}, "egressAllowRules": {"type": "object", "additionalProperties": false, "properties": {"cloudMetadataServer": {"type": "boolean"}, "dnsPortsCloudMetadataServer": {"type": "boolean"}, "dnsPortsKubeSystemNamespace": {"type": "boolean"}, "dnsPortsPrivateIPs": {"type": "boolean"}, "nonPrivateIPs": {"type": "boolean"}, "privateIPs": {"type": "boolean"}}}, "interNamespaceAccessLabels": {"enum": ["accept", "ignore"]}, "allowedIngressPorts": {"type": "array"}}}, "podNameTemplate": {"type": ["string", "null"]}, "cpu": {"type": "object", "additionalProperties": false, "properties": {"limit": {"type": ["number", "null"]}, "guarantee": {"type": ["number", "null"]}}}, "memory": {"type": "object", "additionalProperties": false, "properties": {"limit": {"type": ["number", "string", "null"]}, "guarantee": {"type": ["number", "string", "null"]}}}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "initContainers": {"type": "array"}, "profileList": {"type": "array"}, "extraFiles": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "object", "additionalProperties": false, "required": ["mountPath"], "oneOf": [{"required": ["data"]}, {"required": ["stringData"]}, {"required": ["binaryData"]}], "properties": {"mountPath": {"type": "string"}, "data": {"type": "object", "additionalProperties": true}, "stringData": {"type": "string"}, "binaryData": {"type": "string"}, "mode": {"type": "number"}}}}}, "extraEnv": {"type": ["object", "array"], "additionalProperties": true}, "nodeSelector": {"type": "object", "additionalProperties": true}, "extraTolerations": {"type": "array"}, "extraNodeAffinity": {"type": "object", "additionalProperties": false, "properties": {"required": {"type": "array"}, "preferred": {"type": "array"}}}, "extraPodAffinity": {"type": "object", "additionalProperties": false, "properties": {"required": {"type": "array"}, "preferred": {"type": "array"}}}, "extraPodAntiAffinity": {"type": "object", "additionalProperties": false, "properties": {"required": {"type": "array"}, "preferred": {"type": "array"}}}, "cloudMetadata": {"type": "object", "additionalProperties": false, "required": ["blockWithIptables", "ip"], "properties": {"blockWithIptables": {"type": "boolean"}, "ip": {"type": "string"}}}, "cmd": {"type": ["array", "string", "null"]}, "defaultUrl": {"type": ["string", "null"]}, "events": {"type": ["boolean", "null"]}, "extraAnnotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "extraContainers": {"type": "array"}, "extraLabels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "extraPodConfig": {"type": "object", "additionalProperties": true}, "extraResource": {"type": "object", "additionalProperties": false, "properties": {"guarantees": {"type": "object", "additionalProperties": true}, "limits": {"type": "object", "additionalProperties": true}}}, "fsGid": {"type": ["integer", "null"]}, "lifecycleHooks": {"type": "object", "additionalProperties": false, "properties": {"postStart": {"type": "object", "additionalProperties": true}, "preStop": {"type": "object", "additionalProperties": true}}}, "networkTools": {"type": "object", "additionalProperties": false, "properties": {"image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "resources": {"type": "object", "additionalProperties": true}}}, "serviceAccountName": {"type": ["string", "null"]}, "startTimeout": {"type": ["integer", "null"]}, "storage": {"type": "object", "additionalProperties": false, "required": ["type", "homeMountPath"], "properties": {"capacity": {"type": ["string", "null"]}, "dynamic": {"type": "object", "additionalProperties": false, "properties": {"pvcNameTemplate": {"type": ["string", "null"]}, "storageAccessModes": {"type": "array", "items": {"type": ["string", "null"]}}, "storageClass": {"type": ["string", "null"]}, "subPath": {"type": ["string", "null"]}, "volumeNameTemplate": {"type": ["string", "null"]}}}, "extraLabels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "extraVolumeMounts": {"type": "array"}, "extraVolumes": {"type": "array"}, "homeMountPath": {"type": "string"}, "static": {"type": "object", "additionalProperties": false, "properties": {"pvcName": {"type": ["string", "null"]}, "subPath": {"type": ["string", "null"]}}}, "type": {"enum": ["dynamic", "static", "none"]}}}, "allowPrivilegeEscalation": {"type": ["boolean", "null"]}, "uid": {"type": ["integer", "null"]}}}, "scheduling": {"type": "object", "additionalProperties": false, "properties": {"userScheduler": {"type": "object", "additionalProperties": false, "required": ["enabled", "plugins", "pluginConfig", "logLevel"], "properties": {"enabled": {"type": "boolean"}, "revisionHistoryLimit": {"type": ["integer", "null"], "minimum": 0}, "replicas": {"type": "integer"}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "pdb": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "maxUnavailable": {"type": ["integer", "null"]}, "minAvailable": {"type": ["integer", "null"]}}}, "nodeSelector": {"type": "object", "additionalProperties": true}, "tolerations": {"type": "array"}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "containerSecurityContext": {"type": "object", "additionalProperties": true}, "logLevel": {"type": "integer"}, "plugins": {"type": "object", "additionalProperties": true}, "pluginConfig": {"type": "array"}, "resources": {"type": "object", "additionalProperties": true}, "serviceAccount": {"type": "object", "required": ["create"], "additionalProperties": false, "properties": {"create": {"type": "boolean"}, "name": {"type": ["string", "null"]}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}}}, "extraPodSpec": {"type": "object", "additionalProperties": true}}}, "podPriority": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "globalDefault": {"type": "boolean"}, "defaultPriority": {"type": "integer"}, "imagePullerPriority": {"type": "integer"}, "userPlaceholderPriority": {"type": "integer"}}}, "userPlaceholder": {"type": "object", "additionalProperties": false, "properties": {"enabled": {"type": "boolean"}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "revisionHistoryLimit": {"type": ["integer", "null"], "minimum": 0}, "replicas": {"type": "integer"}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "resources": {"type": "object", "additionalProperties": true}, "containerSecurityContext": {"type": "object", "additionalProperties": true}}}, "corePods": {"type": "object", "additionalProperties": false, "properties": {"tolerations": {"type": "array"}, "nodeAffinity": {"type": "object", "additionalProperties": false, "properties": {"matchNodePurpose": {"enum": ["ignore", "prefer", "require"]}}}}}, "userPods": {"type": "object", "additionalProperties": false, "properties": {"tolerations": {"type": "array"}, "nodeAffinity": {"type": "object", "additionalProperties": false, "properties": {"matchNodePurpose": {"enum": ["ignore", "prefer", "require"]}}}}}}}, "ingress": {"type": "object", "additionalProperties": false, "required": ["enabled"], "properties": {"enabled": {"type": "boolean"}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "ingressClassName": {"type": ["string", "null"]}, "hosts": {"type": "array"}, "pathSuffix": {"type": ["string", "null"]}, "pathType": {"enum": ["Prefix", "Exact", "ImplementationSpecific"]}, "tls": {"type": "array"}, "extraPaths": {"type": "array"}}}, "prePuller": {"type": "object", "additionalProperties": false, "required": ["hook", "continuous"], "properties": {"revisionHistoryLimit": {"type": ["integer", "null"], "minimum": 0}, "labels": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}, "resources": {"type": "object", "additionalProperties": true}, "extraTolerations": {"type": "array"}, "hook": {"type": "object", "additionalProperties": false, "required": ["enabled"], "properties": {"enabled": {"type": "boolean"}, "pullOnlyOnChanges": {"type": "boolean"}, "podSchedulingWaitDuration": {"type": "integer"}, "nodeSelector": {"type": "object", "additionalProperties": true}, "tolerations": {"type": "array"}, "containerSecurityContext": {"type": "object", "additionalProperties": true}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}, "resources": {"type": "object", "additionalProperties": true}, "serviceAccount": {"type": "object", "required": ["create"], "additionalProperties": false, "properties": {"create": {"type": "boolean"}, "name": {"type": ["string", "null"]}, "annotations": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "string"}}}}}}}, "continuous": {"type": "object", "additionalProperties": false, "required": ["enabled"], "properties": {"enabled": {"type": "boolean"}}}, "pullProfileListImages": {"type": "boolean"}, "extraImages": {"type": "object", "additionalProperties": false, "patternProperties": {".*": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}}}}}, "containerSecurityContext": {"type": "object", "additionalProperties": true}, "pause": {"type": "object", "additionalProperties": false, "properties": {"containerSecurityContext": {"type": "object", "additionalProperties": true}, "image": {"type": "object", "additionalProperties": false, "required": ["name", "tag"], "properties": {"name": {"type": "string"}, "tag": {"type": "string"}, "pullPolicy": {"enum": [null, "", "IfNotPresent", "Always", "Never"]}, "pullSecrets": {"type": "array"}}}}}}}, "custom": {"type": "object", "additionalProperties": true}, "cull": {"type": "object", "additionalProperties": false, "required": ["enabled"], "properties": {"enabled": {"type": "boolean"}, "users": {"type": ["boolean", "null"]}, "adminUsers": {"type": ["boolean", "null"]}, "removeNamedServers": {"type": ["boolean", "null"]}, "timeout": {"type": ["integer", "null"]}, "every": {"type": ["integer", "null"]}, "concurrency": {"type": ["integer", "null"]}, "maxAge": {"type": ["integer", "null"]}}}, "debug": {"type": "object", "additionalProperties": false, "required": ["enabled"], "properties": {"enabled": {"type": "boolean"}}}, "rbac": {"type": "object", "additionalProperties": false, "required": ["create"], "properties": {"enabled": {"type": "boolean"}, "create": {"type": "boolean"}}}, "global": {"type": "object", "additionalProperties": true, "properties": {"safeToShowValues": {"type": "boolean"}}}}} \ No newline at end of file diff --git a/jupyter/base/charts/jupyterhub/values.yaml b/jupyter/base/charts/jupyterhub/values.yaml index eaa3875..4e35607 100644 --- a/jupyter/base/charts/jupyterhub/values.yaml +++ b/jupyter/base/charts/jupyterhub/values.yaml @@ -41,6 +41,7 @@ hub: annotations: {} ports: nodePort: + appProtocol: extraPorts: [] loadBalancerIP: baseUrl: / @@ -84,16 +85,21 @@ hub: extraVolumeMounts: [] image: name: quay.io/jupyterhub/k8s-hub - tag: "3.2.1" + tag: "4.0.0" pullPolicy: pullSecrets: [] resources: {} podSecurityContext: + runAsNonRoot: true fsGroup: 1000 + seccompProfile: + type: "RuntimeDefault" containerSecurityContext: runAsUser: 1000 runAsGroup: 1000 allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] lifecycle: {} loadRoles: {} services: {} @@ -197,15 +203,20 @@ proxy: chp: revisionHistoryLimit: containerSecurityContext: + runAsNonRoot: true runAsUser: 65534 # nobody user runAsGroup: 65534 # nobody group allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" image: name: quay.io/jupyterhub/configurable-http-proxy # tag is automatically bumped to new patch versions by the # watch-dependencies.yaml workflow. # - tag: "4.6.1" # https://github.com/jupyterhub/configurable-http-proxy/tags + tag: "4.6.2" # https://github.com/jupyterhub/configurable-http-proxy/tags pullPolicy: pullSecrets: [] extraCommandLineFlags: [] @@ -250,15 +261,20 @@ proxy: traefik: revisionHistoryLimit: containerSecurityContext: + runAsNonRoot: true runAsUser: 65534 # nobody user runAsGroup: 65534 # nobody group allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" image: name: traefik # tag is automatically bumped to new patch versions by the # watch-dependencies.yaml workflow. # - tag: "v2.10.5" # ref: https://hub.docker.com/_/traefik?tab=tags + tag: "v3.2.0" # ref: https://hub.docker.com/_/traefik?tab=tags pullPolicy: pullSecrets: [] hsts: @@ -300,12 +316,17 @@ proxy: extraPodSpec: {} secretSync: containerSecurityContext: + runAsNonRoot: true runAsUser: 65534 # nobody user runAsGroup: 65534 # nobody group allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" image: name: quay.io/jupyterhub/k8s-secret-sync - tag: "3.2.1" + tag: "4.0.0" pullPolicy: pullSecrets: [] resources: {} @@ -345,7 +366,7 @@ singleuser: networkTools: image: name: quay.io/jupyterhub/k8s-network-tools - tag: "3.2.1" + tag: "4.0.0" pullPolicy: pullSecrets: [] resources: {} @@ -392,12 +413,13 @@ singleuser: homeMountPath: /home/jovyan dynamic: storageClass: - pvcNameTemplate: claim-{username}{servername} - volumeNameTemplate: volume-{username}{servername} + pvcNameTemplate: + volumeNameTemplate: volume-{user_server} storageAccessModes: [ReadWriteOnce] + subPath: image: name: quay.io/jupyterhub/k8s-singleuser-sample - tag: "3.2.1" + tag: "4.0.0" pullPolicy: pullSecrets: [] startTimeout: 300 @@ -432,19 +454,24 @@ scheduling: # plugins: score: - # These scoring plugins are enabled by default according to - # https://kubernetes.io/docs/reference/scheduling/config/#scheduling-plugins - # 2022-02-22. + # We make use of the default scoring plugins, but we re-enable some with + # a new priority, leave some enabled with their lower default priority, + # and disable some. # - # Enabled with high priority: + # Below are the default scoring plugins as of 2024-09-23 according to + # https://kubernetes.io/docs/reference/scheduling/config/#scheduling-plugins. + # + # Re-enabled with high priority: # - NodeAffinity # - InterPodAffinity # - NodeResourcesFit # - ImageLocality + # # Remains enabled with low default priority: # - TaintToleration # - PodTopologySpread # - VolumeBinding + # # Disabled for scoring: # - NodeResourcesBalancedAllocation # @@ -473,20 +500,25 @@ scheduling: - name: NodeResourcesFit args: scoringStrategy: + type: MostAllocated resources: - name: cpu weight: 1 - name: memory weight: 1 - type: MostAllocated containerSecurityContext: + runAsNonRoot: true runAsUser: 65534 # nobody user runAsGroup: 65534 # nobody group allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" image: # IMPORTANT: Bumping the minor version of this binary should go hand in - # hand with an inspection of the user-scheduelrs RBAC resources - # that we have forked in + # hand with an inspection of the user-scheduelr's RBAC + # resources that we have forked in # templates/scheduling/user-scheduler/rbac.yaml. # # Debugging advice: @@ -519,7 +551,7 @@ scheduling: # here. We aim to stay around 1 minor version behind the latest k8s # version. # - tag: "v1.26.11" # ref: https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG + tag: "v1.30.6" # ref: https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG pullPolicy: pullSecrets: [] nodeSelector: {} @@ -551,7 +583,7 @@ scheduling: # # If you update this, also update prePuller.pause.image.tag # - tag: "3.9" + tag: "3.10" pullPolicy: pullSecrets: [] revisionHistoryLimit: @@ -559,9 +591,14 @@ scheduling: labels: {} annotations: {} containerSecurityContext: + runAsNonRoot: true runAsUser: 65534 # nobody user runAsGroup: 65534 # nobody group allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" resources: {} corePods: tolerations: @@ -595,9 +632,14 @@ prePuller: annotations: {} resources: {} containerSecurityContext: + runAsNonRoot: true runAsUser: 65534 # nobody user runAsGroup: 65534 # nobody group allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" extraTolerations: [] # hook relates to the hook-image-awaiter Job and hook-image-puller DaemonSet hook: @@ -606,13 +648,18 @@ prePuller: # image and the configuration below relates to the hook-image-awaiter Job image: name: quay.io/jupyterhub/k8s-image-awaiter - tag: "3.2.1" + tag: "4.0.0" pullPolicy: pullSecrets: [] containerSecurityContext: + runAsNonRoot: true runAsUser: 65534 # nobody user runAsGroup: 65534 # nobody group allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" podSchedulingWaitDuration: 10 nodeSelector: {} tolerations: [] @@ -627,9 +674,14 @@ prePuller: extraImages: {} pause: containerSecurityContext: + runAsNonRoot: true runAsUser: 65534 # nobody user runAsGroup: 65534 # nobody group allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + seccompProfile: + type: "RuntimeDefault" image: name: registry.k8s.io/pause # tag is automatically bumped to new patch versions by the @@ -637,7 +689,7 @@ prePuller: # # If you update this, also update scheduling.userPlaceholder.image.tag # - tag: "3.9" + tag: "3.10" pullPolicy: pullSecrets: [] @@ -649,6 +701,7 @@ ingress: pathSuffix: pathType: Prefix tls: [] + extraPaths: [] # cull relates to the jupyterhub-idle-culler service, responsible for evicting # inactive singleuser pods. diff --git a/jupyter/base/jupyterhub-ingress.yml b/jupyter/base/jupyterhub-ingress.yml index 2d95dbc..d0667c8 100644 --- a/jupyter/base/jupyterhub-ingress.yml +++ b/jupyter/base/jupyterhub-ingress.yml @@ -4,7 +4,6 @@ kind: Ingress metadata: name: jupyterhub-ingress annotations: - kubernetes.io/ingress.class: traefik traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.tls: "true" spec: diff --git a/jupyter/overlays/test/vr/kustomization.yaml b/jupyter/overlays/test/vr/kustomization.yaml index aad0b00..8cbec9e 100644 --- a/jupyter/overlays/test/vr/kustomization.yaml +++ b/jupyter/overlays/test/vr/kustomization.yaml @@ -5,10 +5,10 @@ resources: [../../../base/] helmCharts: - includeCRDs: true name: jupyterhub - releaseName: uu-jupyterhub + releaseName: vr-jupyterhub valuesFile: ./values/values.yaml - version: 3.2.1 - namespace: uu-jupyterhub + version: 4.0.0 + namespace: vr-jupyterhub helmGlobals: chartHome: ../../../base/charts/ patches: diff --git a/jupyter/overlays/test/vr/values/values.yaml b/jupyter/overlays/test/vr/values/values.yaml index 321453d..b6162e3 100644 --- a/jupyter/overlays/test/vr/values/values.yaml +++ b/jupyter/overlays/test/vr/values/values.yaml @@ -277,8 +277,8 @@ hub: name: refresh-token extraEnv: NEXTCLOUD_DEBUG_OAUTH: "no" - NEXTCLOUD_HOST: uu.drive.test.sunet.se - JUPYTER_HOST: uu-jupyter.drive.test.sunet.se + NEXTCLOUD_HOST: vr.drive.test.sunet.se + JUPYTER_HOST: vr-jupyter.drive.test.sunet.se JUPYTERHUB_API_KEY: valueFrom: secretKeyRef: @@ -321,8 +321,8 @@ singleuser: storageClass: csi-sc-cinderplugin extraEnv: JUPYTER_ENABLE_LAB: "yes" - JUPYTER_HOST: uu-jupyter.drive.test.sunet.se - NEXTCLOUD_HOST: uu.drive.test.sunet.se + JUPYTER_HOST: vr-jupyter.drive.test.sunet.se + NEXTCLOUD_HOST: vr.drive.test.sunet.se extraFiles: jupyter_notebook_config: mountPath: /home/jovyan/.jupyter/jupyter_server_config.py