Skip to main content

OKE 플랫폼 엔지니어링 랩 2편 — ArgoCD App-in-Apps로 인프라 배포하기

2 min 438 words

이 포스트는 OKE 플랫폼 엔지니어링 랩 시리즈의 2편입니다.


1. 배경

1편에서 OKE 클러스터를 프로비저닝했습니다. 이제 그 위에 플랫폼 애플리케이션들(Istio, Vault, cert-manager 등)을 배포해야 합니다.

kubectl apply -f로 하나씩 적용하는 방식은 관리하기 어렵고, 상태를 추적할 방법도 없습니다. 이를 해결하기 위해 ArgoCD를 사용하고, 여러 애플리케이션을 선언적으로 한꺼번에 관리하는 App-in-Apps 패턴을 적용했습니다.

App-in-Apps 패턴이란?

일반적으로 ArgoCD Application 하나는 하나의 Helm 차트나 매니페스트를 배포합니다. App-in-Apps는 상위 Application이 하위 Application 매니페스트들을 담은 Git 경로를 바라보는 구조입니다. 상위 Application을 apply하면 그 안의 모든 하위 Application이 자동으로 등록되고 배포됩니다.

flowchart LR
  apply["kubectl apply -f core.yaml\n상위 Application 하나만 적용"]
  argo["ArgoCD\ninfra/core/ 경로 스캔"]
  apply --> argo
  argo --> cm[cert-manager 자동 배포]
  argo --> eso[external-secrets 자동 배포]
  argo --> istio[istio 자동 배포]
  argo --> vault[vault 자동 배포]

2. 전체 구조

gitops/infra/
├── core.yaml                     # 상위 Application (core)
├── platform.yaml                 # 상위 Application (platform)
├── core/                         # Wave 순 배포 그룹
│   ├── cert-manager-app.yaml
│   ├── external-secrets-app.yaml
│   ├── istio-base-app.yaml
│   ├── istiod-app.yaml
│   ├── istio-ingressgateway-app.yaml
│   ├── vault-app.yaml
│   ├── reflector-app.yaml
│   └── nfs-provisioner-app.yaml
├── platform/                     # core 완료 후 배포 그룹
│   ├── cert-manager-config/
│   ├── cluster-secret-store/
│   └── istio-gateway/
└── cert-manager/                 # Helm values
    istio/ vault/ ...

coreplatform 두 그룹으로 분리한 이유는 배포 순서 때문입니다. platform 그룹의 앱들은 core 그룹의 앱이 먼저 설치되어 있어야 합니다. 예를 들어 ClusterSecretStore는 External Secrets CRD가 등록된 뒤에만 적용할 수 있고, cert-manager ClusterIssuer는 cert-manager가 먼저 떠 있어야 합니다.


3. ArgoCD 최초 부트스트랩

ArgoCD 자체는 Helm으로 직접 설치합니다. ArgoCD가 없으면 App-in-Apps를 등록할 수 없기 때문에, 이 단계만큼은 수동으로 진행합니다.

helm repo add argo https://argoproj.github.io/argo-helm
helm repo update

kubectl create namespace argocd

helm install argocd argo/argo-cd \
  --namespace argocd \
  --values argocd/values.yaml
# argocd/values.yaml
global:
  domain: argocd.<your-domain>
configs:
  params:
    server.insecure: true   # Istio에서 TLS 종료하므로 ArgoCD는 HTTP로

server:
  metrics:
    enabled: true

ArgoCD가 뜨면 core.yamlplatform.yaml을 한 번만 적용합니다. 이후부터는 Git에 push하면 ArgoCD가 자동으로 동기화합니다.

kubectl apply -f infra/core.yaml
kubectl apply -f infra/platform.yaml

4. Core 그룹

상위 Application

core.yamlinfra/core/ 경로를 바라봅니다. 이 경로 안의 모든 Application 매니페스트를 자동으로 등록합니다.

# infra/core.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: infra-core
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/<your-org>/gitops.git
    targetRevision: main
    path: infra/core
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

Sync Wave — 배포 순서 제어

infra/core/ 안의 앱들은 서로 의존 관계가 있습니다. istiodistio-base의 CRD가 먼저 등록되어야 하고, istio-ingressgatewayistiod가 먼저 떠야 합니다.

ArgoCD의 sync-wave 어노테이션으로 배포 순서를 제어합니다. 숫자가 낮을수록 먼저 배포되고, 같은 Wave 안에서는 병렬로 배포됩니다.

Wave애플리케이션이유
-3cert-manager, external-secrets, nfs-provisioner다른 앱의 CRD 의존성 없음, 가장 먼저 CRD 등록
-2istio-base, vaultistio-base CRD 등록 후 istiod 설치 필요
-1istiodistio-base CRD 필요
0istio-ingressgateway, metrics-server, reflectoristiod 필요
# infra/core/cert-manager-app.yaml
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "-3"

Helm 멀티소스 패턴

Helm 차트는 공식 레포에서 받고, values 파일은 GitOps 레포에서 관리합니다. 이 두 소스를 함께 사용하는 것이 ArgoCD의 멀티소스 기능입니다.

# infra/core/cert-manager-app.yaml
spec:
  sources:
    - repoURL: https://charts.jetstack.io
      chart: cert-manager
      targetRevision: v1.20.0
      helm:
        valueFiles:
          - $values/infra/cert-manager/values.yaml  # $values 참조
    - repoURL: https://github.com/<your-org>/gitops.git
      targetRevision: main
      ref: values    # 이 소스를 $values 변수로 참조

두 번째 소스에 ref: values를 지정하면 첫 번째 소스의 valueFiles에서 $values로 참조할 수 있습니다. Helm 차트와 values를 완전히 분리해서 관리할 수 있는 방식입니다.


5. Platform 그룹

상위 Application

platform.yamlinfra/platform/ 경로를 바라봅니다. Core 그룹과 구조는 동일하지만, Core 앱들이 모두 정상적으로 배포된 뒤에 적용되어야 합니다.

# infra/platform.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: infra-platform
  namespace: argocd
spec:
  source:
    repoURL: https://github.com/<your-org>/gitops.git
    targetRevision: main
    path: infra/platform
  # ...

Platform 앱 목록

Platform 그룹의 앱들은 Helm 차트가 아닌 직접 작성한 매니페스트를 Git 경로로 배포합니다.

# infra/platform/cert-manager-config-app.yaml
spec:
  source:
    repoURL: https://github.com/<your-org>/gitops.git
    targetRevision: main
    path: infra/cert-manager/config   # ClusterIssuer, Certificate 매니페스트
  destination:
    namespace: cert-manager
# infra/platform/istio-gateway-app.yaml
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "1"   # cert-manager-config 이후 적용
spec:
  source:
    path: infra/istio/gateway           # Istio Gateway 매니페스트
  destination:
    namespace: istio-system
애플리케이션역할
cert-manager-configClusterIssuer (Let’s Encrypt), 와일드카드 Certificate
cluster-secret-storeVault 연동 ClusterSecretStore
istio-gatewayIstio Gateway (와일드카드 도메인, TLS)
vault-vsVault Istio VirtualService
argocd-vsArgoCD Istio VirtualService
keycloak-operatorKeycloak 배포 (PostgreSQL 포함)

6. 배포 흐름 정리

flowchart TD
  A["1. ArgoCD 수동 설치 (Helm)"]
  B["2. kubectl apply -f core.yaml"]
  C["3. ArgoCD → infra/core/ 경로 스캔"]
  A --> B --> C

  subgraph w3["Wave −3 (병렬)"]
    cm[cert-manager]
    eso[external-secrets]
    nfs[nfs-provisioner]
  end
  C --> cm & eso & nfs

  subgraph w2["Wave −2 (병렬)"]
    ib[istio-base]
    vault[vault]
  end
  cm & eso & nfs --> ib & vault

  subgraph w1["Wave −1"]
    isd[istiod]
  end
  ib & vault --> isd

  subgraph w0["Wave 0 (병렬)"]
    igw[istio-ingressgateway]
    ms[metrics-server]
    ref[reflector]
  end
  isd --> igw & ms & ref

이후부터는 Git에 변경사항을 push하면 ArgoCD가 자동으로 클러스터에 반영합니다(selfHeal: true). 클러스터 상태가 Git과 다르면 자동으로 원복됩니다.