224 lines
7.5 KiB
YAML
224 lines
7.5 KiB
YAML
hub:
|
|
config:
|
|
JupyterHub:
|
|
authenticator_class: generic-oauth
|
|
admin_access: false
|
|
|
|
Authenticator:
|
|
enable_auth_state: true
|
|
allow_all: true # allow all Keycloak users
|
|
|
|
GenericOAuthenticator:
|
|
client_id: {{ .Env.JUPYTERHUB_OIDC_CLIENT_ID }}
|
|
oauth_callback_url: "https://{{ .Env.JUPYTERHUB_HOST }}/hub/oauth_callback"
|
|
authorize_url: "https://{{ .Env.KEYCLOAK_HOST }}/realms/{{ .Env.KEYCLOAK_REALM }}/protocol/openid-connect/auth"
|
|
token_url: "https://{{ .Env.KEYCLOAK_HOST }}/realms/{{ .Env.KEYCLOAK_REALM }}/protocol/openid-connect/token"
|
|
userdata_url: "https://{{ .Env.KEYCLOAK_HOST }}/realms/{{ .Env.KEYCLOAK_REALM }}/protocol/openid-connect/userinfo"
|
|
login_service: keycloak
|
|
# username_claim: email
|
|
username_claim: preferred_username
|
|
|
|
OAuthenticator:
|
|
scope:
|
|
- openid
|
|
- profile
|
|
- email
|
|
|
|
{{- if eq .Env.JUPYTERHUB_VAULT_INTEGRATION_ENABLED "true" }}
|
|
extraConfig:
|
|
01-vault-integration: |
|
|
import os
|
|
|
|
async def pre_spawn_hook(spawner):
|
|
"""Pass OIDC tokens and Vault config to notebook environment"""
|
|
auth_state = await spawner.user.get_auth_state()
|
|
if auth_state:
|
|
if 'access_token' in auth_state:
|
|
spawner.environment['JUPYTERHUB_OIDC_ACCESS_TOKEN'] = auth_state['access_token']
|
|
if 'refresh_token' in auth_state:
|
|
spawner.environment['JUPYTERHUB_OIDC_REFRESH_TOKEN'] = auth_state['refresh_token']
|
|
if 'id_token' in auth_state:
|
|
spawner.environment['JUPYTERHUB_OIDC_ID_TOKEN'] = auth_state['id_token']
|
|
if 'expires_at' in auth_state:
|
|
spawner.environment['JUPYTERHUB_OIDC_TOKEN_EXPIRES_AT'] = str(auth_state['expires_at'])
|
|
|
|
# Add Keycloak configuration for token refresh
|
|
spawner.environment['KEYCLOAK_HOST'] = '{{ .Env.KEYCLOAK_HOST }}'
|
|
spawner.environment['KEYCLOAK_REALM'] = '{{ .Env.KEYCLOAK_REALM }}'
|
|
spawner.environment['KEYCLOAK_CLIENT_ID'] = 'jupyterhub'
|
|
|
|
c.Spawner.pre_spawn_hook = pre_spawn_hook
|
|
{{- end }}
|
|
02-postgres-integration: |
|
|
from functools import wraps
|
|
|
|
# Store the original pre_spawn_hook if it exists
|
|
original_hook = c.Spawner.pre_spawn_hook if hasattr(c.Spawner, 'pre_spawn_hook') else None
|
|
|
|
async def postgres_pre_spawn_hook(spawner):
|
|
"""Add PostgreSQL connection information to notebook environment"""
|
|
# Call the original hook first if it exists
|
|
if original_hook:
|
|
await original_hook(spawner)
|
|
|
|
# Add PostgreSQL configuration
|
|
spawner.environment['POSTGRES_HOST'] = 'postgres-cluster-rw.postgres'
|
|
spawner.environment['POSTGRES_PORT'] = '5432'
|
|
|
|
c.Spawner.pre_spawn_hook = postgres_pre_spawn_hook
|
|
|
|
podSecurityContext:
|
|
fsGroup: {{ .Env.JUPYTER_FSGID }}
|
|
|
|
singleuser:
|
|
storage:
|
|
{{ if env.Getenv "PVC_NAME" -}}
|
|
type: static
|
|
static:
|
|
pvcName: {{ .Env.PVC_NAME }}
|
|
{{ else -}}
|
|
type: dynamic
|
|
dynamic:
|
|
storageClass: longhorn
|
|
storageAccessModes:
|
|
- ReadWriteOnce
|
|
{{ end -}}
|
|
capacity: 10Gi
|
|
|
|
{{- if eq .Env.JUPYTERHUB_VAULT_INTEGRATION_ENABLED "true" }}
|
|
extraEnv:
|
|
VAULT_ADDR: "{{ .Env.VAULT_ADDR }}"
|
|
KEYCLOAK_HOST: "{{ .Env.KEYCLOAK_HOST }}"
|
|
KEYCLOAK_REALM: "{{ .Env.KEYCLOAK_REALM }}"
|
|
|
|
# lifecycleHooks:
|
|
# postStart:
|
|
# exec:
|
|
# command:
|
|
# - /bin/bash
|
|
# - -c
|
|
# - |
|
|
# # Install hvac for Vault integration
|
|
# mamba install hvac requests
|
|
# echo "Vault integration ready"
|
|
{{- end }}
|
|
networkPolicy:
|
|
egress:
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: chroma
|
|
ports:
|
|
- port: 8000
|
|
protocol: TCP
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: qdrant
|
|
ports:
|
|
- port: 6333
|
|
protocol: TCP
|
|
- port: 6334
|
|
protocol: TCP
|
|
- port: 6335
|
|
protocol: TCP
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: litellm
|
|
ports:
|
|
- port: 4000
|
|
protocol: TCP
|
|
{{- if eq .Env.JUPYTERHUB_VAULT_INTEGRATION_ENABLED "true" }}
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: vault
|
|
ports:
|
|
- port: 8200
|
|
protocol: TCP
|
|
- port: 8201
|
|
protocol: TCP
|
|
{{- end }}
|
|
- to:
|
|
- ipBlock:
|
|
cidr: 0.0.0.0/0
|
|
ports:
|
|
- port: 443
|
|
protocol: TCP
|
|
domains:
|
|
- '*.shds.dev'
|
|
|
|
image:
|
|
pullPolicy: IfNotPresent
|
|
|
|
profileList:
|
|
# https://quay.io/repository/jupyter/pyspark-notebook
|
|
{{- if eq .Env.JUPYTER_PROFILE_MINIMAL_ENABLED "true" }}
|
|
- display_name: "Minimal Jupyter Notebook Stack"
|
|
description: "Minimal Jupyter Notebook Stack"
|
|
kubespawner_override:
|
|
image: quay.io/jupyter/minimal-notebook
|
|
{{- end }}
|
|
{{ if eq .Env.JUPYTER_PROFILE_BASE_ENABLED "true" }}
|
|
- display_name: "Base Jupyter Notebook Stack"
|
|
description: "Base Jupyter Notebook Stack"
|
|
kubespawner_override:
|
|
image: quay.io/jupyter/base-notebook
|
|
{{- end }}
|
|
{{- if eq .Env.JUPYTER_PROFILE_DATASCIENCE_ENABLED "true" }}
|
|
- display_name: "Jupyter Notebook Data Science Stack"
|
|
description: "Jupyter Notebook Data Science Stack"
|
|
kubespawner_override:
|
|
image: quay.io/jupyter/datascience-notebook
|
|
{{- end }}
|
|
{{- if eq .Env.JUPYTER_PROFILE_PYSPARK_ENABLED "true" }}
|
|
- display_name: "Jupyter Notebook Python, Spark Stack"
|
|
description: "Jupyter Notebook Python, Spark Stack"
|
|
kubespawner_override:
|
|
image: quay.io/jupyter/pyspark-notebook
|
|
{{- end }}
|
|
{{- if eq .Env.JUPYTER_PROFILE_PYTORCH_ENABLED "true" }}
|
|
- display_name: "Jupyter Notebook PyTorch Deep Learning Stack"
|
|
description: "Jupyter Notebook PyTorch Deep Learning Stack"
|
|
kubespawner_override:
|
|
image: quay.io/jupyter/pytorch-notebook
|
|
{{- end }}
|
|
{{- if eq .Env.JUPYTER_PROFILE_TENSORFLOW_ENABLED "true" }}
|
|
- display_name: "Jupyter Notebook TensorFlow Deep Learning Stack"
|
|
description: "Jupyter Notebook TensorFlow Deep Learning Stack"
|
|
kubespawner_override:
|
|
image: quay.io/jupyter/tensorflow-notebook
|
|
{{- end }}
|
|
{{- if eq .Env.JUPYTER_PROFILE_BUUN_STACK_ENABLED "true" }}
|
|
- display_name: "Buun-stack"
|
|
description: "Jupyter Notebook with buun-stack"
|
|
kubespawner_override:
|
|
image: "{{ .Env.IMAGE_REGISTRY }}/{{ .Env.KERNEL_IMAGE_BUUN_STACK_REPOSITORY }}:{{ .Env.JUPYTER_PYTHON_KERNEL_TAG }}"
|
|
{{- end }}
|
|
{{- if eq .Env.JUPYTER_PROFILE_BUUN_STACK_CUDA_ENABLED "true" }}
|
|
- display_name: "Buun-stack with CUDA"
|
|
description: "Jupyter Notebook with buun-stack and CUDA support"
|
|
kubespawner_override:
|
|
image: "{{ .Env.IMAGE_REGISTRY }}/{{ .Env.KERNEL_IMAGE_BUUN_STACK_CUDA_REPOSITORY }}:{{ .Env.JUPYTER_PYTHON_KERNEL_TAG }}"
|
|
# resources:
|
|
# requests:
|
|
# nvidia.com/gpu: "1"
|
|
{{- end }}
|
|
|
|
imagePullSecrets:
|
|
- name: regcred
|
|
|
|
ingress:
|
|
enabled: true
|
|
annotations:
|
|
kubernetes.io/ingress.class: traefik
|
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
|
ingressClassName: traefik
|
|
hosts:
|
|
- {{ .Env.JUPYTERHUB_HOST }}
|
|
pathType: Prefix
|
|
tls:
|
|
- hosts:
|
|
- {{ .Env.JUPYTERHUB_HOST }}
|