Add CI/CD workflow examples and serving manifest
CI - Lint & Test / lint-and-test (push) Has been cancelled
Details
CI - Lint & Test / lint-and-test (push) Has been cancelled
Details
- ci.yaml: lint (ruff) + test (pytest) on push/PR - train.yaml: dvc pull → train → dvc push → docker build → deploy - dvc-data-update.yaml: data validation on .dvc file changes - manifests/deployment.yaml: example serving Deployment + Service Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4f7c3da543
commit
b606ed18ae
|
|
@ -0,0 +1,30 @@
|
||||||
|
name: CI - Lint & Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, develop]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint-and-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.10"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
pip install -r requirements.txt
|
||||||
|
pip install ruff pytest
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
run: ruff check .
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: pytest tests/ -v
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
name: DVC Data Validation
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- "**.dvc"
|
||||||
|
- "dvc.yaml"
|
||||||
|
- "dvc.lock"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
validate-data:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.10"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
pip install dvc pandas
|
||||||
|
|
||||||
|
- name: Pull updated data
|
||||||
|
run: dvc pull
|
||||||
|
|
||||||
|
- name: Validate data
|
||||||
|
run: |
|
||||||
|
python -c "
|
||||||
|
import pandas as pd
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# TODO: 실제 데이터 경로와 검증 로직으로 수정
|
||||||
|
# df = pd.read_csv('data/dataset.csv')
|
||||||
|
# assert len(df) > 0, 'Dataset is empty'
|
||||||
|
# assert df.isnull().sum().sum() == 0, 'Dataset has null values'
|
||||||
|
print('Data validation passed')
|
||||||
|
"
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
name: Train & Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- "src/**"
|
||||||
|
- "configs/**"
|
||||||
|
- "dvc.yaml"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
train:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.10"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
pip install -r requirements.txt
|
||||||
|
pip install dvc
|
||||||
|
|
||||||
|
- name: Pull data from DVC
|
||||||
|
run: dvc pull
|
||||||
|
|
||||||
|
- name: Train model
|
||||||
|
run: python src/train.py
|
||||||
|
|
||||||
|
- name: Track model with DVC
|
||||||
|
run: |
|
||||||
|
dvc add models/
|
||||||
|
dvc push
|
||||||
|
|
||||||
|
- name: Commit DVC metadata
|
||||||
|
run: |
|
||||||
|
git config user.name "gitea-runner"
|
||||||
|
git config user.email "runner@mlops"
|
||||||
|
git add models/*.dvc models/.gitignore
|
||||||
|
git diff --cached --quiet || git commit -m "Update model - $(date +%Y%m%d-%H%M%S)"
|
||||||
|
git push
|
||||||
|
|
||||||
|
build-and-deploy:
|
||||||
|
needs: train
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: main
|
||||||
|
|
||||||
|
- name: Build Docker image
|
||||||
|
run: |
|
||||||
|
IMAGE_TAG="${{ github.sha }}"
|
||||||
|
docker build -t $REGISTRY_URL/mlops-serving:${IMAGE_TAG} .
|
||||||
|
docker push $REGISTRY_URL/mlops-serving:${IMAGE_TAG}
|
||||||
|
env:
|
||||||
|
REGISTRY_URL: ${{ vars.REGISTRY_URL }}
|
||||||
|
|
||||||
|
- name: Update manifest
|
||||||
|
run: |
|
||||||
|
IMAGE_TAG="${{ github.sha }}"
|
||||||
|
sed -i "s|image:.*mlops-serving.*|image: $REGISTRY_URL/mlops-serving:${IMAGE_TAG}|" manifests/deployment.yaml
|
||||||
|
git config user.name "gitea-runner"
|
||||||
|
git config user.email "runner@mlops"
|
||||||
|
git add manifests/
|
||||||
|
git commit -m "Deploy model ${IMAGE_TAG:0:7}"
|
||||||
|
git push
|
||||||
|
env:
|
||||||
|
REGISTRY_URL: ${{ vars.REGISTRY_URL }}
|
||||||
|
# ↑ manifests/ 변경 → ArgoCD가 자동 감지 → soo ns에 배포
|
||||||
46
README.md
46
README.md
|
|
@ -163,20 +163,58 @@ dvc version
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 5. CI/CD 워크플로우
|
||||||
|
|
||||||
|
`.gitea/workflows/` 에 정의. Gitea Runner가 실행합니다.
|
||||||
|
|
||||||
|
### ci.yaml — 코드 push 시 린트 + 테스트
|
||||||
|
|
||||||
|
```
|
||||||
|
trigger: push to main/develop, PR to main
|
||||||
|
동작: ruff lint → pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
### train.yaml — 모델 학습 + 배포
|
||||||
|
|
||||||
|
```
|
||||||
|
trigger: src/, configs/, dvc.yaml 변경 시
|
||||||
|
동작:
|
||||||
|
1. dvc pull (NAS에서 데이터 가져오기)
|
||||||
|
2. python src/train.py (학습)
|
||||||
|
3. dvc add + dvc push (모델 → NAS)
|
||||||
|
4. Docker build + push (서빙 이미지)
|
||||||
|
5. manifests/ 이미지 태그 업데이트 → git push
|
||||||
|
6. → ArgoCD 자동 감지 → soo ns에 배포
|
||||||
|
```
|
||||||
|
|
||||||
|
### dvc-data-update.yaml — 데이터 변경 시 검증
|
||||||
|
|
||||||
|
```
|
||||||
|
trigger: .dvc 파일, dvc.yaml, dvc.lock 변경 시
|
||||||
|
동작: dvc pull → 데이터 검증 스크립트 실행
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 파일 구조
|
## 파일 구조
|
||||||
|
|
||||||
```
|
```
|
||||||
mlops_architecture/
|
mlops_architecture/
|
||||||
├── .env # 접속 정보, 시크릿 (git 제외)
|
├── .env # 접속 정보, 시크릿 (git 제외)
|
||||||
├── .gitignore
|
├── .gitignore
|
||||||
├── config.yaml # 인프라 구성 정보
|
|
||||||
├── README.md # 설치 가이드 (이 파일)
|
|
||||||
├── .dvc/ # DVC 설정 (remote 등)
|
├── .dvc/ # DVC 설정 (remote 등)
|
||||||
|
├── .gitea/workflows/ # CI/CD 파이프라인
|
||||||
|
│ ├── ci.yaml # 린트 + 테스트
|
||||||
|
│ ├── train.yaml # 학습 → 빌드 → 배포
|
||||||
|
│ └── dvc-data-update.yaml # 데이터 검증
|
||||||
├── argocd/
|
├── argocd/
|
||||||
│ └── application.yaml # ArgoCD Application 정의
|
│ └── application.yaml # ArgoCD Application 정의
|
||||||
|
├── config.yaml # 인프라 구성 정보
|
||||||
├── gitea-runner/
|
├── gitea-runner/
|
||||||
│ └── deployment.yaml # Gitea Runner K8s 배포 (Secret+ConfigMap+Deployment)
|
│ └── deployment.yaml # Gitea Runner K8s 배포
|
||||||
└── manifests/ # K8s 배포 manifest (ArgoCD가 감시)
|
├── manifests/ # K8s 배포 manifest (ArgoCD 감시)
|
||||||
|
│ └── deployment.yaml # 서빙 Deployment + Service
|
||||||
|
└── README.md # 설치 가이드 (이 파일)
|
||||||
```
|
```
|
||||||
|
|
||||||
## 설정 파일 사용법
|
## 설정 파일 사용법
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: mlops-serving
|
||||||
|
namespace: soo
|
||||||
|
labels:
|
||||||
|
app: mlops-serving
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: mlops-serving
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: mlops-serving
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: serving
|
||||||
|
image: ${REGISTRY_URL}/mlops-serving:latest # CI에서 자동 업데이트
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
limits:
|
||||||
|
cpu: "2"
|
||||||
|
memory: 2Gi
|
||||||
|
# env:
|
||||||
|
# - name: MODEL_PATH
|
||||||
|
# value: /models/model.pt
|
||||||
|
# volumeMounts:
|
||||||
|
# - name: model-storage
|
||||||
|
# mountPath: /models
|
||||||
|
# volumes:
|
||||||
|
# - name: model-storage
|
||||||
|
# persistentVolumeClaim:
|
||||||
|
# claimName: mlops-model-pvc
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: mlops-serving
|
||||||
|
namespace: soo
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: mlops-serving
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 8080
|
||||||
|
type: ClusterIP
|
||||||
Loading…
Reference in New Issue