CGOA — GitOps 인증 어소시에이트 · 저장소 구조와 환경 승격 · 실습
GitOps 저장소 뼈대 만들기
목표
GitOps 설정 저장소의 표준 레이아웃을 직접 만들고, 같은 base 가 환경마다 다른 최종 매니페스트로 렌더되는 것을 눈으로 확인합니다. 마지막에는 그 저장소를 Argo CD 에 물리는 Application·AppProject·app-of-apps 루트까지 파일로 완성합니다.
왜 중요한가
GitOps 에서 저장소 구조는 취향 문제가 아니라 운영 비용을 결정하는 설계 입니다. base 와 오버레이가 제대로 갈려 있으면 stage 에서 prod 로 올리는 PR 의 diff 가 이미지 태그 한 줄이 되고, 리뷰어는 "설정은 그대로이고 버전만 올라간다"를 눈으로 확인할 수 있습니다. 반대로 환경별로 YAML 을 통째로 복사해 두면 승격 PR 마다 수십 줄이 바뀌고, 어느 줄이 의도된 차이인지 아무도 모르게 됩니다. 이 실습에서 만드는 Application 과 AppProject 는 실습 환경에 Argo CD CRD 가 없으므로 파일로만 작성하며, 채점은 그 파일을 읽어서 합니다. 실제 운영에서도 이 파일들은 Git 에 커밋되는 산출물이므로 형태를 정확히 익히는 것이 그대로 실무입니다.
단계
1. /root/cgoa-repo/apps/checkout/base, /root/cgoa-repo/apps/checkout/overlays/dev, /root/cgoa-repo/apps/checkout/overlays/stage, /root/cgoa-repo/apps/checkout/overlays/prod, /root/cgoa-repo/bootstrap 디렉터리를 만드세요.
2. base/deployment.yaml 에 Deployment checkout 을 작성하세요 — spec.replicas: 1, 셀렉터와 파드 라벨 모두 app: checkout, 컨테이너 이름 app, 이미지 ghcr.io/labhub/checkout:1.4.0, containerPort 8080. base/service.yaml 에 Service checkout 을 작성하세요 — spec.ports[0].port: 80, targetPort: 8080, 셀렉터 app: checkout. base/kustomization.yaml 의 resources 에 두 파일을 나열하세요.
3. overlays/dev/kustomization.yaml 에 resources: [../../base], namespace: cgoa-dev, namePrefix: dev- 를 쓰세요. overlays/stage/kustomization.yaml 에는 resources: [../../base], namespace: cgoa-stage, namePrefix: stage-, 그리고 replicas 로 checkout 을 2 로 지정하세요.
4. overlays/prod/kustomization.yaml 에 resources: [../../base], namespace: cgoa-prod, namePrefix: prod-, replicas 로 checkout 을 3, images 로 ghcr.io/labhub/checkout 의 newTag 를 1.5.0 으로 지정하세요.
5. kubectl kustomize /root/cgoa-repo/apps/checkout/overlays/prod 의 출력을 /root/cgoa-repo/render-prod.yaml 에 저장하세요.
6. /root/cgoa-repo/bootstrap/app-checkout-prod.yaml 에 Argo CD Application 을 작성하세요 — apiVersion: argoproj.io/v1alpha1, kind: Application, metadata.name: checkout-prod, metadata.namespace: argocd, spec.project: checkout, spec.source.repoURL: http://10.0.0.200/labhub/gitops.git, spec.source.path: apps/checkout/overlays/prod, spec.source.targetRevision: main, spec.destination.server: https://kubernetes.default.svc, spec.destination.namespace: cgoa-prod, spec.syncPolicy.automated.prune: true, spec.syncPolicy.automated.selfHeal: true, spec.syncPolicy.syncOptions 첫 항목 CreateNamespace=true.
7. /root/cgoa-repo/bootstrap/root-app.yaml 에 app-of-apps 루트 Application 을 작성하세요 — 이름 root, 네임스페이스 argocd, spec.project: checkout, spec.source.path: bootstrap, spec.source.directory.recurse: true, spec.destination.namespace: argocd, 자동 동기화(prune·selfHeal 모두 true).
8. /root/cgoa-repo/bootstrap/project-checkout.yaml 에 AppProject checkout 을 작성하세요 — metadata.namespace: argocd, spec.sourceRepos 첫 항목 http://10.0.0.200/labhub/gitops.git, spec.destinations[0].server: https://kubernetes.default.svc, spec.destinations[0].namespace: cgoa-*, spec.clusterResourceWhitelist[0] 은 group "" 에 kind Namespace.
참고
- 렌더 확인은
kubectl kustomize <경로>입니다.kubectl apply -k와 달리 클러스터를 건드리지 않습니다. - kustomization.yaml 의
replicas는- name: checkout/count: 3형태이고,images는- name: <이미지>/newTag: "1.5.0"형태입니다. - 흔한 실수 1: 오버레이의
resources에../../base대신 파일 이름을 다시 나열해 base 를 복사해 버리는 것. 그러면 승격 PR 이 한 줄로 끝나지 않습니다. - 흔한 실수 2:
namePrefix를 base 에 두는 것. base 는 환경 무관해야 하므로 접두어는 오버레이의 몫입니다.
단계 8개
- 저장소 디렉터리 뼈대
- base 매니페스트와 kustomization
- dev·stage 오버레이
- prod 오버레이 — replicas 와 이미지 태그
- kubectl kustomize 로 렌더 결과 저장
- Argo CD Application 매니페스트
- app-of-apps 루트 Application
- AppProject 로 경계 긋기