jupyterlab

This commit is contained in:
ychangkim
2026-03-26 15:14:05 +09:00
parent d3d3ee8496
commit af34d9280e
12 changed files with 936 additions and 0 deletions
@@ -0,0 +1,157 @@
# Chart 개발 및 빌드 가이드
이 문서는 JupyterLab Helm chart의 구조와 템플릿 개발, 검증 방법을 설명합니다.
## 디렉토리 구조
```
jupyterlab/
├── Chart.yaml # 차트 메타데이터
├── values.yaml # 기본값 정의
├── custom-values.yaml # 환경별 override 예시
├── README.md # 사용자 가이드
├── CUSTOM-README.md # custom-values 작성 가이드
├── BUILD-README.md # 이 파일 (개발/빌드 가이드)
└── templates/
├── _helpers.tpl # 재사용 헬퍼 함수 정의
├── deployment.yaml # Deployment 리소스
├── service.yaml # Service 리소스
├── ingress.yaml # Ingress 리소스
├── pvc.yaml # PersistentVolumeClaim 리소스
└── configmap.yaml # ConfigMap (startup-script.sh)
```
## 템플릿 구조 설명
### `_helpers.tpl` — 헬퍼 함수
| 함수 | 반환값 예시 | 설명 |
|------|------------|------|
| `jupyterlab.name` | `my-jupyter` | 릴리즈 이름 그대로 사용 |
| `jupyterlab.configMapName` | `my-jupyter-scripts` | ConfigMap 이름 |
| `jupyterlab.homePvcName` | `pvc-my-jupyter-home` | 홈 PVC 이름 |
| `jupyterlab.dataPvcName` | `pvc-my-jupyter-data` | 데이터 PVC 이름 |
| `jupyterlab.homeDir` | `/home/jovyan` | `homeVolume.mountPath` 또는 기본값 |
| `jupyterlab.dataDir` | `/home/jovyan/data` | `<homeDir>/<dataVolume.mountPath>` |
| `jupyterlab.labels` | (라벨 맵) | 공통 라벨 세트 |
| `jupyterlab.image` | `quay.io/jupyter/scipy-notebook:latest` | 전체 이미지 참조 |
| `jupyterlab.command` | (bash 커맨드 배열) | JupyterLab 시작 커맨드 |
### `deployment.yaml`
- `replicas`: `values.replicas`
- 보안 컨텍스트: Pod 레벨 `runAsUser: 1000 / fsGroup: 100`, Container 레벨 `runAsUser: 0`
- readinessProbe: `tcpSocket:8888`, 초기 30초 대기, 10초 주기, 27회 실패 허용 (총 ~5분)
- 볼륨: `localtime`, `startup-script` (항상), `home-volume`, `data-volume`, `groupVolumes` (조건부)
### `configmap.yaml`
startup-script.sh 내용:
```bash
#!/bin/bash
apt-get update -y
python -m pip install --upgrade pip
```
이 스크립트는 `/usr/local/bin/start-notebook.d/` 에 마운트되어 JupyterLab 시작 전 자동 실행됩니다.
추가 패키지 설치가 필요하면 이 파일을 수정하세요.
### `pvc.yaml`
- `homeVolume.enabled: true` 일 때만 `pvc-<release>-home` 생성
- `dataVolume.enabled: true` 일 때만 `pvc-<release>-data` 생성
- `storageClassName`이 비어 있으면 클러스터 기본 StorageClass 사용
- PVC 보존 필요 시 주석 해제: `helm.sh/resource-policy: keep`
### `ingress.yaml`
- `ingress.enabled: false` 이면 리소스 생성 안 함
- annotations는 `range`로 동적 주입 (Kong, cert-manager 설정 포함)
- pathType은 `Prefix`로 고정
## 개발 시 자주 쓰는 명령어
### 렌더링 검증
```bash
# 전체 렌더링 출력
helm template my-jupyter . -f custom-values.yaml
# 특정 리소스만 확인
helm template my-jupyter . -f custom-values.yaml | \
kubectl neat | grep -A50 "kind: Deployment"
# values 병합 결과 확인
helm template my-jupyter . -f custom-values.yaml --debug 2>&1 | head -50
```
### Lint
```bash
helm lint . -f custom-values.yaml
```
### values 스키마 검증 (schema 파일 추가 시)
```bash
helm template my-jupyter . -f custom-values.yaml --validate
```
### 실 클러스터 dry-run
```bash
helm install my-jupyter . \
--namespace jupyter \
--create-namespace \
-f custom-values.yaml \
--dry-run
```
## 새 기능 추가 시 체크리스트
- [ ] `values.yaml`에 새 키와 기본값 추가
- [ ] `_helpers.tpl`에 필요한 헬퍼 함수 추가
- [ ] 해당 템플릿 파일에 조건부 블록으로 구현 (`{{- if .Values.xxx }}`)
- [ ] `custom-values.yaml`에 예시값 반영
- [ ] `helm lint` 통과 확인
- [ ] `helm template` 렌더링 결과 확인
- [ ] `README.md` Values 테이블 업데이트
## 자주 발생하는 오류
### Error: YAML parse error
`values.yaml`이나 `custom-values.yaml`의 들여쓰기 오류.
`helm lint` 로 위치 확인.
### Error: template: jupyterlab/templates/xxx.yaml: ... nil pointer evaluating
`values.yaml`에 존재하지 않는 키를 템플릿에서 참조할 때 발생.
`_helpers.tpl`에서 `default` 함수 사용:
```
{{ .Values.some.key | default "fallback" }}
```
### PVC Pending 상태
`storageClassName`이 클러스터에 없는 경우.
`kubectl get storageclass` 로 사용 가능한 클래스 확인 후 설정.
### Pod CrashLoopBackOff
startup-script.sh 오류 가능성 높음.
`kubectl logs <pod> -n <namespace>` 로 스크립트 실행 로그 확인.
## Chart 버전 관리
`Chart.yaml``version` 필드는 **SemVer** 규칙을 따릅니다.
| 변경 유형 | 버전 업 | 예시 |
|----------|---------|------|
| 하위 호환 버그 픽스 | patch | `1.0.0``1.0.1` |
| 새 기능 추가 (하위 호환) | minor | `1.0.0``1.1.0` |
| 하위 비호환 변경 | major | `1.0.0``2.0.0` |
`appVersion`은 JupyterLab 애플리케이션 버전을 나타내며, chart version과 별도로 관리합니다.
@@ -0,0 +1,215 @@
# custom-values.yaml 사용 가이드
이 문서는 `custom-values.yaml`을 작성하고 배포에 적용하는 방법을 설명합니다.
## Helm Values Merge 동작 방식
Helm은 `--values` 플래그로 전달된 파일을 기본 `values.yaml`**deep merge** 방식으로 적용합니다.
- `custom-values.yaml`에 명시된 키는 `values.yaml` 기본값을 **덮어씁니다**
- 명시하지 않은 키는 `values.yaml` 기본값이 **그대로 유지됩니다**
- 중첩 객체(`resources`, `ingress` 등)도 키 단위로 병합됩니다
```
values.yaml (기본값)
+
custom-values.yaml (override)
=
최종 적용값
```
## custom-values.yaml 필드 설명
### image
```yaml
image:
registry: "quay.io" # 레지스트리 주소. 비워두면 Docker Hub 사용
repository: "jupyter/scipy-notebook"
tag: "latest" # 특정 버전 고정 권장 (예: "2024-01-15")
```
> `image.pullPolicy`는 custom-values에 없으므로 `values.yaml` 기본값 `IfNotPresent` 적용
### resources
```yaml
resources:
limits:
cpu: "2000m" # 최대 2 vCPU
memory: "4096Mi" # 최대 4 GiB
requests:
cpu: "500m" # 예약 0.5 vCPU
memory: "1024Mi" # 예약 1 GiB
gpu: "" # GPU 사용 시: "1" (nvidia.com/gpu limits/requests에 동일하게 설정됨)
```
### jupyterConfig
```yaml
jupyterConfig:
token: "" # 비어 있으면 토큰 인증 비활성화
# 값 설정 시 SHA-256으로 해시되어 ServerApp.password에 적용
```
### ingress
```yaml
ingress:
enabled: true
ingressClassName: "kong"
annotations:
cert-manager.io/cluster-issuer: "root-ca-issuer"
cert-manager.io/duration: "8760h"
cert-manager.io/renew-before: "720h"
konghq.com/https-redirect-status-code: "301"
konghq.com/protocols: "https"
hosts:
- host: "jupyter.example.com" # 실제 도메인으로 변경 필수
paths:
- /
tls:
- hosts:
- "jupyter.example.com"
secretName: "jupyter-tls-secret"
```
### homeVolume / dataVolume
```yaml
homeVolume:
enabled: false # true로 설정 시 /home/jovyan에 PVC 마운트
size: "5Gi"
storageClassName: "" # 클러스터 기본 StorageClass 사용
accessMode: "ReadWriteOnce"
# mountPath: "" # custom-values에 없음 → 기본값 /home/jovyan 적용
dataVolume:
enabled: false # true로 설정 시 /home/jovyan/data에 PVC 마운트
size: "5Gi"
storageClassName: ""
accessMode: "ReadWriteOnce"
# mountPath: "" # custom-values에 없음 → 기본값 "data" 적용
```
### groupVolumes
```yaml
groupVolumes: []
# 공유 PVC 마운트 예시:
# groupVolumes:
# - claimName: "pvc-shared-data"
# mountPath: "/group_data"
# - claimName: "pvc-team-models"
# mountPath: "/models"
```
## custom-values.yaml 미포함 필드 (values.yaml 기본값 적용)
| 필드 | 기본값 | 비고 |
|------|--------|------|
| `image.pullPolicy` | `IfNotPresent` | |
| `replicas` | `1` | 0으로 설정하면 Pod 중지 |
| `homeVolume.mountPath` | `""``/home/jovyan` | |
| `dataVolume.mountPath` | `""``data` | |
| `imagePullSecrets` | `[]` | Private 레지스트리 사용 시 추가 필요 |
## 배포 명령어
```bash
# 렌더링 미리보기 (실제 배포 없음)
helm template my-jupyter ./manifests/helm/jupyterlab \
-f ./manifests/helm/jupyterlab/custom-values.yaml
# 신규 설치
helm install my-jupyter ./manifests/helm/jupyterlab \
--namespace jupyter \
--create-namespace \
-f ./manifests/helm/jupyterlab/custom-values.yaml
# 업그레이드
helm upgrade my-jupyter ./manifests/helm/jupyterlab \
-n jupyter \
-f ./manifests/helm/jupyterlab/custom-values.yaml
# 변경 사항 확인 (helm-diff 플러그인 필요)
helm diff upgrade my-jupyter ./manifests/helm/jupyterlab \
-n jupyter \
-f ./manifests/helm/jupyterlab/custom-values.yaml
```
## 환경별 설정 예시
### 개발 환경 (최소 리소스, 인증 없음)
```yaml
image:
tag: "latest"
resources:
limits:
cpu: "500m"
memory: "1024Mi"
requests:
cpu: "100m"
memory: "256Mi"
gpu: ""
jupyterConfig:
token: ""
ingress:
enabled: true
ingressClassName: "kong"
hosts:
- host: "jupyter-dev.example.com"
paths: [/]
tls:
- hosts: ["jupyter-dev.example.com"]
secretName: "jupyter-dev-tls"
```
### 운영 환경 (토큰 인증, PVC, GPU)
```yaml
image:
tag: "2024-01-15" # 버전 고정
resources:
limits:
cpu: "4000m"
memory: "8192Mi"
requests:
cpu: "1000m"
memory: "2048Mi"
gpu: "1" # NVIDIA GPU 1개
jupyterConfig:
token: "my-secure-token"
ingress:
enabled: true
ingressClassName: "kong"
hosts:
- host: "jupyter.example.com"
paths: [/]
tls:
- hosts: ["jupyter.example.com"]
secretName: "jupyter-prod-tls"
homeVolume:
enabled: true
size: "20Gi"
storageClassName: "fast-ssd"
accessMode: "ReadWriteOnce"
dataVolume:
enabled: true
size: "100Gi"
storageClassName: "fast-ssd"
accessMode: "ReadWriteOnce"
groupVolumes:
- claimName: "pvc-shared-datasets"
mountPath: "/datasets"
```
@@ -0,0 +1,13 @@
apiVersion: v2
name: jupyterlab
description: Helm chart for deploying JupyterLab instances using pure Kubernetes resources (no Operator required)
type: application
version: 1.0.0
appVersion: "1.0"
keywords:
- jupyterlab
- jupyter
- notebook
- data-science
maintainers:
- name: paasup
+118
View File
@@ -0,0 +1,118 @@
# JupyterLab Helm Chart
Helm chart for deploying JupyterLab instances using pure Kubernetes resources (no Operator required).
## Overview
| Item | Value |
|------|-------|
| Chart Version | 1.0.0 |
| App Version | 1.0 |
| Default Image | `quay.io/jupyter/scipy-notebook:latest` |
| Port | 8888 |
| Maintainer | paasup |
## Architecture
```
Deployment
└── Container: jupyterlab (port 8888)
├── ConfigMap: startup-script.sh (pip upgrade 등 초기화)
├── Volume: /etc/localtime (Asia/Seoul)
├── Volume: homeVolume → /home/jovyan (optional)
├── Volume: dataVolume → /home/jovyan/data (optional)
└── groupVolumes → 임의 경로 (optional)
Service (ClusterIP, port 8888)
Ingress (Kong, HTTPS)
PVC: pvc-<release>-home (optional)
PVC: pvc-<release>-data (optional)
```
## Prerequisites
- Kubernetes 1.21+
- Helm 3.x
- Kong Ingress Controller
- cert-manager (TLS 사용 시)
## Installation
```bash
# 기본 설치
helm install my-jupyter ./manifests/helm/jupyterlab \
--namespace jupyter \
--create-namespace
# custom-values 적용
helm install my-jupyter ./manifests/helm/jupyterlab \
--namespace jupyter \
--create-namespace \
-f ./manifests/helm/jupyterlab/custom-values.yaml
# 설치 확인
helm status my-jupyter -n jupyter
kubectl get pods -n jupyter
```
## Upgrade / Uninstall
```bash
helm upgrade my-jupyter ./manifests/helm/jupyterlab \
-n jupyter \
-f ./manifests/helm/jupyterlab/custom-values.yaml
helm uninstall my-jupyter -n jupyter
```
## Values
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `image.registry` | string | `quay.io` | 이미지 레지스트리 |
| `image.repository` | string | `jupyter/scipy-notebook` | 이미지 리포지토리 |
| `image.tag` | string | `latest` | 이미지 태그 |
| `image.pullPolicy` | string | `IfNotPresent` | 이미지 풀 정책 |
| `replicas` | int | `1` | Pod 복제본 수 (1=실행, 0=중지) |
| `resources.limits.cpu` | string | `2000m` | CPU 제한 |
| `resources.limits.memory` | string | `4096Mi` | 메모리 제한 |
| `resources.requests.cpu` | string | `500m` | CPU 요청 |
| `resources.requests.memory` | string | `1024Mi` | 메모리 요청 |
| `resources.gpu` | string | `""` | NVIDIA GPU 수 (비어 있으면 비활성화) |
| `jupyterConfig.token` | string | `""` | 접근 토큰 (비어 있으면 인증 비활성화) |
| `ingress.enabled` | bool | `true` | Ingress 활성화 여부 |
| `ingress.ingressClassName` | string | `kong` | Ingress 클래스 |
| `ingress.hosts` | list | `[{host: jupyter.example.com, paths: ["/"]}]` | 호스트 설정 |
| `ingress.tls` | list | `[{hosts: [...], secretName: ...}]` | TLS 설정 |
| `homeVolume.enabled` | bool | `false` | 홈 디렉토리 PVC 활성화 |
| `homeVolume.mountPath` | string | `""` | 마운트 경로 (기본: `/home/jovyan`) |
| `homeVolume.size` | string | `5Gi` | PVC 크기 |
| `homeVolume.storageClassName` | string | `""` | StorageClass 이름 |
| `homeVolume.accessMode` | string | `ReadWriteOnce` | 접근 모드 |
| `dataVolume.enabled` | bool | `false` | 데이터 디렉토리 PVC 활성화 |
| `dataVolume.mountPath` | string | `""` | 서브 디렉토리 이름 (기본: `data`) |
| `dataVolume.size` | string | `5Gi` | PVC 크기 |
| `dataVolume.storageClassName` | string | `""` | StorageClass 이름 |
| `dataVolume.accessMode` | string | `ReadWriteOnce` | 접근 모드 |
| `groupVolumes` | list | `[]` | 공유 그룹 볼륨 목록 |
| `imagePullSecrets` | list | `[]` | Private 레지스트리 시크릿 |
## Generated Resource Names
릴리즈 이름이 `my-jupyter`일 경우:
| 리소스 | 이름 |
|--------|------|
| Deployment | `my-jupyter` |
| Service | `my-jupyter` |
| Ingress | `my-jupyter` |
| ConfigMap | `my-jupyter-scripts` |
| Home PVC | `pvc-my-jupyter-home` |
| Data PVC | `pvc-my-jupyter-data` |
## Notes
- Pod는 `runAsUser: 1000`, `fsGroup: 100`으로 실행됩니다.
- Container는 `runAsUser: 0` (root)으로 실행됩니다 (pip install 등을 위해).
- 토큰 미설정 시 인증 없이 JupyterLab에 접근 가능합니다. 운영 환경에서는 `jupyterConfig.token`을 설정하거나 별도 인증 레이어를 구성하세요.
- PVC는 `helm uninstall` 시 삭제됩니다. 데이터 보존이 필요하면 `pvc.yaml``helm.sh/resource-policy: keep` 주석을 해제하세요.
- `/etc/localtime`은 호스트의 `Asia/Seoul` zoneinfo를 마운트합니다.
@@ -0,0 +1,49 @@
image:
registry: "quay.io"
repository: "jupyter/scipy-notebook"
tag: "latest"
resources:
limits:
cpu: "2000m"
memory: "4096Mi"
requests:
cpu: "500m"
memory: "1024Mi"
gpu: ""
jupyterConfig:
token: ""
ingress:
enabled: true
ingressClassName: "kong"
annotations:
cert-manager.io/cluster-issuer: "root-ca-issuer"
cert-manager.io/duration: "8760h"
cert-manager.io/renew-before: "720h"
konghq.com/https-redirect-status-code: "301"
konghq.com/protocols: "https"
hosts:
- host: "jupyter.example.com"
paths:
- /
tls:
- hosts:
- "jupyter.example.com"
secretName: "jupyter-tls-secret"
homeVolume:
enabled: false
size: "5Gi"
storageClassName: ""
accessMode: "ReadWriteOnce"
dataVolume:
enabled: false
size: "5Gi"
storageClassName: ""
accessMode: "ReadWriteOnce"
groupVolumes: []
@@ -0,0 +1,93 @@
{{/*
Common resource name: uses Helm release name
*/}}
{{- define "jupyterlab.name" -}}
{{- .Release.Name }}
{{- end }}
{{/*
ConfigMap name: <release-name>-scripts
*/}}
{{- define "jupyterlab.configMapName" -}}
{{- printf "%s-scripts" .Release.Name }}
{{- end }}
{{/*
Home volume PVC name: pvc-<release-name>-home
*/}}
{{- define "jupyterlab.homePvcName" -}}
{{- printf "pvc-%s-home" .Release.Name }}
{{- end }}
{{/*
Data volume PVC name: pvc-<release-name>-data
*/}}
{{- define "jupyterlab.dataPvcName" -}}
{{- printf "pvc-%s-data" .Release.Name }}
{{- end }}
{{/*
Resolved home directory path (mountPath or default /home/jovyan)
*/}}
{{- define "jupyterlab.homeDir" -}}
{{- .Values.homeVolume.mountPath | default "/home/jovyan" }}
{{- end }}
{{/*
Resolved data volume mount path: <homeDir>/<mountPath or "data">
*/}}
{{- define "jupyterlab.dataDir" -}}
{{- $home := include "jupyterlab.homeDir" . }}
{{- $sub := .Values.dataVolume.mountPath | default "data" }}
{{- printf "%s/%s" $home $sub }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "jupyterlab.labels" -}}
app: {{ include "jupyterlab.name" . }}
app.kubernetes.io/name: jupyterlab
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
{{- end }}
{{/*
Full image reference: [registry/]repository:tag
*/}}
{{- define "jupyterlab.image" -}}
{{- if .Values.image.registry }}
{{- printf "%s/%s:%s" .Values.image.registry .Values.image.repository .Values.image.tag }}
{{- else }}
{{- printf "%s:%s" .Values.image.repository .Values.image.tag }}
{{- end }}
{{- end }}
{{/*
JupyterLab startup command
*/}}
{{- define "jupyterlab.command" -}}
{{- $token := .Values.jupyterConfig.token }}
{{- $homeDir := include "jupyterlab.homeDir" . }}
- /bin/bash
- -c
- |
start.sh jupyter lab \
--core-mode \
{{- if $token }}
--ServerApp.password='sha256::{{ $token | sha256sum | trimSuffix " -" }}' \
--ServerApp.token='' \
{{- else }}
--ServerApp.token='' \
--ServerApp.password='' \
{{- end }}
--ServerApp.ip='0.0.0.0' \
--ServerApp.allow_origin='*' \
--IdentityProvider.cookie_options="max-age=28800" \
--ServerApp.disable_check_xsrf=True \
--ServerApp.quit_button=False \
--ServerApp.allow_root=False \
--ServerApp.terminals_enabled=True \
--ServerApp.root_dir={{ $homeDir }}
{{- end }}
@@ -0,0 +1,12 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "jupyterlab.configMapName" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "jupyterlab.labels" . | nindent 4 }}
data:
startup-script.sh: |
#!/bin/bash
apt-get update -y
python -m pip install --upgrade pip
@@ -0,0 +1,100 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "jupyterlab.name" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "jupyterlab.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicas }}
selector:
matchLabels:
app: {{ include "jupyterlab.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
{{- include "jupyterlab.labels" . | nindent 8 }}
spec:
securityContext:
runAsUser: 1000
fsGroup: 100
{{- if .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml .Values.imagePullSecrets | nindent 8 }}
{{- end }}
containers:
- name: jupyterlab
image: {{ include "jupyterlab.image" . | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command:
{{- include "jupyterlab.command" . | nindent 12 }}
ports:
- containerPort: 8888
protocol: TCP
env:
- name: NVIDIA_DRIVER_CAPABILITIES
value: "compute,utility"
resources:
limits:
cpu: {{ .Values.resources.limits.cpu | quote }}
memory: {{ .Values.resources.limits.memory | quote }}
{{- if .Values.resources.gpu }}
nvidia.com/gpu: {{ .Values.resources.gpu | quote }}
{{- end }}
requests:
cpu: {{ .Values.resources.requests.cpu | quote }}
memory: {{ .Values.resources.requests.memory | quote }}
{{- if .Values.resources.gpu }}
nvidia.com/gpu: {{ .Values.resources.gpu | quote }}
{{- end }}
securityContext:
runAsUser: 0
readinessProbe:
tcpSocket:
port: 8888
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 27
volumeMounts:
- name: localtime
mountPath: /etc/localtime
readOnly: true
- name: startup-script
mountPath: /usr/local/bin/start-notebook.d/startup-script.sh
subPath: startup-script.sh
{{- if .Values.homeVolume.enabled }}
- name: home-volume
mountPath: {{ include "jupyterlab.homeDir" . }}
{{- end }}
{{- if .Values.dataVolume.enabled }}
- name: data-volume
mountPath: {{ include "jupyterlab.dataDir" . }}
{{- end }}
{{- range .Values.groupVolumes }}
- name: gv-{{ .claimName }}
mountPath: {{ .mountPath }}
{{- end }}
volumes:
- name: localtime
hostPath:
path: /usr/share/zoneinfo/Asia/Seoul
- name: startup-script
configMap:
name: {{ include "jupyterlab.configMapName" . }}
defaultMode: 0755
{{- if .Values.homeVolume.enabled }}
- name: home-volume
persistentVolumeClaim:
claimName: {{ include "jupyterlab.homePvcName" . }}
{{- end }}
{{- if .Values.dataVolume.enabled }}
- name: data-volume
persistentVolumeClaim:
claimName: {{ include "jupyterlab.dataPvcName" . }}
{{- end }}
{{- range .Values.groupVolumes }}
- name: gv-{{ .claimName }}
persistentVolumeClaim:
claimName: {{ .claimName }}
{{- end }}
@@ -0,0 +1,42 @@
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "jupyterlab.name" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "jupyterlab.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- range $k, $v := . }}
{{ $k }}: {{ $v | quote }}
{{- end }}
{{- end }}
spec:
ingressClassName: {{ .Values.ingress.ingressClassName }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ . }}
pathType: Prefix
backend:
service:
name: {{ include "jupyterlab.name" $ }}
port:
number: 8888
{{- end }}
{{- end }}
{{- end }}
@@ -0,0 +1,43 @@
{{- if .Values.homeVolume.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "jupyterlab.homePvcName" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "jupyterlab.labels" . | nindent 4 }}
annotations:
# Uncomment below to retain the PVC even after helm uninstall.
# helm.sh/resource-policy: keep
spec:
accessModes:
- {{ .Values.homeVolume.accessMode }}
{{- if .Values.homeVolume.storageClassName }}
storageClassName: {{ .Values.homeVolume.storageClassName }}
{{- end }}
resources:
requests:
storage: {{ .Values.homeVolume.size }}
---
{{- end }}
{{- if .Values.dataVolume.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "jupyterlab.dataPvcName" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "jupyterlab.labels" . | nindent 4 }}
annotations:
# Uncomment below to retain the PVC even after helm uninstall.
# helm.sh/resource-policy: keep
spec:
accessModes:
- {{ .Values.dataVolume.accessMode }}
{{- if .Values.dataVolume.storageClassName }}
storageClassName: {{ .Values.dataVolume.storageClassName }}
{{- end }}
resources:
requests:
storage: {{ .Values.dataVolume.size }}
{{- end }}
@@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "jupyterlab.name" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "jupyterlab.labels" . | nindent 4 }}
spec:
type: ClusterIP
selector:
app: {{ include "jupyterlab.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
ports:
- name: http
port: 8888
targetPort: 8888
protocol: TCP
@@ -0,0 +1,77 @@
# JupyterLab Simple Helm Chart - Default values
# Deploys JupyterLab using pure Kubernetes resources without an Operator.
# JupyterLab Docker image
# Full image ref: <registry>/<repository>:<tag>
# Leave registry empty to use Docker Hub (default).
image:
registry: "quay.io"
repository: "jupyter/scipy-notebook"
tag: "latest"
pullPolicy: IfNotPresent
# Running state: 1=running, 0=stopped
replicas: 1
# Compute resources
resources:
limits:
cpu: "2000m"
memory: "4096Mi"
requests:
cpu: "500m"
memory: "1024Mi"
# Number of NVIDIA GPUs to allocate (e.g. "1"). Leave empty to disable.
# nvidia.com/gpu is set to the same value in both limits and requests (Kubernetes requirement).
gpu: ""
# JupyterLab process configuration
jupyterConfig:
# Access token (leave empty to disable token authentication)
token: ""
# External access Ingress configuration
ingress:
enabled: true
ingressClassName: "kong"
annotations:
cert-manager.io/cluster-issuer: "root-ca-issuer"
cert-manager.io/duration: "8760h"
cert-manager.io/renew-before: "720h"
konghq.com/https-redirect-status-code: "301"
konghq.com/protocols: "https"
hosts:
- host: "jupyter.example.com"
paths:
- /
tls:
- hosts:
- "jupyter.example.com"
secretName: "jupyter-tls-secret"
# Home directory volume: PVC mounted at the user's home directory.
# mountPath: mount path inside the container (defaults to /home/jovyan if left empty)
homeVolume:
enabled: false
mountPath: ""
size: "5Gi"
storageClassName: ""
accessMode: "ReadWriteOnce"
# Data volume: PVC mounted at <homeDir>/<mountPath>.
# mountPath: subdirectory name under the home directory (defaults to "data" if left empty)
dataVolume:
enabled: false
mountPath: ""
size: "5Gi"
storageClassName: ""
accessMode: "ReadWriteOnce"
# Shared group volume mounts (optional)
# groupVolumes:
# - claimName: "pvc-shared-data"
# mountPath: "/group_data"
groupVolumes: []
# imagePullSecrets for private registries
imagePullSecrets: []