CGOA — GitOps Certified Associate
Building the Skeleton of a GitOps Repository
한국어 원문으로 표시합니다.
목표
GitOps 설정 저장소의 표준 레이아웃을 직접 만들고, 같은 base 가 환경마다 다른 최종 매니페스트로 렌더되는 것을 눈으로 확인합니다. 마지막에는 그 저장소를 Argo CD 에 물리는 Application·AppProject·app-of-apps 루트까지 파일로 완성합니다.
왜 중요한가
GitOps 에서 저장소 구조는 취향 문제가 아니라 운영 비용을 결정하는 설계 입니다. base 와 오버레이가 제대로 갈려 있으면 stage 에서 prod 로 올리는 PR 의 diff 가 이미지 태그 한 줄이 되고, 리뷰어는 "설정은 그대로이고 버전만 올라간다"를 눈으로 확인할 수 있습니다. 반대로 환경별로 YAML 을 통째로 복사해 두면 승격 PR 마다 수십 줄이 바뀌고, 어느 줄이 의도된 차이인지 아무도 모르게 됩니다. 이 실습에서 만드는 Application 과 AppProject 는 실습 환경에 Argo CD CRD 가 없으므로 파일로만 작성하며, 채점은 그 파일을 읽어서 합니다. 실제 운영에서도 이 파일들은 Git 에 커밋되는 산출물이므로 형태를 정확히 익히는 것이 그대로 실무입니다.
단계
/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디렉터리를 만드세요.base/deployment.yaml에 Deploymentcheckout을 작성하세요 —spec.replicas: 1, 셀렉터와 파드 라벨 모두app: checkout, 컨테이너 이름app, 이미지ghcr.io/labhub/checkout:1.4.0, containerPort8080.base/service.yaml에 Servicecheckout을 작성하세요 —spec.ports[0].port: 80,targetPort: 8080, 셀렉터app: checkout.base/kustomization.yaml의resources에 두 파일을 나열하세요.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로 지정하세요.overlays/prod/kustomization.yaml에resources: [../../base],namespace: cgoa-prod,namePrefix: prod-,replicas로checkout을3,images로ghcr.io/labhub/checkout의newTag를1.5.0으로 지정하세요.kubectl kustomize /root/cgoa-repo/apps/checkout/overlays/prod의 출력을/root/cgoa-repo/render-prod.yaml에 저장하세요./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./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)./root/cgoa-repo/bootstrap/project-checkout.yaml에 AppProjectcheckout을 작성하세요 —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""에 kindNamespace.
참고
- 렌더 확인은
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 는 환경 무관해야 하므로 접두어는 오버레이의 몫입니다.
저장소 디렉터리 뼈대
/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 디렉터리를 만드세요.
베이스 하나에 환경 오버레이 셋, 그리고 Application 매니페스트를 모아 둘 bootstrap 디렉터리가 필요합니다. 상위 경로까지 한 번에 만드는 mkdir 옵션을 쓰세요.
base 매니페스트와 kustomization
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 에 두 파일을 나열하세요.
base 는 환경에 무관한 공통분모만 담습니다. 네임스페이스도 replicas 도 여기서 정하지 않는 편이 좋습니다. kustomization.yaml 의 resources 에 파일 이름을 나열하세요.
dev·stage 오버레이
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 로 지정하세요.
오버레이의 resources 는 상대 경로로 base 를 가리킵니다. 이름 충돌을 막는 접두어 필드와 네임스페이스 필드를 kustomization.yaml 에서 지정할 수 있습니다.
prod 오버레이 — replicas 와 이미지 태그
overlays/prod/kustomization.yaml 에 resources: [../../base], namespace: cgoa-prod, namePrefix: prod-, replicas 로 checkout 을 3, images 로 ghcr.io/labhub/checkout 의 newTag 를 1.5.0 으로 지정하세요.
kustomize 에는 replicas 를 이름으로 지정해 바꾸는 필드와, 이미지 이름을 찾아 태그만 바꾸는 필드가 따로 있습니다. 패치 파일 없이 kustomization.yaml 안에서 끝낼 수 있습니다.
kubectl kustomize 로 렌더 결과 저장
kubectl kustomize /root/cgoa-repo/apps/checkout/overlays/prod 의 출력을 /root/cgoa-repo/render-prod.yaml 에 저장하세요.
kubectl kustomize <디렉터리> 는 오버레이를 적용한 최종 매니페스트를 표준 출력으로 뱉습니다. 클러스터에 적용하지 않고도 원하는 상태를 눈으로 볼 수 있습니다.
Argo CD Application 매니페스트
/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.
Application 은 source(어디서), destination(어디로), syncPolicy(어떻게) 세 덩어리입니다. 자동 동기화와 자기 치유, 그리고 네임스페이스 자동 생성 옵션이 어디에 들어가는지 확인하세요.
app-of-apps 루트 Application
/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).
루트는 자식 Application 파일들이 든 디렉터리를 source.path 로 가리키고, 그 디렉터리를 재귀적으로 읽도록 설정합니다. destination 은 Argo CD 자신이 사는 네임스페이스입니다.
AppProject 로 경계 긋기
/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.
AppProject 는 이 프로젝트의 Application 이 어떤 저장소에서, 어느 클러스터·네임스페이스로, 어떤 클러스터 스코프 리소스를 만들 수 있는지 제한합니다. 6 단계에서 만든 Application 의 project 값과 이름이 맞아야 합니다.