ML Plugin Train — Dagster UI 임베드 (#1508 / RFC #1476 결정 B')
ml_plugin 학습 트리거 운영자 가이드. RFC #1476 결정 = 옵션 B' (Dagster UI iframe 내장) — GenD UI 안에서 Dagster Playground 그대로 사용.
본 가이드 (ml-plugin-train.md) = 운영자 UI 시나리오 — GenD UI 안 iframe 로 클릭 + Playground 직접 사용. 이 페이지부터 보세요.
자동화 / CI / ETL 통합 = ml-plugin-train-trigger.md — POST /api/v1/ml-plugins/{id}/train REST API 호출, 3-layer allowlist 보안, GraphQL launchRun 내부 구조.
운영자 절차 — GenD UI 안 Dagster 임베드
1. ML Plugin 선택
/admin/ml-plugins → 등록된 plugin 의 우측 액션 영역 → 👁 (detail) 아이콘 클릭 → detail sheet 오픈.

운영자 사이클 #1531 prod 캡쳐 (commit 7208a631). demo_credit_risk_plugin 1개 등록 + Capability badge (train / predict) + Provider Allowlist verified 표시.
2. Detail Sheet — Plugin 정보 + Train (Dagster) section
Detail Sheet 가 우측에서 슬라이드 인 → 상단에 plugin 정보 (Capability / Config / Serving Runtime / 메타데이터) + 하단에 "Train (Dagster)" section.

스크롤하면 Train (Dagster) section 안의 DagsterRunEmbed iframe (/dagster/locations/ml_plugin_train_repo/jobs/ml_plugin_train_job/playground) 노출:

위 캡쳐의 iframe 안 화면 — oauth2-proxy 의 "Sign in with Keycloak OIDC" 가 보이는 이유는 password-grant 토큰 주입 (E2E 캡쳐 path) 이 Dagster 의 oauth2-proxy 세션과 분리되기 때문. 실 운영자가 GenD UI 로 로그인하면 cookie 가 자동 공유되어 iframe 안에서 Dagster Playground 가 그대로 보임 — 별도 클릭 / 로그인 불필요.
3. Launch Run
Playground 안에서 직접:
- Run config editor — 다음 YAML 입력 (또는 minimum):
ops:ml_plugin_train:config:plugin_id: "<UUID>" # plugin row idplugin_name: "demo_credit_risk_plugin"provider_class: "gend_api.services.ml_plugins.sklearn_baseline.SklearnBaselineProvider"plugin_config: {task: "classification", dataset_uri: "demo://"}
- Launch Run 버튼 → run id 즉시 발급
- 같은 iframe 안에서 step log / event log / asset materialization 모두 추적
4. 결과 확인
- MLflow registry:
mlflow.gend.svc.cluster.local:5000/#/models/<plugin_name>(별도 탭) - KServe InferenceService:
kubectl --context aks-genos-prod -n gend get inferenceservice(운영자 ops) - Audit log:
gend.auditchannel —ml_plugin_train_triggeredevent
자동화 (API)
GenD UI 가 아닌 외부 시스템 / 스크립트 trigger:
TOKEN=$(curl -s -X POST "https://gend.genon.ai/auth/realms/gend/protocol/openid-connect/token" \
-d "grant_type=password" -d "client_id=gend-ui" \
-d "username=$ADMIN_USER" -d "password=$ADMIN_PASS" | jq -r .access_token)
curl -X POST "https://gend.genon.ai/api/v1/ml-plugins/$PLUGIN_ID/train" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{}'
# → 202 + {"run_id":"<dagster_run_id>","plugin_id":"...","status":"queued"}
RFC #1476 옵션 B' 의 근거
| A (UI 책무) | B' (iframe embed) ← 선택 | |
|---|---|---|
| 운영자 진입점 | GenD UI 안 액션 버튼 | GenD UI 안 iframe (같은 진입점) |
| step log / re-execute | UI 가 wrap 구현 | Dagster UI 그대로 |
| Dagster API 변경 영향 | UI fix 필요 | 0 (iframe 안 자동 반영) |
| 운영자 학습곡선 | GenD-only | 기존 Dagster 사용자 호환 + GenD-only 사용자도 같은 화면 |
| 구현 비용 | 큰 (RunProgressDialog 신규) | 작은 (50-line iframe wrapper) |
보안
iframe sandbox:allow-same-origin allow-scripts allow-forms allow-popupsallow-downloads/allow-top-navigation거부 — 임베드된 콘텐츠가 부모 페이지 탈취 불가
- 같은
gend.genon.ai도메인 →X-Frame-Options: SAMEORIGIN자연 호환 - oauth2-proxy 가 같은 Keycloak 세션 사용 → silent SSO
- CSP
frame-src 'self'명시 (ingress nginx config)
트러블슈팅
| 증상 | 원인 | 해결 |
|---|---|---|
| iframe 빈 화면 + console "Refused to display ... in a frame" | X-Frame-Options: DENY 헤더 | Dagster ingress 의 proxy_hide_header X-Frame-Options; 또는 SAMEORIGIN 으로 교체 |
| iframe 안 "Login required" | oauth2-proxy 세션 만료 | 부모 페이지 새로고침 → 자동 재인증 |
| Launch Run 후 step FAILURE | (a) Dagster image stale (b) ml_plugin_train_repo workspace.yaml 미반영 | 본 PR 의 cross-reference #1430 audit, PR #1431 |
| iframe 안 navigation 후 GenD UI back 버튼 부조 | 별도 navigation context | 의도된 설계 — iframe 안 history 는 부모와 분리 |
회귀 가드
ui/src/components/admin/MLPlugins/DagsterRunEmbed.test.tsx(6 vitest 케이스):- default src / custom job/location / view='runs' / sandbox attribute / 새 탭 링크 / height prop
ui/tests/ml-plugins-train-embed-e2e.spec.ts(3 Playwright):- detail sheet → Train 탭 → iframe 렌더 + src 검증
- sandbox attribute strict
/dagster/ingress 200/302/401 응답
관련
- RFC #1476 (PR #1493, commit
92e8c8e9) - 본 PR (구현 follow-up) #1508
- ML Plugin registry: ./ml-plugin-registry.md
- KServe serving (별개): ../serving/kserve-inference.md