ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

๋ฐ˜์‘ํ˜•

๐Ÿ“ฆ MLOps - ๊ตฌ์ถ• ํ๋ฆ„ ์š”์•ฝ

 

๐Ÿšง 1. Build & Deploy ํŒŒ์ดํ”„๋ผ์ธ

1.1 Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ & Artifact Registry ์—…๋กœ๋“œ

  • mlops-app Docker ์ด๋ฏธ์ง€ ์ƒ์„ฑ (FastAPI + Model)
  • ํ”Œ๋žซํผ๋ณ„ ๋นŒ๋“œ
# ์ผ๋ฐ˜ 
docker build -t mlops-app . 

# M1 ๋งฅ๋ถ 
docker build --platform linux/amd64 -t mlops-app .

 

 

  • ๋กœ์ปฌ ์‹คํ–‰ ํ…Œ์ŠคํŠธ
docker run -it -p 80:80 mlops-app
  • GCP Artifact Registry ์—…๋กœ๋“œ
# ๋กœ๊ทธ์ธ 
cat key.json | docker login -u _json_key --password-stdin asia-northeast3-docker.pkg.dev 

# ํƒœ๊น… ํ›„ ์—…๋กœ๋“œ 
docker tag mlops-app asia-northeast3-docker.pkg.dev/<PROJECT>/docker/mlops-app 
docker push asia-northeast3-docker.pkg.dev/<PROJECT>/docker/mlops-app

โš™๏ธ 2. Helm ํŒจํ‚ค์ง•

2.1 Helm ์ฐจํŠธ ๊ตฌ์„ฑ ๋ฐ ๋ฐฐํฌ ์„ค์ •

  • Helm ์„ค์น˜ ๋ฐ ์ฐจํŠธ ์ƒ์„ฑ
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 

chmod 700 get_helm.sh && ./get_helm.sh 
helm create mlops-helm
  • values.yaml ๋ฐ Chart.yaml ์ˆ˜์ •
    • ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ ๋ณ€๊ฒฝ
    • pullPolicy: Always
    • type: LoadBalancer
    • ๋ฒ„์ „ ์ •๋ณด ์„ค์ •
  • ํ—ฌ๋ฆ„ ํŒจํ‚ค์ง• ๋ฐ Artifact Registry ํ‘ธ
helm package . 

helm registry login ... 

helm push mlops-helm-0.0.1.tgz oci://asia-northeast3-docker.pkg.dev/<PROJECT>/helm

โ˜ธ๏ธ 3. Kubernetes ๋ฐฐํฌ

3.1 Helm์œผ๋กœ ๋ฐฐํฌ

 
kubectl create namespace api 

helm install nlp-service oci://... --namespace api 

kubectl get all -n api

๐Ÿš€ 4. GitLab CI/CD ์—ฐ๋™

4.1 .gitlab-ci.yml

  • build, deploy ์Šคํ…Œ์ด์ง€ ์ž‘์„ฑ
  • ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋“ฑ๋ก
$GCP_KEY 
$ARGOCD_IP 
$ARGOCD_ID 
$ARGOCD_PW

๐Ÿงญ 5. ArgoCD ์„ค์ •

5.1 ์„ค์น˜ ๋ฐ ์ดˆ๊ธฐํ™”

 
kubectl create namespace argocd 
kubectl apply -n argocd -f https://.../install.yaml 
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type":"LoadBalancer"}}'
  • ArgoCD ์ ‘์† ํ›„ ๋กœ๊ทธ์ธ
  • helm repo ๋“ฑ๋ก
     
argocd repo add ... --type helm --enable-oci ...

5.2 Application ์ƒ์„ฑ

  • mlops-helm Chart ์„ ํƒ
  • mlops-app ์ƒ์„ฑ ๋ฐ Sync ์‹คํ–‰
  • ๋ฒ„์ „ ์—…๋ฐ์ดํŠธ ์‹œ .gitlab-ci.yml ์ˆ˜์ •

๐ŸŒ 6. nginx Ingress ์„ค์ • (stcps.com)

6.1 Ingress Controller ๋ฐฐํฌ

  • Helm Chart๋กœ nginx-ingress ์„ค์น˜
  • External IP → GCP ๊ณ ์ • IP๋กœ ์„ค์ •
  • DNS ์—ฐ๋™ (A record ๋“ฑ๋ก)

6.2 Helm ์ฐจํŠธ ์ˆ˜์ •

  • ingress.enabled: true
  • className: nginx
  • hosts: [stcps.com]
  • Chart.yaml ๋ฒ„์ „ ์—…๋ฐ์ดํŠธ → ๋‹ค์‹œ ํŒจํ‚ค์ง• & push

๐Ÿ” 7. API ์ธ์ฆ ํ† ํฐ ์„ค์ •

  • ingress.yaml & values.yaml → auth_request ์Šค๋‹ˆํŽซ ์ถ”๊ฐ€
annotations:
  nginx.org/location-snippets: |
    location /auth {
        ...
        if ($http_x_auth_token ~ ^(user1token|user2token)$) {
            return 200;
        }
        return 403;
    }
    auth_request /auth;
 
  • FastAPI /predict API์—์„œ Header ์ธ์ฆ ์ฒ˜๋ฆฌ
@app.post("/predict")
async def predict(input: Input, x_auth_token: str = Header(None)):
    ...

๐Ÿ“Š 8. GCP Logging → BigQuery ์—ฐ๋™

8.1 FastAPI ๋กœ๊ทธ → GCP Logging → BigQuery

  • ๋กœ๊ทธ๋ฅผ jsonPayload ํ˜•ํƒœ๋กœ ์ „์†ก
 
from google.cloud.logging import Client Client().setup_logging() logging.info({...})

 

8.2 Logging Sink ๊ตฌ์„ฑ

  • Sink ๋Œ€์ƒ: BigQuery dataset predict_logs
  • ํ•„ํ„ฐ: namespace, path ๊ธฐ์ค€์œผ๋กœ ์ง€์ •
resource.labels.namespace_name="api" jsonPayload.path="/predict"

8.3 BigQuery ๋ถ„์„ ์˜ˆ์‹œ

SELECT
  jsonPayload.request_time,
  EXTRACT(DATE FROM TIMESTAMP(jsonPayload.request_time)) AS request_date,
  COUNT(*) AS request_cnt
FROM `predict_logs.stderr_YYYYMMDD`
WHERE jsonPayload.x_auth_token="user2token"
GROUP BY 1,2

โœ… ์ตœ์ข… ๊ฒฐ๊ณผ

  • GitLab → CI/CD ์ž๋™ํ™”
  • ArgoCD → Kubernetes GitOps ๋ฐฐํฌ
  • Helm → ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ
  • Nginx Ingress → ๋„๋ฉ”์ธ ๋ผ์šฐํŒ… + ์ธ์ฆ
  • GCP Logging → BigQuery → API ์‚ฌ์šฉ๋Ÿ‰ ์‹œ๊ฐํ™”๊นŒ์ง€ ์™„์„ฑ
๋ฐ˜์‘ํ˜•
๋ฐ˜์‘ํ˜•
๊ณต์ง€์‚ฌํ•ญ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€
Total
Today
Yesterday
๋งํฌ
ยซ   2025/05   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
๊ธ€ ๋ณด๊ด€ํ•จ