Files
service-catalog/manifests/helm/mlflow/1.9.0
2026-04-24 09:59:57 +09:00
..
2026-04-22 17:08:02 +09:00
2026-04-22 17:08:02 +09:00
2026-04-22 17:08:02 +09:00
2026-04-22 17:08:02 +09:00
2026-04-22 17:08:02 +09:00
2026-04-22 17:08:02 +09:00
2026-04-22 17:08:02 +09:00
2026-04-24 09:59:57 +09:00
2026-04-22 17:08:02 +09:00
2026-04-22 17:08:02 +09:00

MLflow 배포 (OIDC Auth)

MLflow 3.11.1 + mlflow-oidc-auth를 Keycloak과 연동하여 배포하는 가이드이다. 커스텀 이미지 paasup/mlflow:v3.11.1-oidc에 OIDC 플러그인이 포함되어 있다.


1. 사전 준비

1.1 Keycloak 설정

Client 생성

  • Realm: paasup, Client ID: mlflow, Protocol: openid-connect
  • Access Type: confidential
  • Valid Redirect URIs: https://mlflow.example.org/*
  • Web Origins: https://mlflow.example.org

Groups Mapper 추가 (userinfo 포함 필수)

Client → Mappers → Create:

항목
Mapper type Group Membership
Token Claim Name groups
Full group path false
Add to ID token true
Add to access token true
Add to userinfo true ← 반드시 true

Groups 생성

  • mlflow — 일반 사용자 접근 허용 그룹
  • mlflow-admin — 관리자 그룹

사용자를 해당 그룹에 할당한다.


1.2 Keycloak CA 인증서 ConfigMap 생성

Keycloak이 사설 CA 인증서를 사용하는 경우 필수이다.

# Keycloak TLS secret에서 CA 인증서 추출
kubectl get secret keycloak.example.org-tls -n platform \
  -o jsonpath='{.data.ca\.crt}' | base64 -d > /tmp/keycloak-ca.crt

# ConfigMap 생성
kubectl create configmap keycloak-ca-cert -n mlflow \
  --from-file=ca.crt=/tmp/keycloak-ca.crt

1.3 OIDC Secret 생성

SECRET_KEY는 uvicorn 멀티워커 환경에서 세션 공유를 위해 반드시 포함해야 한다.

# Fernet key 생성 (webhook secret 암호화용)
FERNET_KEY=$(python3 -c "import os,base64; print(base64.urlsafe_b64encode(os.urandom(32)).decode())")

# Session key 생성 (멀티워커 세션 공유용)
SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")

kubectl create secret generic mlflow-oidc-secret -n mlflow \
  --from-literal=OIDC_CLIENT_SECRET="<keycloak-client-secret>" \
  --from-literal=MLFLOW_WEBHOOK_SECRET_ENCRYPTION_KEY="$FERNET_KEY" \
  --from-literal=SECRET_KEY="$SECRET_KEY"

Keycloak Client Secret은 Keycloak Admin Console → Client → Credentials 탭에서 확인한다.


2. 배포 방법

git clone https://github.com/paasup/dip-catalog.git
cd dip-catalog

# 신규 설치
helm install mlflow manifests/helm/mlflow/1.9.0/ \
  -f manifests/helm/mlflow/1.9.0/custom-values.yaml \
  -n mlflow --create-namespace

# 업그레이드
helm upgrade mlflow manifests/helm/mlflow/1.9.0/ \
  -f manifests/helm/mlflow/1.9.0/custom-values.yaml \
  -n mlflow

3. custom-values.yaml 설명

3.1 이미지 설정

OIDC 플러그인이 포함된 커스텀 이미지를 사용한다.

image:
  repository: paasup/mlflow
  tag: "v3.11.1-oidc"

initImages:
  mlflowDbMigration:
    repository: paasup/mlflow
    tag: "v3.11.1-oidc"

3.2 OIDC 환경변수 설정

extraEnvVars:
  SSL_CERT_FILE: "/etc/ssl/certs/custom-ca.crt"
  OIDC_CLIENT_ID: "mlflow"
  OIDC_DISCOVERY_URL: "https://keycloak.example.org/realms/paasup/.well-known/openid-configuration"
  OIDC_REDIRECT_URI: "https://mlflow.example.org/callback"
  OIDC_SCOPE: "openid email profile"
  OIDC_GROUPS_ATTRIBUTE: "groups"
  OIDC_GROUP_NAME: "mlflow"
  OIDC_ADMIN_GROUP_NAME: "mlflow-admin"
  OIDC_USERS_DB_URI: "postgresql://mlflow:mlflow1234@mlflow-postgresql:5432/mlflow"
  DEFAULT_MLFLOW_PERMISSION: "READ"
  MLFLOW_ENABLE_WORKSPACES: "false"
  AUTOMATIC_LOGIN_REDIRECT: "true"
  OIDC_ALEMBIC_VERSION_TABLE: "mlflow_oidc_alembic_version"

3.3 OIDC App 활성화

extraArgs:
  appName: "oidc-auth"              # OIDC 플러그인 활성화
  uvicornOpts: "--timeout-keep-alive 600"
  allowedHosts: "mlflow.example.org"

log:
  enabled: false    # uvicornOpts 사용 시 반드시 false (gunicorn/uvicorn 충돌 방지)

auth:
  enabled: false    # mlflow-oidc-auth가 자체 인증 처리

3.4 Secret 참조

extraSecretNamesForEnvFrom:
  - mlflow-oidc-secret    # OIDC_CLIENT_SECRET, SECRET_KEY, MLFLOW_WEBHOOK_SECRET_ENCRYPTION_KEY 포함

3.5 CA 인증서 볼륨 마운트

extraVolumes:
  - name: keycloak-ca-cert
    configMap:
      name: keycloak-ca-cert

extraVolumeMounts:
  - name: keycloak-ca-cert
    mountPath: /etc/ssl/certs/custom-ca.crt
    subPath: ca.crt
    readOnly: true

3.6 OIDC Auth Middleware 패치

mlflow-oidc-auth 플러그인의 auth_middleware.py를 차트에 포함된 버전으로 교체한다. 워크스페이스 지원(x-mlflow-workspace 헤더 처리) 등 업스트림 수정 사항을 반영한다.

oidcAuthPatch:
  enabled: true
  mountPath: "/usr/local/lib/python3.11/site-packages/mlflow_oidc_auth/middleware/auth_middleware.py"

파일 소스: files/auth_middleware.py

Python 버전 확인: 컨테이너 이미지의 Python 버전이 다를 경우 mountPath를 수정한다.

kubectl exec -n mlflow <pod> -- python -c \
  "import mlflow_oidc_auth.middleware.auth_middleware as m; print(m.__file__)"

3.7 Ingress 설정

ingress:
  enabled: true
  className: "kong"
  annotations:
    cert-manager.io/cluster-issuer: "selfsigned-issuer"
    cert-manager.io/duration: 8760h
    cert-manager.io/renew-before: 720h
  hosts:
    - host: mlflow.example.org
      paths:
        - path: /
          pathType: ImplementationSpecific
  tls:
    - secretName: mlflow-tls-secret
      hosts:
        - mlflow.example.org

mlflow.example.org를 실제 도메인으로 변경한다.


3.8 PostgreSQL 설정

내장 PostgreSQL을 사용한다.

postgresql:
  enabled: true
  auth:
    username: mlflow
    password: mlflow1234    # 변경 권장
    database: mlflow
  image:
    repository: bitnamilegacy/postgresql
  primary:
    persistence:
      enabled: true

OIDC_USERS_DB_URI도 동일한 접속 정보를 사용한다.

extraEnvVars:
  OIDC_USERS_DB_URI: "postgresql://mlflow:mlflow1234@mlflow-postgresql:5432/mlflow"

3.9 S3 (MinIO) 설정

artifactRoot:
  proxiedArtifactStorage: true
  defaultArtifactsDestination: "s3://mlflow/artifacts"
  s3:
    enabled: true
    bucket: mlflow
    path: artifacts
    awsAccessKeyId: "adminuser"       # MinIO access key
    awsSecretAccessKey: "adminuser"   # MinIO secret key

extraEnvVars:
  MLFLOW_S3_ENDPOINT_URL: "http://minio.minio.svc.cluster.local:9000"
  MLFLOW_S3_IGNORE_TLS: "true"

외부 MinIO 사용 시 MLFLOW_S3_ENDPOINT_URL을 해당 엔드포인트로 변경한다.


4. 배포 검증

  1. https://mlflow.example.org 접속 → Keycloak 로그인 페이지로 자동 리다이렉트
  2. mlflow 그룹 사용자로 로그인 → MLflow UI 정상 진입 확인
  3. mlflow-admin 그룹 사용자로 로그인 → 관리자 메뉴 접근 확인
  4. 미가입 사용자 로그인 → 접근 거부 확인