문서 구성: 아키텍처 다이어그램(mermaid), 각 구성요소 설명, 운영/모니터링 체크리스트, 그리고 GitHub Actions 기반의 ML용 CI/CD YAML 템플릿
flowchart LR
subgraph Ingestion
A[External Data Sources\n(Streaming, DB, Files, Events)] -->|Ingest| B[Azure Data Factory / Event Hubs / IoT Hub]
end
B --> C[ADLS Gen2 (Raw Zone)]
C --> D[Data Versioning\n(LakeFS / DVC)]
D --> E[Data Validation\n(Great Expectations / whylogs)]
E --> F[Feature Engineering Notebook/Pipelines\n(Azure Databricks / Azure ML Data Prep)]
F --> G[Feature Store / Parquet Store]
G --> H[Training Compute\n(Azure ML Compute / Compute Cluster)]
H --> I[Experiment Tracking & Model Registry\n(Azure ML Registry / MLflow)]
I --> J[Model Artifact (registry + metadata)]
J --> K[CI/CD Pipeline (GitHub Actions / Azure DevOps)]
K --> L[Image Build & ACR]\n K --> M[Validation Tests & Approval]
L --> N[Deployment Targets]
subgraph Deployment
N --> O[Managed Online Endpoint (Azure ML Endpoints)]
N --> P[Batch Endpoint (Azure ML Batch/Databricks)]
N --> Q[Edge / IoT Devices]
end
O --> R[Monitoring: Azure Monitor / Application Insights + Model Monitoring (Evidently / Fiddler / Arize)]
R --> S[Alerts & Retrain Trigger]
S --> H
style Ingestion fill:#f8f9fa,stroke:#333,stroke-width:1px
이 템플릿은 (A) 코드 테스트/데이터 검사/모델 평가(Metric gate)로 구성된 CI, (B) 모델 등록·이미지 빌드·배포를 수행하는 CD 파이프라인으로 나뉩니다. 필요에 따라
train단계를 오프라인 학습(온프레미스)으로 바꾸거나, 학습은 주기적 트리거로 분리하세요.
name: mlops-azureml-ci-cd
on:
push:
branches: [ main ]
workflow_dispatch: {}
env:
AZURE_SUBSCRIPTION: ${{ secrets.AZURE_SUBSCRIPTION }}
AZURE_RESOURCE_GROUP: my-ml-rg
AZURE_WORKSPACE: my-ml-workspace
LOCATION: eastus
ACR_NAME: myacrname
MODEL_NAME: my-model
ENDPOINT_NAME: my-model-endpoint
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run unit tests
run: |
pytest tests/unit -q
data-and-smoke-tests:
needs: unit-tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install validation tools
run: |
pip install great_expectations whylogs
- name: Run data validation
run: |
# 예: 스테이징 데이터에 대한 스키마 검사 또는 샘플 검사
python infra/data_validation/run_data_checks.py --source staging
train-and-register:
needs: data-and-smoke-tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Install Azure ML CLI v2
run: |
python -m pip install --upgrade pip
pip install azure-cli
az extension add -n ml --yes || true
- name: Submit training job to Azure ML
id: submit_train
run: |
# 학습은 Azure ML job으로 제출
az ml job create --file jobs/train_job.yml --no-wait
- name: Wait for training completion (poll)
run: |
# 간단한 polling 예시(프로덕션에서는 더 견고한 로직을 권장)
JOB_ID=$(az ml job list --query "[?name=='train_job'].name | [0]" -o tsv)
echo "Job: $JOB_ID"
az ml job wait --name $JOB_ID --timeout 36000
- name: Register model
run: |
az ml model create --name ${{ env.MODEL_NAME }} --path outputs/model.pkl --asset-path outputs/model.pkl
- name: Fetch model metadata
run: az ml model show --name ${{ env.MODEL_NAME }} -o table
evaluate-and-gate:
needs: train-and-register
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Download registered model for evaluation
run: |
az ml model download --name ${{ env.MODEL_NAME }} --path downloaded_model
- name: Run evaluation script
run: |
python infra/eval/evaluate.py downloaded_model --metrics-file metrics.json
- name: Check metric gate
id: check_metrics
run: |
python infra/eval/check_gate.py metrics.json --min-auc 0.78
build-and-push-image:
needs: evaluate-and-gate
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Login to ACR
run: |
az acr login --name ${{ env.ACR_NAME }}
- name: Build container image
run: |
IMAGE_TAG=${{ github.sha }}
az acr build --registry ${{ env.ACR_NAME }} --image ${ACR_NAME}.azurecr.io/${{ env.MODEL_NAME }}:${IMAGE_TAG} .
deploy:
needs: build-and-push-image
runs-on: ubuntu-latest
steps:
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Create or update endpoint
run: |
IMAGE_TAG=${{ github.sha }}
az ml online-endpoint create --name ${{ env.ENDPOINT_NAME }} --resource-group ${{ env.AZURE_RESOURCE_GROUP }} --workspace-name ${{ env.AZURE_WORKSPACE }} || true
- name: Create deployment
run: |
az ml online-deployment create \
--name blue-deployment \
--endpoint ${{ env.ENDPOINT_NAME }} \
--resource-group ${{ env.AZURE_RESOURCE_GROUP }} \
--workspace-name ${{ env.AZURE_WORKSPACE }} \
--model ${{ env.MODEL_NAME }}:1 \
--image ${ACR_NAME}.azurecr.io/${{ env.MODEL_NAME }}:${{ github.sha }} \
--instance-type Standard_DS3_v2 \
--instance-count 1
- name: Traffic shift (Canary -> full)
run: |
# 예: 10% 트래픽을 blue에 주기
az ml online-endpoint update --name ${{ env.ENDPOINT_NAME }} --traffic "{\"blue-deployment\":10, \"green-deployment\":90}"
monitor-alerts:
needs: deploy
runs-on: ubuntu-latest
steps:
- name: Create monitor resources (if not exists)
run: |
# Application Insights / Monitor 알람 셋업 스크립트 또는 IaC 실행
echo "Monitoring and alert resources should be configured separately via IaC or ARM/Bicep"
사용법 노트
secrets.AZURE_CREDENTIALS는 OIDC 또는 서비스 프린시플 JSON을 사용jobs/train-and-register에서jobs/train_job.yml은 Azure ML Job 스펙으로 교체- 모델 평가/게이트 로직은 도메인별 지표(AUC, RMSE, F1 등)에 따라 조정
- 트래픽 쉐어 로직은 엔드포인트/배포 이름에 맞춰 수정
좋아, CI/CD를 “MLOps 관점”에서 정리해주면 AI·데이터 사이언스 파이프라인이 단번에 구조화된다.
일반 소프트웨어와 달리 ML 모델은 코드 외에 데이터·실험·모델 버전·성능 모니터링이 중요하기 때문이야.
아래에서 ML에 특화된 CI → CD → CM(Continuous Monitoring) 흐름으로 체계적으로 설명할게.
ML에서 CI는 코드뿐 아니라 데이터, 모델 구성 요소 전체를 안정적으로 통합하는 과정이야.
일반 소프트웨어 CI는 코드 중심이지만
ML CI는 4가지를 다룬다:
코드
데이터
모델 설정(하이퍼파라미터)
학습/검증 파이프라인
ML 모델은 소프트웨어처럼 단순 배포가 아니라
배포 이후 성능 유지가 핵심이라 더 복잡하다.
이 모델을 어디에 배포할까?
어떻게 안전하게 업데이트할까?
CI에서 검증된 모델이 저장됨.
저장되는 것:
CD 시스템(예: GitHub Actions, Jenkins, Azure DevOps)이 다음을 자동화:
ML에서 가장 중요한 것은 배포 이후 성능이 떨어지는 시점을 감지하는 것
→ CI/CD만으로는 해결 불가
→ “CM(모델 모니터링)”이 필수
정답 레이블이 지연되므로(라벨링 딜레이)
배포 후 며칠~몇 주 후에 검증하는 구조가 흔함.
CM에서 성능 저하 감지 →
CI 파이프라인 다시 실행 →
새로운 모델 자동 재학습 →
CD 통해 자동 배포
이게 MLOps의 완성된 자동화 루프:
Data → CI → Model Registry → CD → Live System → CM → (성능 저하) → 재학습 → 또 CI
① Data Versioning
↓
② CI (코드 + 데이터 + 모델 테스트)
↓
③ Model Registry (승인된 모델 저장)
↓
④ CD (API, Batch, Streaming 배포)
↓
⑤ CM (성능, 드리프트, 운영 문제 감지)
↓
⑥ Trigger: 재학습 필요
↓
다시 ② CI로 돌아감
문서 구성: 아키텍처 다이어그램(mermaid), 각 구성요소 설명, 운영/모니터링 체크리스트, 그리고 GitHub Actions 기반의 ML용 CI/CD YAML 템플릿
flowchart LR
subgraph Ingestion
A[External Data Sources\n(Streaming, DB, Files, Events)] -->|Ingest| B[Azure Data Factory / Event Hubs / IoT Hub]
end
B --> C[ADLS Gen2 (Raw Zone)]
C --> D[Data Versioning\n(LakeFS / DVC)]
D --> E[Data Validation\n(Great Expectations / whylogs)]
E --> F[Feature Engineering Notebook/Pipelines\n(Azure Databricks / Azure ML Data Prep)]
F --> G[Feature Store / Parquet Store]
G --> H[Training Compute\n(Azure ML Compute / Compute Cluster)]
H --> I[Experiment Tracking & Model Registry\n(Azure ML Registry / MLflow)]
I --> J[Model Artifact (registry + metadata)]
J --> K[CI/CD Pipeline (GitHub Actions / Azure DevOps)]
K --> L[Image Build & ACR]\n K --> M[Validation Tests & Approval]
L --> N[Deployment Targets]
subgraph Deployment
N --> O[Managed Online Endpoint (Azure ML Endpoints)]
N --> P[Batch Endpoint (Azure ML Batch/Databricks)]
N --> Q[Edge / IoT Devices]
end
O --> R[Monitoring: Azure Monitor / Application Insights + Model Monitoring (Evidently / Fiddler / Arize)]
R --> S[Alerts & Retrain Trigger]
S --> H
style Ingestion fill:#f8f9fa,stroke:#333,stroke-width:1px
이 템플릿은 (A) 코드 테스트/데이터 검사/모델 평가(Metric gate)로 구성된 CI, (B) 모델 등록·이미지 빌드·배포를 수행하는 CD 파이프라인으로 나뉩니다. 필요에 따라
train단계를 오프라인 학습(온프레미스)으로 바꾸거나, 학습은 주기적 트리거로 분리하세요.
name: mlops-azureml-ci-cd
on:
push:
branches: [ main ]
workflow_dispatch: {}
env:
AZURE_SUBSCRIPTION: ${{ secrets.AZURE_SUBSCRIPTION }}
AZURE_RESOURCE_GROUP: my-ml-rg
AZURE_WORKSPACE: my-ml-workspace
LOCATION: eastus
ACR_NAME: myacrname
MODEL_NAME: my-model
ENDPOINT_NAME: my-model-endpoint
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run unit tests
run: |
pytest tests/unit -q
data-and-smoke-tests:
needs: unit-tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install validation tools
run: |
pip install great_expectations whylogs
- name: Run data validation
run: |
# 예: 스테이징 데이터에 대한 스키마 검사 또는 샘플 검사
python infra/data_validation/run_data_checks.py --source staging
train-and-register:
needs: data-and-smoke-tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Install Azure ML CLI v2
run: |
python -m pip install --upgrade pip
pip install azure-cli
az extension add -n ml --yes || true
- name: Submit training job to Azure ML
id: submit_train
run: |
# 학습은 Azure ML job으로 제출
az ml job create --file jobs/train_job.yml --no-wait
- name: Wait for training completion (poll)
run: |
# 간단한 polling 예시(프로덕션에서는 더 견고한 로직을 권장)
JOB_ID=$(az ml job list --query "[?name=='train_job'].name | [0]" -o tsv)
echo "Job: $JOB_ID"
az ml job wait --name $JOB_ID --timeout 36000
- name: Register model
run: |
az ml model create --name ${{ env.MODEL_NAME }} --path outputs/model.pkl --asset-path outputs/model.pkl
- name: Fetch model metadata
run: az ml model show --name ${{ env.MODEL_NAME }} -o table
evaluate-and-gate:
needs: train-and-register
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Download registered model for evaluation
run: |
az ml model download --name ${{ env.MODEL_NAME }} --path downloaded_model
- name: Run evaluation script
run: |
python infra/eval/evaluate.py downloaded_model --metrics-file metrics.json
- name: Check metric gate
id: check_metrics
run: |
python infra/eval/check_gate.py metrics.json --min-auc 0.78
build-and-push-image:
needs: evaluate-and-gate
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Login to ACR
run: |
az acr login --name ${{ env.ACR_NAME }}
- name: Build container image
run: |
IMAGE_TAG=${{ github.sha }}
az acr build --registry ${{ env.ACR_NAME }} --image ${ACR_NAME}.azurecr.io/${{ env.MODEL_NAME }}:${IMAGE_TAG} .
deploy:
needs: build-and-push-image
runs-on: ubuntu-latest
steps:
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Create or update endpoint
run: |
IMAGE_TAG=${{ github.sha }}
az ml online-endpoint create --name ${{ env.ENDPOINT_NAME }} --resource-group ${{ env.AZURE_RESOURCE_GROUP }} --workspace-name ${{ env.AZURE_WORKSPACE }} || true
- name: Create deployment
run: |
az ml online-deployment create \
--name blue-deployment \
--endpoint ${{ env.ENDPOINT_NAME }} \
--resource-group ${{ env.AZURE_RESOURCE_GROUP }} \
--workspace-name ${{ env.AZURE_WORKSPACE }} \
--model ${{ env.MODEL_NAME }}:1 \
--image ${ACR_NAME}.azurecr.io/${{ env.MODEL_NAME }}:${{ github.sha }} \
--instance-type Standard_DS3_v2 \
--instance-count 1
- name: Traffic shift (Canary -> full)
run: |
# 예: 10% 트래픽을 blue에 주기
az ml online-endpoint update --name ${{ env.ENDPOINT_NAME }} --traffic "{\"blue-deployment\":10, \"green-deployment\":90}"
monitor-alerts:
needs: deploy
runs-on: ubuntu-latest
steps:
- name: Create monitor resources (if not exists)
run: |
# Application Insights / Monitor 알람 셋업 스크립트 또는 IaC 실행
echo "Monitoring and alert resources should be configured separately via IaC or ARM/Bicep"
사용법 노트
secrets.AZURE_CREDENTIALS는 OIDC 또는 서비스 프린시플 JSON을 사용jobs/train-and-register에서jobs/train_job.yml은 Azure ML Job 스펙으로 교체- 모델 평가/게이트 로직은 도메인별 지표(AUC, RMSE, F1 등)에 따라 조정
- 트래픽 쉐어 로직은 엔드포인트/배포 이름에 맞춰 수정
원하면 이 문서를 기반으로 (A) Azure DevOps YAML 변환, (B) 실제 jobs/train_job.yml 예시(AML job spec), (C) Bicep 템플릿(Workspace+ACR+KeyVault)을 추가로 만들어줄게.
repo-root/
├─ src/
│ ├─ train.py # 훈련 엔트리포인트 (main)
│ ├─ inference.py # 서빙용 래퍼 (predict function)
│ ├─ model_utils.py # 모델 저장/로딩 로직
│ └─ requirements.txt
├─ infra/
│ ├─ data_validation/
│ │ └─ run_data_checks.py # Great Expectations 호출 스크립트
│ ├─ eval/
│ │ ├─ evaluate.py # 모델 성능 계산
│ │ └─ check_gate.py # metric gate 로직 (exit code 여부)
│ └─ aml/
│ └─ jobs/
│ └─ train_job.yml # Azure ML job 스펙
├─ outputs/
│ ├─ model.pkl
│ └─ metrics.json
└─ .github/workflows/
└─ mlops-azureml-ci-cd.yml # CI/CD 워크플로
위 구조를 기준으로 아래 GitHub Actions YAML은
src/train.py를 Azure ML job으로 제출하고, 학습 아티팩트는outputs/에 저장되도록 합니다.
name: mlops-azureml-ci-cd
on:
push:
branches: [ main ]
workflow_dispatch: {}
env:
AZURE_SUBSCRIPTION: ${{ secrets.AZURE_SUBSCRIPTION }}
AZURE_RESOURCE_GROUP: my-ml-rg
AZURE_WORKSPACE: my-ml-workspace
LOCATION: eastus
ACR_NAME: myacrname
MODEL_NAME: my-model
ENDPOINT_NAME: my-model-endpoint
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r src/requirements.txt
- name: Run unit tests
run: |
pytest tests/unit -q || true
data-and-smoke-tests:
needs: unit-tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install validation tools
run: |
pip install great_expectations whylogs
- name: Run data validation (staging)
run: |
python infra/data_validation/run_data_checks.py --source staging
train-and-register:
needs: data-and-smoke-tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Install Azure ML CLI v2
run: |
python -m pip install --upgrade pip
pip install azure-cli
az extension add -n ml --yes || true
- name: Submit training job to Azure ML
id: submit_train
run: |
az ml job create --file infra/aml/jobs/train_job.yml --no-wait
- name: Wait for training completion (poll)
run: |
JOB_ID=$(az ml job list --query "[?properties.display_name=='train_job'].name | [0]" -o tsv)
echo "Job: $JOB_ID"
az ml job wait --name $JOB_ID --timeout 36000
- name: Download model artifact from run outputs
run: |
# train_job.yml에서 outputs/model.pkl을 upload 하도록 설정되어 있다고 가정
az ml job download --name $JOB_ID --output outputs --artifact-path outputs/model.pkl || true
- name: Register model
run: |
az ml model create --name ${{ env.MODEL_NAME }} --path outputs/model.pkl --asset-path outputs/model.pkl
evaluate-and-gate:
needs: train-and-register
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v
리포지토리 구조(권장) 기준으로 GitHub Actions YAML을 커스터마이즈해서 .github/workflows/mlops-azureml-ci-cd.yml 내용으로 문서에 추가했어.
src/train.py, outputs/model.pkl, infra/data_validation/run_data_checks.py, infra/eval/* 같은 경로들이 반영되어 있어.infra/aml/jobs/train_job.yml로 Azure ML job으로 제출하도록 구성되어 있고, 학습 결과(artifact)를 받아 모델을 레지스트리에 등록하고 평가-게이트 통과하면 컨테이너 빌드와 배포로 이어지게 되어 있어.데이터 드리프트 알림 시스템 아키텍처(머메이드 다이어그램 포함), 권장 메트릭(PSI, KS p-value 등), 임계값 예시, 알림/오케스트레이션 플로우, 그리고 Azure Function을 통한 재학습 트리거 코드 스켈레톤까지 문서화해서 추가했어.