Docker·Kubernetes·MLflow로 짜는 MLOps 배포 파이프라인 — 카나리 배포부터 자동 롤백까지
MLflow로 실험·모델을 추적하고 Docker·Kubernetes로 카나리 배포·자동 롤백까지 이어지는 MLOps 파이프라인 구조와 코드 예시를 정리한다.
2026-08-12 · 최초 발행 2024-04-29
데이터·모델·코드가 빠르게 변하는 환경에서 재현성·확장성·안정성을 동시에 확보하려면 모델 배포를 표준화(Docker, Kubernetes)하고 실험·등록·배포를 자동화(MLflow)하는 운영 체계가 필요하다. MLOps(Machine Learning Operations)는 데이터 수집부터 학습·검증·배포·모니터링·재학습까지 전 과정을 DevOps 원칙으로 자동화·표준화하는 운영 프레임워크로, 소스·데이터·모델 버전관리, 실험 추적, 모델 레지스트리, CI/CD/CT, 컨테이너 배포, 관측·경보, 거버넌스·승인 절차를 아우른다.
이 체계에서 세 도구는 각기 다른 역할을 맡는다. Docker는 실행 환경 불변성과 이식성을 확보하고, Kubernetes는 확장·자가치유·롤아웃/롤백을 오케스트레이션하며, MLflow는 실험 추적(Tracking), 아티팩트·모델 관리(Artifacts/Models), 모델 레지스트리(Registry), 서빙 연계를 담당한다.
각 도구가 맡는 역할
Docker 컨테이너는 종속성을 캡슐화해 환경 편차를 제거하고 이미지를 불변 아티팩트로 관리한다. 빌드-런타임을 분리해 공격면을 축소하는 distroless 이미지가 권장되며, 이미지 서명·검증(cosign), 취약점 스캔(Trivy), 최소 권한 런타임(Non-root) 적용이 거버넌스 측면에서 중요하다.
Kubernetes는 수평 확장(HPA)과 롤링 업데이트·블루/그린·카나리 배포 전략을 지원하고, Readiness/Liveness 프로브로 장애 파드를 자가치유한다. 리소스 QoS(requests/limits), PodDisruptionBudget, GPU 스케줄링(Node selector, tolerations)까지 다루며 네트워크 정책·시크릿 관리도 함께 담당한다.
MLflow는 파라미터·메트릭·아티팩트·모델 시그니처를 실험/런 단위로 자동 기록하는 Tracking 기능과, Staging→Production 단계 전환·승인 워크플로·버전 아카이빙을 지원하는 Model Registry로 나뉜다. 모델 URI를 일원화해 서빙 경로를 안정화하는 역할도 한다.
배포 옵션을 단독 Docker와 클러스터 Kubernetes로 비교하면 다음과 같다.
| 항목 | Docker(단독) | Kubernetes(클러스터) |
|---|---|---|
| 성능 | 단일 노드 자원 극대화 용이 | 노드 풀 기반 수평 확장 용이 |
| 확장성 | 수동 스케일링 한계 | 자동 스케일링(HPA/VPA) 지원 |
| 일관성 | 호스트 의존성 영향 가능 | 선언적 상태관리로 일관성 확보 |
| 안정성 | 프로세스 장애 시 수동 복구 | 자가치유, 롤아웃/롤백 자동화 |
| 운영 편의 | 초기 진입 용이 | 초기 복잡도 높으나 장기 운영 유리 |
파이프라인 자동화(CI/CD/CT)는 Git 기반 트리거로 PR 빌드→테스트→이미지 빌드/스캔→레지스트리 푸시→배포 매니페스트 업데이트(GitOps)까지 이어진다. CT(Continuous Training)는 데이터 드리프트 신호가 감지되면 학습 잡을 스케줄링하고 검증 후 Registry에 등록, 카나리 배포까지 자동화하는 개념이며, 스테이지 전환 승인·락으로 동시성 충돌을 방지한다. 관측성 측면에서는 예측 지연, 오류율, 입력 분포/드리프트, 성능(정확도/AUC)을 모델·서비스 이중으로 모니터링하고, SLO 위반 시 카나리를 중지하거나 자동 롤백하며 피처·레이블 데이터 품질 체크와 스키마 유효성 검증도 함께 수행한다.
표준 배포 절차와 파이프라인 흐름
표준 배포 절차는 Git 커밋(SHA), 데이터 스냅샷(버전/해시), 환경 스펙(conda.yaml/requirements.txt)을 입력으로 받아 학습 파이프라인을 실행하고, MLflow Tracking/Artifacts에 기록한 뒤 검증 게이트(성능/스키마/바이어스)를 통과하면 Registry에 등록하고 Staging으로 전환한다. 이후 컨테이너 이미지를 빌드·서명하고 Kubernetes 카나리 배포로 넘어가며, 최종 출력은 버전이 고정된 Production 스테이지 모델과 안정화된 배포(Deployment/Service), 관측 대시보드·경보 룰이다.
에러 처리를 포함한 전체 흐름은 다음과 같다.
검증 게이트를 통과하지 못하거나 Staging 승인이 거부되면 파이프라인이 중단되고 알림이 발송된다는 점, 카나리 배포 중 지연·오류율·드리프트 위반이 감지되면 자동 롤백된다는 점이 이 흐름의 핵심이다.
최소 구현 예시
전제조건은 Python 3.10, mlflow 2.x, scikit-learn, Docker 24+, Kubernetes 1.27+(최신 정보 확인 필요), kubectl 구성 완료다.
학습과 등록은 MLflow Tracking/Registry로 처리한다.
# train_register.py
import mlflow, mlflow.sklearn
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
mlflow.set_tracking_uri("http://mlflow-tracking:5000") # 또는 file:/.../mlruns
mlflow.set_experiment("iris-rf")
X, y = load_iris(return_X_y=True)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.2, random_state=42)
with mlflow.start_run() as run:
model = RandomForestClassifier(n_estimators=200, random_state=42).fit(Xtr, ytr)
acc = model.score(Xte, yte)
mlflow.log_metric("accuracy", acc)
mlflow.sklearn.log_model(model, "model", registered_model_name="iris_rf")
# 새 버전이 Registry에 생성됨
print("Accuracy:", acc)
모델 서빙 컨테이너는 Dockerfile과 FastAPI로 구성한다.
# Dockerfile
FROM python:3.10-slim
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
RUN pip install --no-cache-dir fastapi uvicorn mlflow scikit-learn
COPY app.py /app/app.py
# 런타임 시 MLFLOW_MODEL_URI 전달 예: models:/iris_rf/Production
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]
# app.py
import os, mlflow.pyfunc
from fastapi import FastAPI, HTTPException
import numpy as np
app = FastAPI()
model_uri = os.getenv("MLFLOW_MODEL_URI", "")
if not model_uri:
raise RuntimeError("MLFLOW_MODEL_URI not set")
model = mlflow.pyfunc.load_model(model_uri)
@app.post("/predict")
def predict(payload: dict):
try:
X = np.array(payload["instances"])
preds = model.predict(X).tolist()
return {"predictions": preds}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
Kubernetes 배포 매니페스트는 카나리용 Replica 분리가 가능한 구조로 작성한다.
# deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: iris-api
spec:
replicas: 3
selector: { matchLabels: { app: iris-api } }
template:
metadata: { labels: { app: iris-api } }
spec:
containers:
- name: api
image: your-registry/iris-api:1.0.0
env:
- name: MLFLOW_MODEL_URI
value: "models:/iris_rf/Production"
ports: [{ containerPort: 8080 }]
resources:
requests: { cpu: "200m", memory: "256Mi" }
limits: { cpu: "1", memory: "512Mi" }
readinessProbe:
httpGet: { path: /predict, port: 8080 }
initialDelaySeconds: 10
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata: { name: iris-api }
spec:
selector: { app: iris-api }
ports: [{ port: 80, targetPort: 8080 }]
type: ClusterIP
운영 팁으로는 kustomize/Helm으로 환경별 오버레이(prod/stage/dev)를 구성하고 커밋 SHA로 이미지를 태깅하는 GitOps, 이미지 서명 검증(admission controller)과 CSI/KMS 암호화·네트워크 정책 기반 egress 제한으로 보안을 강화하는 방법, 요청 타임아웃/재시도·서킷브레이커(서비스 메시)·지표 기반 카나리(Argo Rollouts/Flagger)로 신뢰성을 높이는 방법이 있다.
기대 효과와 도입 순서
자동화된 MLOps 파이프라인을 도입하면 여러 지표에서 개선을 기대할 수 있다. 배포 리드타임은 수작업 대비 7090% 감소해 주 단위 작업이 시간 단위로 줄어들고, 실패 시 MTTR은 자동 롤백을 통해 50% 이상 단축된다. 실험·아티팩트·레지스트리를 일관되게 버전관리하면 재현성과 감사 추적이 향상돼 감사 대응 시간이 60% 이상 단축되고, 자동 스케일링과 리소스 상한 설정으로 피크 외 시간 자원을 3060% 절감할 수 있다. 드리프트·스키마 검증과 승인 게이트를 갖추면 성능 급락 사고율도 50% 이상 감소한다.
Docker로 불변 실행 환경을 확보하고 Kubernetes로 확장·가용성을 보장하며 MLflow로 실험·모델 생애주기를 표준화하는 것이 이 구조의 핵심이다. 여기에 CI/CD/CT 파이프라인과 관측 체계를 동시에 구축하면 운영 리스크를 줄이고 컴플라이언스 대응력도 강화된다. 처음부터 전체 체계를 갖추기보다는 단일 모델·단일 파이프라인으로 시작한 뒤, 지표 기반 카나리와 GitOps를 순차적으로 도입해 점진적으로 확장하는 방식이 현실적이다.