298 lines
8.6 KiB
Markdown
298 lines
8.6 KiB
Markdown
# MLOps Architecture
|
|
|
|
Gitea + Gitea Runner + ArgoCD + DVC 기반 MLOps 파이프라인 구성 프로젝트
|
|
|
|
## Repository
|
|
|
|
```
|
|
https://gitea.inje-private.com/soo-rnd/mlops-architecture
|
|
```
|
|
|
|
## 환경 정보
|
|
|
|
| 항목 | 값 |
|
|
|------|-----|
|
|
| K8s 클러스터 | v1.34.3 / Master 3 + Worker 14 |
|
|
| Gitea | v1.22.1 — `https://gitea.inje-private.com` (외부 클러스터) |
|
|
| ArgoCD | v2.12.3 — `https://argocd.gpulive.cloud` |
|
|
| DVC Remote | NAS `192.168.0.43` |
|
|
| Storage Class | `component-nas` (default), `internal-nas`, `user-nas` |
|
|
|
|
## 컴포넌트 설치 상태
|
|
|
|
| 컴포넌트 | 상태 | 위치 |
|
|
|----------|------|------|
|
|
| Gitea | installed | 외부 클러스터 |
|
|
| Gitea Runner | **installed** (v0.3.0) | VM (`soo-runner`) |
|
|
| ArgoCD | installed + **repo 연동 완료** | 이 클러스터 (`argocd` ns) |
|
|
| DVC | **installed** (v3.66.1) | 로컬 + NAS (`/ainas/dvc-storage`) |
|
|
|
|
---
|
|
|
|
## 스케줄링 정책
|
|
|
|
워크로드(ML 학습 등)를 제외한 모든 인프라 컴포넌트는 `nodeSelector`를 지정합니다.
|
|
|
|
| 용도 | nodeSelector | 노드 |
|
|
|------|-------------|------|
|
|
| 인프라 컴포넌트 | `nodegroup: nd` | `dv2-kr3-ins-nd-worker-01` |
|
|
| 모니터링 | `nodegroup: prometheus` | `dv2-kr3-ins-nd-worker-02` |
|
|
| ML 워크로드 | 제한 없음 | GPU 등 자유 배치 |
|
|
|
|
```yaml
|
|
# 인프라 컴포넌트 예시
|
|
spec:
|
|
template:
|
|
spec:
|
|
nodeSelector:
|
|
nodegroup: nd
|
|
|
|
# 모니터링 컴포넌트 예시
|
|
spec:
|
|
template:
|
|
spec:
|
|
nodeSelector:
|
|
nodegroup: prometheus
|
|
```
|
|
|
|
---
|
|
|
|
## 1. Gitea (외부 클러스터, 설치됨)
|
|
|
|
외부 클러스터에서 운영 중. 이 프로젝트 repo 생성 완료.
|
|
|
|
```bash
|
|
# repo 생성 (API)
|
|
curl -sk -X POST "https://gitea.inje-private.com/api/v1/user/repos" \
|
|
-u "$GITEA_ADMIN_USER:$GITEA_ADMIN_PASSWORD" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"name":"mlops-architecture","description":"MLOps Architecture","private":true,"auto_init":false}'
|
|
|
|
# 로컬 연결
|
|
git init && git branch -m main
|
|
git remote add origin https://gitea.inje-private.com/soo-rnd/mlops-architecture.git
|
|
git add config.yaml README.md .gitignore
|
|
git commit -m "Initial commit"
|
|
git push -u origin main
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Gitea Runner (설치 완료 — VM 방식)
|
|
|
|
전용 VM(`soo-runner`)에 act_runner를 직접 설치하여 systemd 서비스로 운영.
|
|
기존 K8s 파드(DinD sidecar) 방식에서 VM 직접 설치로 전환.
|
|
|
|
| 항목 | 값 |
|
|
|------|-----|
|
|
| 호스트 | `ssh ubuntu@runner` (호스트명: `soo-runner`) |
|
|
| OS | Ubuntu 22.04.5 LTS |
|
|
| IP | `10.0.0.67` |
|
|
| Runner 이름 | `soo-runner` |
|
|
| act_runner | v0.3.0 (`/usr/local/bin/act_runner`) |
|
|
| Docker | v29.3.0 |
|
|
| 작업 디렉토리 | `/opt/act_runner/` |
|
|
| 서비스 | `/etc/systemd/system/act_runner.service` |
|
|
| Labels | `ubuntu-latest`, `ubuntu-22.04` (Docker), `self-hosted` (Host) |
|
|
|
|
### 2-1. VM 설치 과정
|
|
|
|
```bash
|
|
# 1. Docker 설치
|
|
sudo apt-get update
|
|
sudo apt-get install -y ca-certificates curl gnupg
|
|
sudo install -m 0755 -d /etc/apt/keyrings
|
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
|
sudo apt-get update && sudo apt-get install -y docker-ce docker-ce-cli containerd.io
|
|
sudo usermod -aG docker ubuntu
|
|
|
|
# 2. act_runner 바이너리 설치
|
|
curl -sL https://gitea.com/gitea/act_runner/releases/download/v0.3.0/act_runner-0.3.0-linux-amd64 -o act_runner
|
|
chmod +x act_runner
|
|
sudo mv act_runner /usr/local/bin/
|
|
|
|
# 3. 작업 디렉토리 생성
|
|
sudo mkdir -p /opt/act_runner
|
|
sudo chown ubuntu:ubuntu /opt/act_runner
|
|
```
|
|
|
|
### 2-2. Gitea 연동 (Runner 등록)
|
|
|
|
```bash
|
|
# 1. Gitea에서 Runner 등록 토큰 발급
|
|
# 방법 A) Web UI: Gitea > 저장소 Settings > Actions > Runners > "Create new Runner"
|
|
# 방법 B) API:
|
|
curl -sk -u "$GITEA_ADMIN_USER:$GITEA_ADMIN_PASSWORD" \
|
|
-X GET "https://gitea.inje-private.com/api/v1/repos/soo-rnd/mlops-architecture/actions/runners/registration-token" \
|
|
-H "Content-Type: application/json"
|
|
# → {"token":"<REGISTRATION_TOKEN>"} 응답에서 토큰 복사
|
|
|
|
# 2. Runner 등록
|
|
cd /opt/act_runner
|
|
act_runner register --no-interactive \
|
|
--instance https://gitea.inje-private.com \
|
|
--token <REGISTRATION_TOKEN> \
|
|
--name soo-runner \
|
|
--labels "ubuntu-latest:docker://catthehacker/ubuntu:act-22.04,ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04,self-hosted:host"
|
|
# → /opt/act_runner/.runner 파일 생성됨
|
|
```
|
|
|
|
### 2-3. systemd 서비스 등록
|
|
|
|
```bash
|
|
# 서비스 파일 생성
|
|
sudo tee /etc/systemd/system/act_runner.service > /dev/null <<'EOF'
|
|
[Unit]
|
|
Description=Gitea Act Runner
|
|
After=docker.service
|
|
Requires=docker.service
|
|
|
|
[Service]
|
|
User=ubuntu
|
|
WorkingDirectory=/opt/act_runner
|
|
ExecStart=/usr/local/bin/act_runner daemon
|
|
Restart=always
|
|
RestartSec=5
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
# 서비스 시작 및 자동 시작 등록
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable --now act_runner
|
|
```
|
|
|
|
### 2-4. 운영 명령어
|
|
|
|
```bash
|
|
# 상태 확인
|
|
ssh ubuntu@runner "sudo systemctl status act_runner"
|
|
|
|
# 로그 확인
|
|
ssh ubuntu@runner "journalctl -u act_runner -f"
|
|
|
|
# 재시작
|
|
ssh ubuntu@runner "sudo systemctl restart act_runner"
|
|
|
|
# Gitea에서 Runner 등록 확인
|
|
# https://gitea.inje-private.com/soo-rnd/mlops-architecture/settings/actions/runners
|
|
```
|
|
|
|
---
|
|
|
|
## 3. ArgoCD (설치됨 + Gitea repo 연동 완료)
|
|
|
|
Helm으로 설치 완료. Gitea repo 등록 및 Application 생성 완료.
|
|
|
|
- App 이름: `mlops-architecture`
|
|
- Source: `gitea.inje-private.com/soo-rnd/mlops-architecture` → `manifests/`
|
|
- Destination: 이 클러스터 `soo` 네임스페이스
|
|
- SyncPolicy: automated (prune + selfHeal)
|
|
|
|
```bash
|
|
# 상태 확인
|
|
kubectl get pods -n argocd
|
|
kubectl get app mlops-architecture -n argocd
|
|
|
|
# ArgoCD에 Gitea repo 등록 (이미 완료)
|
|
# ArgoCD API를 통해 등록됨 - argocd/application.yaml 참조
|
|
|
|
# Application 적용
|
|
kubectl apply -f argocd/application.yaml
|
|
|
|
# sync 상태 확인
|
|
kubectl get app mlops-architecture -n argocd -o jsonpath='{.status.sync.status}'; echo
|
|
```
|
|
|
|
---
|
|
|
|
## 4. DVC (설치 + NAS remote 설정 완료)
|
|
|
|
- 버전: v3.66.1
|
|
- Remote: NAS (`/ainas/dvc-storage`)
|
|
- NAS 마운트: `192.168.0.43:/GJ_SHARE_FS2/...` → `/ainas`
|
|
|
|
```bash
|
|
# 설치
|
|
sudo apt-get install -y python3-pip
|
|
pip3 install dvc
|
|
|
|
# 초기화
|
|
dvc init
|
|
|
|
# NAS remote 설정 (NAS가 /ainas에 마운트된 상태)
|
|
sudo mkdir -p /ainas/dvc-storage && sudo chown ubuntu:ubuntu /ainas/dvc-storage
|
|
dvc remote add -d nas /ainas/dvc-storage
|
|
|
|
# 확인
|
|
dvc remote list
|
|
dvc version
|
|
|
|
# 사용 예시
|
|
# dvc add data/dataset.csv # 파일 추적
|
|
# dvc push # NAS로 push
|
|
# dvc pull # NAS에서 pull
|
|
```
|
|
|
|
---
|
|
|
|
## 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/
|
|
├── .env # 접속 정보, 시크릿 (git 제외)
|
|
├── .gitignore
|
|
├── .dvc/ # DVC 설정 (remote 등)
|
|
├── .gitea/workflows/ # CI/CD 파이프라인
|
|
│ ├── ci.yaml # 린트 + 테스트
|
|
│ ├── train.yaml # 학습 → 빌드 → 배포
|
|
│ └── dvc-data-update.yaml # 데이터 검증
|
|
├── argocd/
|
|
│ └── application.yaml # ArgoCD Application 정의
|
|
├── config.yaml # 인프라 구성 정보
|
|
├── manifests/ # K8s 배포 manifest (ArgoCD 감시)
|
|
│ └── deployment.yaml # 서빙 Deployment + Service
|
|
└── README.md # 설치 가이드 (이 파일)
|
|
```
|
|
|
|
## 설정 파일 사용법
|
|
|
|
- `.env` : 계정 정보, 토큰 등 민감 정보 → **git에 포함되지 않음**
|
|
- `config.yaml` : 클러스터/컴포넌트 메타 정보 → git 추적 가능
|
|
- 컴포넌트 설치할 때마다 이 README와 config.yaml을 업데이트합니다
|