# 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` | 전체 이미지 참조. `repository`에 `:`가 있으면 `tag` 무시 |
| `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`, `dshm` (항상), `home-volume`, `data-volume`, `groupVolumes` (조건부)
- `dshm`: RAM 기반 tmpfs를 `/dev/shm`에 마운트. PyTorch/NumPy 멀티프로세싱 시 기본 64MB 제한 해제

### `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과 별도로 관리합니다.
