본문으로 건너뛰기

ADR-0029: 코드스페이스 = JupyterHub 제품화 계층 (GenOS 스택 비이식)

  • 상태: 승인
  • 날짜: 2026-07-24
  • 관련: Epic #2614 (GenD 코드스페이스), Epic #1081 (Notebook ↔ Git), GenOS codespace (container-services/codespace)

배경

GenD 는 GenOS 없이 단독 판매되는 고객이 존재하므로, 개발환경(코드스페이스)은 GenD 자체 완결이어야 한다. GenOS 에는 제품화된 코드스페이스(사용자별 컨테이너, VSCode+Jupyter 동시, GPU/공유볼륨 옵션, 서빙 자동연결)가 있어 "이식"이 자연스러운 선택지로 보였다.

GenOS develop(2026-07-23) 3-렌즈 심층 조사 결과, GenOS 코드스페이스 컨트롤플레인은 다음에 강결합되어 있다: Istio(VirtualService + CUSTOM ext-authz) · admin-api 세션 JWT · IAM policy statement · orchestrator(k8s client 직접 호출) · RabbitMQ 로그 파이프라인 · DB 마스터 4종(docker_image/instance_type/quota_gpu/quota_volume). 반면 GenD 는 이미 prod 에서 z2jh(JupyterHub) 스택을 운영 중이며 — Keycloak OIDC, per-user PVC, idle culling(GenOS 에는 없음), Hub REST API 프록시(routers/notebook.py), multi-arch 이미지 CI 를 보유한다.

결정적으로, GenOS 코드스페이스의 본질인 "한 팟에서 JupyterLab + VS Code 동시 제공" 모델은 GenD 의 기존 gend-singleuser-codeserver 이미지(jupyterhub-singleuser PID1 + jupyter-server-proxy 가 code-server 를 서브프로세스로 구동)가 이미 동일 구조로 구현하고 있었다.

결정

GenOS 코드스페이스 스택을 이식하지 않는다. 코드스페이스는 기존 JupyterHub(z2jh) 위의 제품화 계층으로 구축한다.

  1. 컨트롤플레인 = z2jh 유지: KubeSpawner(오케스트레이션), configurable-http-proxy (라우팅), GenericOAuthenticator+Keycloak(인증), cull(1h idle/8h max — 수명 정책).
  2. 제품화 계층: routers/notebook.py 소폭 확장(profile slug 스폰 + lab/vscode URL)
    • GenD UI "코드스페이스" 1급 화면. 프로필(slug)은 helm values profileList 와 gend-api settings 의 문자열 계약이며 pytest 가 양쪽 파일을 파싱해 드리프트를 차단한다.
  3. 선별 이식: 단일 팟 멀티 IDE 모델(기본 프로필로 승격), 인스턴스 타입 선택 UX, cline-provision.sh+서빙 자동연결 개념(컨테이너 계약 = env 3개 — M3 애드온).
  4. 명시적 비이식: admin-api/orchestrator 2단 스택, Istio ext-authz(신뢰 헤더 모델 — GenD 워크스페이스 격리 기준보다 약함), user_proxy(공유 코드스페이스 전제 — GenD 는 per-user 팟), git-wrapper(GenD 는 #1081 Gitea 통합이 우월), log_watcher(fluent-bit 기존재), SSH NodePort, DB 마스터 4종(helm values GitOps 가 정본), 코드스페이스 공유.

함께 확정한 세부 결정

  • named server 미사용: IDE 동시성은 단일 팟이 해결. RWO(Azure Disk) PVC 는 다중 팟 동시 마운트가 불가하므로 named server 는 RWX 전환 시 재평가.
  • 인증 부트스트랩 정본 = gend init(device flow, M2): auth_state → env 자동 시드는 ① jupyterhub 클라이언트에 gend-api audience mapper 부재 ② API-생성 사용자의 auth_state 부재(순서 역전) ③ 토큰 수명 30분 — 3중 파손으로 폐기. postStart 자동 시드는 hub-attested 패턴(별도 적대 리뷰)으로 후속 검토.
  • URL 토큰 자동로그인 폐기: JupyterHub 5.x 는 ?token= 페이지 인증이 기본 비활성(allow_token_in_url=False) — 기존 #455 메커니즘은 무동작이었고 실제 인증은 Keycloak SSO 세션. UI 열기는 SSO 세션 기반으로 정리.
  • 리소스: guarantee 는 전 프로필 0.25CPU/512M 유지(노드 requests 86~97% 기예약 — 상향 시 FailedScheduling), limit 만 차등(1/2/4 CPU).

결과

  • 단독 판매 고객도 GenD 매니페스트만으로 완결된 코드스페이스를 갖는다 (GenOS 의존 0).
  • Istio·orchestrator·마스터 테이블 등 플랫폼 전환급 비용 회피. GenOS 에 없는 culling·SSO 자동로그인은 그대로 유지.
  • infra/code-server/(단일 공유 인스턴스·무인증 초기 잔재)는 폐기 — JupyterHub 코드스페이스 프로필이 정본.
  • GPU 프로필·Cline/LLM 연결·공유 팀 볼륨은 M3 옵션(각각 별도 go/no-go)으로 분리.