[Daily morning study] GitOps์™€ ArgoCD ๊ฐœ๋…

#daily morning study

Image


GitOps๋ž€

GitOps๋Š” Git์„ ์ธํ”„๋ผ์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฐํฌ์˜ ๋‹จ์ผ ์ง„์‹ค ์†Œ์Šค(Single Source of Truth)๋กœ ์‚ผ๋Š” ์šด์˜ ๋ฐฉ์‹์ด๋‹ค. ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด, โ€œGit์— ์žˆ๋Š” ๊ฒƒ์ด ๊ณง ์‹ค์ œ ์‹œ์Šคํ…œ์˜ ์ƒํƒœ์—ฌ์•ผ ํ•œ๋‹คโ€๋Š” ์›์น™์ด๋‹ค.

2017๋…„ Weaveworks๊ฐ€ ์ฒ˜์Œ ์ œ์•ˆํ•œ ๊ฐœ๋…์œผ๋กœ, ๋‹ค์Œ ๋„ค ๊ฐ€์ง€ ์›์น™์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ๋‹ค.

์›์น™์„ค๋ช…
์„ ์–ธ์ (Declarative)์ธํ”„๋ผ์™€ ์•ฑ ์ƒํƒœ๋ฅผ ์ฝ”๋“œ๋กœ ์„ ์–ธ์ ์œผ๋กœ ๊ธฐ์ˆ 
๋ฒ„์ „ ๊ด€๋ฆฌ๋ชจ๋“  ๋ณ€๊ฒฝ ์ด๋ ฅ์ด Git์— ๊ธฐ๋ก๋จ
์ž๋™ ์ ์šฉGit ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ž๋™์œผ๋กœ ์‹œ์Šคํ…œ์— ๋ฐ˜์˜
์ง€์†์  ๋™๊ธฐํ™”์‹ค์ œ ์‹œ์Šคํ…œ ์ƒํƒœ์™€ Git ์ƒํƒœ๋ฅผ ์ง€์†์ ์œผ๋กœ ๋น„๊ตยท๊ต์ •

GitOps vs ๊ธฐ์กด CI/CD

๊ธฐ์กด CI/CD ํŒŒ์ดํ”„๋ผ์ธ์€ ๋ณดํ†ต Push ๋ฐฉ์‹์ด๋‹ค. ์ฝ”๋“œ๊ฐ€ ํ‘ธ์‹œ๋˜๋ฉด CI ์„œ๋ฒ„๊ฐ€ ๋นŒ๋“œํ•˜๊ณ , ์ง์ ‘ ํด๋Ÿฌ์Šคํ„ฐ์— ๋ฐฐํฌ ๋ช…๋ น์„ ์‹คํ–‰ํ•œ๋‹ค.

[Git Push] โ†’ [CI ์„œ๋ฒ„: ๋นŒ๋“œ/ํ…Œ์ŠคํŠธ] โ†’ [kubectl apply] โ†’ [k8s ํด๋Ÿฌ์Šคํ„ฐ]

GitOps๋Š” Pull ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค. ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด๋ถ€์˜ ์—์ด์ „ํŠธ๊ฐ€ Git์„ ์ฃผ๊ธฐ์ ์œผ๋กœ ๊ฐ์‹œํ•˜๋‹ค๊ฐ€, ์ฐจ์ด(diff)๊ฐ€ ์ƒ๊ธฐ๋ฉด ์Šค์Šค๋กœ ๋™๊ธฐํ™”ํ•œ๋‹ค.

[Git Push] โ†’ [CI ์„œ๋ฒ„: ๋นŒ๋“œ/์ด๋ฏธ์ง€ ํ‘ธ์‹œ] โ†’ [Git ๋งค๋‹ˆํŽ˜์ŠคํŠธ ์—…๋ฐ์ดํŠธ]
                                                        โ†“
                                          [์—์ด์ „ํŠธ๊ฐ€ diff ๊ฐ์ง€ ํ›„ Pull & Apply]

ํ•ต์‹ฌ ์ฐจ์ด์ 

  • ๊ธฐ์กด ๋ฐฉ์‹: CI ์„œ๋ฒ„๊ฐ€ ํด๋Ÿฌ์Šคํ„ฐ์— ์ง์ ‘ ์ ‘๊ทผ(Push)ํ•ด์„œ ๋ฐฐํฌ
  • GitOps: ํด๋Ÿฌ์Šคํ„ฐ ์•ˆ์˜ ์—์ด์ „ํŠธ๊ฐ€ Git์„ Pullํ•ด์„œ ์Šค์Šค๋กœ ๋ฐ˜์˜

์ด ์ฐจ์ด ๋•๋ถ„์— ํด๋Ÿฌ์Šคํ„ฐ ์™ธ๋ถ€์—์„œ ์ง์ ‘ ์ ‘๊ทผํ•˜๋Š” ์ž๊ฒฉ์ฆ๋ช…์„ CI ์„œ๋ฒ„์— ์ค„ ํ•„์š”๊ฐ€ ์—†์–ด ๋ณด์•ˆ์ด ํ–ฅ์ƒ๋œ๋‹ค.


ArgoCD๋ž€

ArgoCD๋Š” Kubernetes๋ฅผ ์œ„ํ•œ GitOps ๊ธฐ๋ฐ˜ ์ง€์†์  ๋ฐฐํฌ(Continuous Delivery) ๋„๊ตฌ๋‹ค.

Git ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ์ •์˜๋œ Kubernetes ๋งค๋‹ˆํŽ˜์ŠคํŠธ(YAML)๋ฅผ ์‹ค์ œ ํด๋Ÿฌ์Šคํ„ฐ ์ƒํƒœ์™€ ์ง€์†์ ์œผ๋กœ ๋น„๊ตํ•ด์„œ, ์ฐจ์ด๊ฐ€ ์ƒ๊ธฐ๋ฉด ์ž๋™ ๋˜๋Š” ์ˆ˜๋™์œผ๋กœ ๋™๊ธฐํ™”ํ•œ๋‹ค.

์ฃผ์š” ํŠน์ง•

  • ์„ ์–ธ์  ์„ค์ •: ๋ฐฐํฌํ•  ์•ฑ์˜ ์†Œ์Šค(Git URL, ๊ฒฝ๋กœ)์™€ ๋Œ€์ƒ ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ArgoCD Application ๋ฆฌ์†Œ์Šค๋กœ ์„ ์–ธ
  • ์‹ค์‹œ๊ฐ„ ์ƒํƒœ ํ™•์ธ: ์›น UI์—์„œ ์•ฑ์˜ ํ˜„์žฌ ๋ฐฐํฌ ์ƒํƒœ, ๋ฆฌ์†Œ์Šค ํŠธ๋ฆฌ๋ฅผ ์‹œ๊ฐ์ ์œผ๋กœ ํ™•์ธ ๊ฐ€๋Šฅ
  • ์ž๋™/์ˆ˜๋™ ๋™๊ธฐํ™”: ์ž๋™ ๋™๊ธฐํ™” ์„ค์ • ์‹œ Git ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๋ฐ”๋กœ ํด๋Ÿฌ์Šคํ„ฐ์— ๋ฐ˜์˜
  • ๋กค๋ฐฑ: Git ํžˆ์Šคํ† ๋ฆฌ๊ฐ€ ๊ณง ๋ฐฐํฌ ์ด๋ ฅ์ด๋ฏ€๋กœ, ์›ํ•˜๋Š” ์ปค๋ฐ‹์œผ๋กœ ๊ฐ„๋‹จํžˆ ๋กค๋ฐฑ ๊ฐ€๋Šฅ
  • ๋ฉ€ํ‹ฐ ํด๋Ÿฌ์Šคํ„ฐ: ๋‹จ์ผ ArgoCD ์ธ์Šคํ„ด์Šค๋กœ ์—ฌ๋Ÿฌ Kubernetes ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ

ArgoCD ํ•ต์‹ฌ ๊ฐœ๋…

Application

ArgoCD์—์„œ ๋ฐฐํฌ ๋‹จ์œ„๋ฅผ Application์ด๋ผ ๋ถ€๋ฅธ๋‹ค. ๋‹ค์Œ ์ •๋ณด๋ฅผ ๋‹ด๋Š”๋‹ค.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/my-org/my-app-config
    targetRevision: HEAD
    path: k8s/overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true       # Git์—์„œ ์‚ญ์ œ๋œ ๋ฆฌ์†Œ์Šค๋Š” ํด๋Ÿฌ์Šคํ„ฐ์—์„œ๋„ ์‚ญ์ œ
      selfHeal: true    # ํด๋Ÿฌ์Šคํ„ฐ ์ƒํƒœ๊ฐ€ ์ˆ˜๋™์œผ๋กœ ๋ฐ”๋€Œ์–ด๋„ Git ์ƒํƒœ๋กœ ๋ณต์›

Sync ์ƒํƒœ

ArgoCD๋Š” Application์˜ ์ƒํƒœ๋ฅผ ํ•ญ์ƒ ๋‘ ๊ฐ€์ง€๋กœ ํ‘œ์‹œํ•œ๋‹ค.

์ƒํƒœ์„ค๋ช…
SyncedGit ์ƒํƒœ = ํด๋Ÿฌ์Šคํ„ฐ ์‹ค์ œ ์ƒํƒœ (์ •์ƒ)
OutOfSyncGit ์ƒํƒœ โ‰  ํด๋Ÿฌ์Šคํ„ฐ ์‹ค์ œ ์ƒํƒœ (๋™๊ธฐํ™” ํ•„์š”)

Health ์ƒํƒœ

์ƒํƒœ์„ค๋ช…
Healthy๋ชจ๋“  ๋ฆฌ์†Œ์Šค๊ฐ€ ์ •์ƒ ๋™์ž‘ ์ค‘
Degraded์ผ๋ถ€ ๋ฆฌ์†Œ์Šค๊ฐ€ ์˜ค๋ฅ˜ ์ƒํƒœ
Progressing๋ฐฐํฌ ์ง„ํ–‰ ์ค‘
Missing๋ฆฌ์†Œ์Šค๊ฐ€ ํด๋Ÿฌ์Šคํ„ฐ์— ์กด์žฌํ•˜์ง€ ์•Š์Œ

ArgoCD ๋™์ž‘ ํ๋ฆ„

1. ๊ฐœ๋ฐœ์ž๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ ๋ณ€๊ฒฝ โ†’ CI์—์„œ ๋นŒ๋“œ ํ›„ Docker ์ด๋ฏธ์ง€ ํ‘ธ์‹œ
2. CI ๋˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ Git ๋งค๋‹ˆํŽ˜์ŠคํŠธ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ image ํƒœ๊ทธ ์—…๋ฐ์ดํŠธ
3. ArgoCD๊ฐ€ ์ฃผ๊ธฐ์ ์œผ๋กœ(๊ธฐ๋ณธ 3๋ถ„) ๋˜๋Š” webhook์œผ๋กœ Git ๋ณ€๊ฒฝ ๊ฐ์ง€
4. Git ์ƒํƒœ์™€ ํด๋Ÿฌ์Šคํ„ฐ ์ƒํƒœ ๋น„๊ต โ†’ OutOfSync ๊ฐ์ง€
5. ์ž๋™ ๋™๊ธฐํ™” ์„ค์ • ์‹œ ์ž๋™์œผ๋กœ kubectl apply, ์ˆ˜๋™์ด๋ฉด ๋Œ€๊ธฐ
6. ๋ฐฐํฌ ์™„๋ฃŒ ํ›„ Synced + Healthy ์ƒํƒœ๋กœ ์ „ํ™˜

Kustomize / Helm ์—ฐ๋™

ArgoCD๋Š” raw YAML๋ฟ ์•„๋‹ˆ๋ผ Kustomize์™€ Helm์„ ๊ธฐ๋ณธ ์ง€์›ํ•œ๋‹ค.

Helm ์˜ˆ์‹œ

source:
  repoURL: https://charts.bitnami.com/bitnami
  chart: redis
  targetRevision: 17.x.x
  helm:
    values: |
      auth:
        enabled: false
      replica:
        replicaCount: 2

Kustomize ์˜ˆ์‹œ

source:
  repoURL: https://github.com/my-org/my-app-config
  path: k8s/overlays/staging
  targetRevision: HEAD
  kustomize:
    images:
      - my-app=my-registry/my-app:v1.2.3

ArgoCD ์„ค์น˜ (๊ฐ„๋‹จ ์š”์•ฝ)

# argocd ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ƒ์„ฑ ํ›„ ์„ค์น˜
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# ์ดˆ๊ธฐ admin ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d

# ArgoCD CLI ๋กœ๊ทธ์ธ
argocd login <ARGOCD_SERVER>

GitOps ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๊ตฌ์กฐ ํŒจํ„ด

GitOps๋ฅผ ๋„์ž…ํ•  ๋•Œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์–ด๋–ป๊ฒŒ ๊ตฌ์„ฑํ• ์ง€๊ฐ€ ์ค‘์š”ํ•˜๋‹ค.

๋ชจ๋…ธ๋ ˆํฌ ๋ฐฉ์‹

my-gitops-repo/
โ”œโ”€โ”€ apps/
โ”‚   โ”œโ”€โ”€ frontend/
โ”‚   โ”‚   โ”œโ”€โ”€ deployment.yaml
โ”‚   โ”‚   โ””โ”€โ”€ service.yaml
โ”‚   โ””โ”€โ”€ backend/
โ”‚       โ”œโ”€โ”€ deployment.yaml
โ”‚       โ””โ”€โ”€ service.yaml
โ””โ”€โ”€ infra/
    โ”œโ”€โ”€ namespaces.yaml
    โ””โ”€โ”€ ingress.yaml

๋ฉ€ํ‹ฐ๋ ˆํฌ ๋ฐฉ์‹

app-source-repo/      โ† ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์†Œ์Šค ์ฝ”๋“œ (CI๊ฐ€ ์ด๋ฏธ์ง€ ๋นŒ๋“œ)
app-config-repo/      โ† Kubernetes ๋งค๋‹ˆํŽ˜์ŠคํŠธ๋งŒ (ArgoCD๊ฐ€ ๊ฐ์‹œ)

๋ฉ€ํ‹ฐ๋ ˆํฌ ๋ฐฉ์‹์ด ๋” ํ”ํžˆ ์‚ฌ์šฉ๋œ๋‹ค. ์†Œ์Šค ์ฝ”๋“œ ๋ณ€๊ฒฝ๊ณผ ๋ฐฐํฌ ์„ค์ • ๋ณ€๊ฒฝ์„ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ , ๋ˆ„๊ฐ€ ์–ธ์ œ ๋ฐฐํฌ ์„ค์ •์„ ๋ณ€๊ฒฝํ–ˆ๋Š”์ง€ ์ถ”์ ์ด ์‰ฝ๋‹ค.


GitOps์˜ ์žฅ์  ์ •๋ฆฌ

  • ๊ฐ์‚ฌ ์ถ”์ (Audit Trail): ๋ชจ๋“  ๋ณ€๊ฒฝ์ด Git ์ปค๋ฐ‹์œผ๋กœ ๋‚จ์•„ โ€œ๋ˆ„๊ฐ€, ์–ธ์ œ, ๋ฌด์—‡์„โ€ ๋ฐ”๊ฟจ๋Š”์ง€ ๋ช…ํ™•
  • ๋กค๋ฐฑ ์šฉ์ด: git revert ๋˜๋Š” ์ด์ „ ์ปค๋ฐ‹์œผ๋กœ ์ฒดํฌ์•„์›ƒํ•˜๋ฉด ์ฆ‰์‹œ ์ด์ „ ์ƒํƒœ๋กœ ๋ณต์›
  • ๋“œ๋ฆฌํ”„ํŠธ ๋ฐฉ์ง€: ๋ˆ„๊ตฐ๊ฐ€ ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์ˆ˜๋™์œผ๋กœ ๊ฑด๋“œ๋ ค๋„ selfHeal์ด Git ์ƒํƒœ๋กœ ๋˜๋Œ๋ฆผ
  • ๋ณด์•ˆ ํ–ฅ์ƒ: CI ์„œ๋ฒ„๊ฐ€ ํด๋Ÿฌ์Šคํ„ฐ์— ์ง์ ‘ ์ ‘๊ทผํ•  ์ž๊ฒฉ์ฆ๋ช…์ด ํ•„์š” ์—†์Œ
  • ํ˜‘์—… ์นœํ™”์ : Pull Request ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฐฐํฌ ๋ณ€๊ฒฝ์„ ๋ฆฌ๋ทฐํ•˜๊ณ  ์Šน์ธํ•  ์ˆ˜ ์žˆ์Œ

์ •๋ฆฌ

GitOps = โ€œGit์ด ๊ณง ๋ฐฐํฌ ์ƒํƒœโ€๋ผ๋Š” ์›์น™. ArgoCD๋Š” ๊ทธ ์›์น™์„ Kubernetes์—์„œ ๊ตฌํ˜„ํ•˜๋Š” ๋„๊ตฌ๋‹ค. ์ฝ”๋“œ ๋ฐฐํฌ๋ฟ ์•„๋‹ˆ๋ผ ํด๋Ÿฌ์Šคํ„ฐ ์„ค์ •, RBAC, ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ƒ์„ฑ ๊ฐ™์€ ์ธํ”„๋ผ ๋ณ€๊ฒฝ๋„ Git์„ ํ†ตํ•ด ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์„œ, ๋Œ€๊ทœ๋ชจ Kubernetes ์šด์˜ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์‹ค์ƒ ํ‘œ์ค€์ฒ˜๋Ÿผ ์“ฐ์ด๊ณ  ์žˆ๋‹ค.