From fa8d65d6dab365254875c9e1c3986743ec45ee34 Mon Sep 17 00:00:00 2001 From: Mayne0213 Date: Sun, 23 Nov 2025 10:18:21 +0900 Subject: [PATCH] REFACTOR(app): migrate to argocd - Add Kustomize base and prod overlay structure - Optimize resources for 2GB RAM environment (100Mi/200Mi) - Add ArgoCD Application manifest - Remove old k8s manifests (replaced by Kustomize) - Add comprehensive deployment guide --- .github/workflows/build.yml | 3 + deploy/argocd/DEPLOY_GUIDE.md | 292 ++++++++++++++++++ deploy/argocd/application.yaml | 38 +++ .../deployment.yaml} | 12 +- deploy/k8s/base/kustomization.yaml | 14 + .../{app-service.yaml => base/service.yaml} | 5 +- .../k8s/overlays/prod/deployment-patch.yaml | 19 ++ deploy/k8s/overlays/prod/kustomization.yaml | 18 ++ 8 files changed, 392 insertions(+), 9 deletions(-) create mode 100644 deploy/argocd/DEPLOY_GUIDE.md create mode 100644 deploy/argocd/application.yaml rename deploy/k8s/{app-deployment.yaml => base/deployment.yaml} (85%) create mode 100644 deploy/k8s/base/kustomization.yaml rename deploy/k8s/{app-service.yaml => base/service.yaml} (85%) create mode 100644 deploy/k8s/overlays/prod/deployment-patch.yaml create mode 100644 deploy/k8s/overlays/prod/kustomization.yaml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9dde08b..f35d0c1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -72,3 +72,6 @@ jobs: echo "๐Ÿ“ฆ Image tags:" echo "${{ steps.meta.outputs.tags }}" echo "๐Ÿ”– Digest: ${{ steps.build.outputs.digest }}" + echo "" + echo "๐Ÿš€ ArgoCD will automatically detect and deploy this new image" + echo " Monitor deployment at your ArgoCD dashboard" diff --git a/deploy/argocd/DEPLOY_GUIDE.md b/deploy/argocd/DEPLOY_GUIDE.md new file mode 100644 index 0000000..7d232ec --- /dev/null +++ b/deploy/argocd/DEPLOY_GUIDE.md @@ -0,0 +1,292 @@ +# Jovies ArgoCD ๋ฐฐํฌ ๊ฐ€์ด๋“œ (2GB RAM ํ™˜๊ฒฝ) + +## ์ „์ œ์กฐ๊ฑด + +- โœ… ArgoCD ์„ค์น˜๋จ +- โœ… K3s ํด๋Ÿฌ์Šคํ„ฐ ์‹คํ–‰ ์ค‘ +- โœ… GHCR์— ์ด๋ฏธ์ง€ ํ‘ธ์‹œ ๊ถŒํ•œ + +## ํ˜„์žฌ ๋ฆฌ์†Œ์Šค ์„ค์ • (2GB ์ตœ์ ํ™”) + +```yaml +Jovies Pod: + replicas: 1 + resources: + requests: + memory: 100Mi + cpu: 50m + limits: + memory: 200Mi + cpu: 150m +``` + +### ์˜ˆ์ƒ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ + +``` +์‹œ์Šคํ…œ: ~300Mi +K3s: ~300Mi +ArgoCD: ~800Mi +Traefik: ~50Mi +Jovies: ~100Mi (์ตœ๋Œ€ 200Mi) +โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +์ดํ•ฉ: ~1,550Mi +์—ฌ์œ : ~500Mi โœ… +``` + +## ๋ฐฐํฌ ๋‹จ๊ณ„ + +### 1. ArgoCD์— Application ๋“ฑ๋ก + +```bash +cd /Users/minjo/home/mayne/projects/jovies + +# Application ์ƒ์„ฑ +kubectl apply -f deploy/argocd/application.yaml +``` + +### 2. ๋ฐฐํฌ ์ƒํƒœ ํ™•์ธ + +```bash +# Application ์ƒํƒœ ํ™•์ธ +kubectl get application jovies -n argocd + +# ์ถœ๋ ฅ ์˜ˆ์‹œ: +# NAME SYNC STATUS HEALTH STATUS +# jovies Synced Healthy +``` + +### 3. Pod ์ƒํƒœ ํ™•์ธ + +```bash +# Jovies namespace์˜ Pod ํ™•์ธ +kubectl get pods -n jovies + +# ์ƒ์„ธ ๋กœ๊ทธ ํ™•์ธ +kubectl logs -n jovies -l app=jovies-app -f +``` + +### 4. Service ํ™•์ธ + +```bash +# Service ์ •๋ณด ํ™•์ธ +kubectl get svc -n jovies + +# ์ถœ๋ ฅ: +# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) +# jovies-service ClusterIP 10.43.xxx.xxx 80/TCP +``` + +## ArgoCD UI ์ ‘๊ทผ + +### ํฌํŠธํฌ์›Œ๋”ฉ์œผ๋กœ ์ ‘๊ทผ + +```bash +# ArgoCD ์„œ๋ฒ„ ํฌํŠธํฌ์›Œ๋”ฉ +kubectl port-forward svc/argocd-server -n argocd 8080:443 + +# ๋ธŒ๋ผ์šฐ์ €์—์„œ https://localhost:8080 ์ ‘์† +``` + +### ์ดˆ๊ธฐ ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ + +```bash +kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d +echo +``` + +- **Username**: `admin` +- **Password**: ์œ„ ๋ช…๋ น์–ด ์ถœ๋ ฅ๊ฐ’ + +## ๋ฐฐํฌ ์›Œํฌํ”Œ๋กœ์šฐ + +``` +1. ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ”๋“œ ๋ณ€๊ฒฝ ํ›„ main ๋ธŒ๋žœ์น˜์— push + โ†“ +2. GitHub Actions๊ฐ€ Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ & GHCR์— ํ‘ธ์‹œ + (ํƒœ๊ทธ: latest, main, main-{sha}) + โ†“ +3. ArgoCD๊ฐ€ ๋งค๋‹ˆํŽ˜์ŠคํŠธ ๋ณ€๊ฒฝ ๊ฐ์ง€ (3๋ถ„๋งˆ๋‹ค) + โ†“ +4. ์ž๋™์œผ๋กœ Kubernetes์— ๋ฐฐํฌ (selfHeal: true) + โ†“ +5. Rolling Update๋กœ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ +``` + +## ์ˆ˜๋™ ๋™๊ธฐํ™” + +ํ•„์š” ์‹œ ์ˆ˜๋™์œผ๋กœ ๋™๊ธฐํ™”: + +```bash +# kubectl ์‚ฌ์šฉ +kubectl patch app jovies -n argocd --type merge -p '{"operation":{"sync":{}}}' + +# ๋˜๋Š” ArgoCD CLI ์‚ฌ์šฉ (์„ค์น˜๋˜์–ด ์žˆ๋‹ค๋ฉด) +argocd app sync jovies +``` + +## ์ด๋ฏธ์ง€ ์—…๋ฐ์ดํŠธ + +### ๋ฐฉ๋ฒ• 1: GitHub Actions (์ž๋™) + +```yaml +# .github/workflows/build.yml์ด ์ž๋™์œผ๋กœ: +# 1. ์ด๋ฏธ์ง€ ๋นŒ๋“œ +# 2. GHCR์— ํ‘ธ์‹œ (latest ํƒœ๊ทธ) +# 3. ArgoCD๊ฐ€ ์ž๋™ ๊ฐ์ง€ํ•˜์—ฌ ๋ฐฐํฌ +``` + +### ๋ฐฉ๋ฒ• 2: ์ˆ˜๋™ ์ด๋ฏธ์ง€ ํƒœ๊ทธ ๋ณ€๊ฒฝ + +```bash +# kustomization.yaml ์ˆ˜์ • +cd deploy/k8s/overlays/prod +vi kustomization.yaml + +# newTag๋ฅผ ์›ํ•˜๋Š” ๋ฒ„์ „์œผ๋กœ ๋ณ€๊ฒฝ +images: + - name: ghcr.io/mayne0213/jovies + newTag: main-abc1234 # โ† ๋ณ€๊ฒฝ + +# Git์— ์ปค๋ฐ‹ & ํ‘ธ์‹œ +git add . +git commit -m "Update jovies to main-abc1234" +git push + +# ArgoCD๊ฐ€ ์ž๋™์œผ๋กœ ๊ฐ์ง€ํ•˜์—ฌ ๋ฐฐํฌ +``` + +## ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… + +### Pod๊ฐ€ CrashLoopBackOff ์ƒํƒœ + +```bash +# Pod ๋กœ๊ทธ ํ™•์ธ +kubectl logs -n jovies -l app=jovies-app --tail=100 + +# Pod ์ƒ์„ธ ์ •๋ณด +kubectl describe pod -n jovies -l app=jovies-app + +# ์ผ๋ฐ˜์ ์ธ ์›์ธ: +# 1. ์ด๋ฏธ์ง€๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ โ†’ GHCR ๊ถŒํ•œ ํ™•์ธ +# 2. ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋ˆ„๋ฝ โ†’ ConfigMap/Secret ํ™•์ธ +# 3. Health check ์‹คํŒจ โ†’ ํฌํŠธ 3000 ํ™•์ธ +``` + +### ArgoCD Sync ์‹คํŒจ + +```bash +# Application ์ƒํƒœ ํ™•์ธ +kubectl get app jovies -n argocd -o yaml + +# ArgoCD ๋กœ๊ทธ ํ™•์ธ +kubectl logs -n argocd -l app.kubernetes.io/name=argocd-application-controller --tail=100 +``` + +### ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ (OOMKilled) + +```bash +# Pod ์ƒํƒœ ํ™•์ธ +kubectl get pod -n jovies -l app=jovies-app + +# ๋งˆ์ง€๋ง‰ ์ข…๋ฃŒ ์ด์œ  ํ™•์ธ +kubectl describe pod -n jovies -l app=jovies-app | grep -A 5 "Last State" + +# OOMKilled๊ฐ€ ๋ณด์ด๋ฉด ๋ฆฌ์†Œ์Šค ์ฆ๊ฐ€ ํ•„์š”: +# deploy/k8s/overlays/prod/deployment-patch.yaml ์ˆ˜์ • +resources: + limits: + memory: "300Mi" # 200Mi โ†’ 300Mi๋กœ ์ฆ๊ฐ€ +``` + +## ๋กค๋ฐฑ + +### ArgoCD UI์—์„œ ๋กค๋ฐฑ + +1. ArgoCD UI ์ ‘์† +2. `jovies` ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํด๋ฆญ +3. `HISTORY` ํƒญ +4. ์ด์ „ ๋ฒ„์ „ ์„ ํƒ ํ›„ `ROLLBACK` ํด๋ฆญ + +### CLI๋กœ ๋กค๋ฐฑ + +```bash +# ํžˆ์Šคํ† ๋ฆฌ ํ™•์ธ +kubectl get app jovies -n argocd -o yaml | grep -A 10 "history:" + +# ํŠน์ • ๋ฆฌ๋น„์ „์œผ๋กœ ๋กค๋ฐฑ (์˜ˆ: revision 3) +argocd app rollback jovies 3 +``` + +## ๋ชจ๋‹ˆํ„ฐ๋ง + +### ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ๋Ÿ‰ ํ™•์ธ + +```bash +# Pod ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ๋Ÿ‰ +kubectl top pod -n jovies + +# Node ์ „์ฒด ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ๋Ÿ‰ +kubectl top node + +# ์ถœ๋ ฅ ์˜ˆ์‹œ: +# NAME CPU(cores) MEMORY(bytes) +# jovies-app-xxx 10m 120Mi +``` + +### ๋ฉ”๋ชจ๋ฆฌ ์••๋ฐ• ํ™•์ธ + +```bash +# ์ „์ฒด ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ๋ชจ๋‹ˆํ„ฐ๋ง +watch -n 5 'kubectl top node && echo "---" && kubectl top pod -A | head -20' +``` + +### ๋กœ๊ทธ ์ŠคํŠธ๋ฆฌ๋ฐ + +```bash +# ์‹ค์‹œ๊ฐ„ ๋กœ๊ทธ ํ™•์ธ +kubectl logs -n jovies -l app=jovies-app -f --tail=100 + +# ์—ฌ๋Ÿฌ Pod์˜ ๋กœ๊ทธ๋ฅผ ๋ชจ๋‘ ๋ณด๊ธฐ +kubectl logs -n jovies -l app=jovies-app --all-containers=true -f +``` + +## ์ •๋ฆฌ (์‚ญ์ œ) + +```bash +# ArgoCD Application ์‚ญ์ œ (๋ฆฌ์†Œ์Šค๋„ ํ•จ๊ป˜ ์‚ญ์ œ๋จ) +kubectl delete -f deploy/argocd/application.yaml + +# ๋˜๋Š” ์ง์ ‘ ์‚ญ์ œ +kubectl delete app jovies -n argocd + +# Namespace๋„ ์‚ญ์ œํ•˜๋ ค๋ฉด +kubectl delete namespace jovies +``` + +## ๋‹ค์Œ ๋‹จ๊ณ„ + +๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ถฉ๋ถ„ํ•ด์ง€๋ฉด (4GB+): + +1. **Replica ์ฆ๊ฐ€** + ```yaml + spec: + replicas: 2 # ๊ณ ๊ฐ€์šฉ์„ฑ + ``` + +2. **๋ฆฌ์†Œ์Šค ์ฆ๊ฐ€** + ```yaml + resources: + requests: + memory: "256Mi" + limits: + memory: "512Mi" + ``` + +3. **ArgoCD Image Updater ์ถ”๊ฐ€** + - ์ž๋™์œผ๋กœ ์ƒˆ ์ด๋ฏธ์ง€ ๊ฐ์ง€ + - Git ์ปค๋ฐ‹ ์—†์ด ๋ฐฐํฌ ๊ฐ€๋Šฅ + +4. **Monitoring Stack ์ถ”๊ฐ€** + - Prometheus + - Grafana + - Alert Manager diff --git a/deploy/argocd/application.yaml b/deploy/argocd/application.yaml new file mode 100644 index 0000000..3b461be --- /dev/null +++ b/deploy/argocd/application.yaml @@ -0,0 +1,38 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: jovies + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: default + + source: + repoURL: https://github.com/Mayne0213/jovies.git + targetRevision: main + path: deploy/k8s/overlays/prod + + destination: + server: https://kubernetes.default.svc + namespace: jovies + + syncPolicy: + automated: + prune: true # ๋งค๋‹ˆํŽ˜์ŠคํŠธ์—์„œ ์ œ๊ฑฐ๋œ ๋ฆฌ์†Œ์Šค ์ž๋™ ์‚ญ์ œ + selfHeal: true # ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ์ˆ˜๋™ ๋ณ€๊ฒฝ ์‹œ ์ž๋™ ๋ณต๊ตฌ + allowEmpty: false + + syncOptions: + - CreateNamespace=true # namespace๊ฐ€ ์—†์œผ๋ฉด ์ž๋™ ์ƒ์„ฑ + - PrunePropagationPolicy=foreground + - PruneLast=true + + retry: + limit: 5 + backoff: + duration: 5s + factor: 2 + maxDuration: 3m + + revisionHistoryLimit: 10 diff --git a/deploy/k8s/app-deployment.yaml b/deploy/k8s/base/deployment.yaml similarity index 85% rename from deploy/k8s/app-deployment.yaml rename to deploy/k8s/base/deployment.yaml index 06a3864..54f5119 100644 --- a/deploy/k8s/app-deployment.yaml +++ b/deploy/k8s/base/deployment.yaml @@ -1,9 +1,9 @@ apiVersion: apps/v1 kind: Deployment metadata: + name: jovies-app labels: app: jovies-app - name: jovies-app spec: replicas: 1 selector: @@ -21,7 +21,7 @@ spec: spec: containers: - name: jovies-app - image: jovies-app-image:latest + image: ghcr.io/mayne0213/jovies:latest ports: - containerPort: 3000 protocol: TCP @@ -30,11 +30,11 @@ spec: value: production resources: requests: - memory: "512Mi" - cpu: "500m" + memory: "100Mi" + cpu: "50m" limits: - memory: "1Gi" - cpu: "1000m" + memory: "200Mi" + cpu: "150m" livenessProbe: httpGet: path: / diff --git a/deploy/k8s/base/kustomization.yaml b/deploy/k8s/base/kustomization.yaml new file mode 100644 index 0000000..6398f30 --- /dev/null +++ b/deploy/k8s/base/kustomization.yaml @@ -0,0 +1,14 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - deployment.yaml + - service.yaml + +commonLabels: + app.kubernetes.io/name: jovies + app.kubernetes.io/component: web + +images: + - name: ghcr.io/mayne0213/jovies + newTag: latest diff --git a/deploy/k8s/app-service.yaml b/deploy/k8s/base/service.yaml similarity index 85% rename from deploy/k8s/app-service.yaml rename to deploy/k8s/base/service.yaml index a9ebafe..8db106b 100644 --- a/deploy/k8s/app-service.yaml +++ b/deploy/k8s/base/service.yaml @@ -1,14 +1,13 @@ apiVersion: v1 kind: Service metadata: + name: jovies-service labels: app: jovies-app - version: prod - name: jovies-service spec: type: ClusterIP ports: - - name: "http" + - name: http port: 80 targetPort: 3000 protocol: TCP diff --git a/deploy/k8s/overlays/prod/deployment-patch.yaml b/deploy/k8s/overlays/prod/deployment-patch.yaml new file mode 100644 index 0000000..eae1de9 --- /dev/null +++ b/deploy/k8s/overlays/prod/deployment-patch.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: jovies-app + labels: + environment: production +spec: + replicas: 1 + template: + spec: + containers: + - name: jovies-app + resources: + requests: + memory: "100Mi" + cpu: "50m" + limits: + memory: "200Mi" + cpu: "150m" diff --git a/deploy/k8s/overlays/prod/kustomization.yaml b/deploy/k8s/overlays/prod/kustomization.yaml new file mode 100644 index 0000000..466bfa1 --- /dev/null +++ b/deploy/k8s/overlays/prod/kustomization.yaml @@ -0,0 +1,18 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: jovies + +resources: + - ../../base + +commonLabels: + environment: production + +# ์ด๋ฏธ์ง€ ํƒœ๊ทธ ์„ค์ • +images: + - name: ghcr.io/mayne0213/jovies + newTag: latest + +patchesStrategicMerge: + - deployment-patch.yaml