LabHub

CGOA — GitOps 인증 어소시에이트 · GitOps 원칙과 용어 · 이론

시험이 쓰는 단어들 — 그리고 CI 와 CD 의 경계가 어디로 옮겨갔나

LabHub 에서 이어서 보기

한 줄 요약

CGOA 는 실기가 없는 대신 단어를 정확히 쓰는지 를 봅니다. desired state, actual(live) state, drift, reconciliation, convergence 는 서로 바꿔 쓸 수 있는 말이 아니라 하나의 루프를 이루는 다섯 개의 다른 자리입니다.

왜 이게 필요했나

현업에서는 "싱크 돌렸어요", "안 맞아요" 같은 말로도 대화가 됩니다. 그런데 시험 문제는 "다음 중 drift 를 가장 잘 설명한 것은?" 처럼 물어보고, 보기 넷 중 셋이 그럴듯합니다. Deviation, Delta, Divergence 같은 단어가 오답으로 깔립니다. 정의를 대충 알면 반드시 틀립니다.

어떻게 동작하나

한 바퀴를 순서대로 따라가 보면 이렇습니다.

1. Desired state(원하는 상태) — Git 에 선언된, 시스템이 도달해야 할 목표. 렌더링 결과까지 포함합니다. Helm 차트나 kustomize 오버레이는 "원하는 상태를 생성하는 재료"이고, 원하는 상태 자체는 그걸 렌더한 최종 매니페스트입니다.
2. Actual state / Live state(실제 상태) — 클러스터 API 서버가 지금 들고 있는 오브젝트.
3. Drift(드리프트) — 이 둘의 차이. 누가 kubectl edit 을 했거나, 컨트롤러가 필드를 바꿨거나, 앞의 sync 가 중간에 실패했을 때 생깁니다.
4. Reconciliation(조정) — 차이를 발견하고 실제 상태를 원하는 상태 쪽으로 밀어 넣는 행위.
5. Convergence(수렴) — 그 결과 둘이 같아진 상태. 한 번에 되지 않을 수 있고, 여러 루프를 돌아 결국 같아지면 그것을 eventual consistency 라고 부릅니다.

여기에 두 단어가 더 붙습니다. State store 는 원하는 상태를 담는 버전 관리 시스템(보통 Git)이고, Software agent 는 조정을 수행하는 클러스터 안의 프로세스(Argo CD, Flux)입니다. OpenGitOps 문서가 이 두 단어를 도구 이름 대신 쓰는 이유는, GitOps 가 특정 제품에 묶인 개념이 아니라는 걸 분명히 하기 위해서입니다.

CI 와 CD 의 경계는 어디로 갔나

전통적 CI/CD 에서 경계는 "테스트가 끝나는 지점"이었습니다. GitOps 에서는 경계가 저장소 사이 로 옮겨갑니다.

[앱 저장소]  코드 커밋 → 빌드 → 테스트 → 이미지 푸시 → (설정 저장소에 태그 커밋)                                                          |                                                          | ← 여기가 CI 의 끝                                                          |[설정 저장소]  PR 리뷰 → 머지 → (에이전트가 당겨감) → 클러스터                                  ↑ 여기부터가 CD

CI 의 산출물은 더 이상 "배포"가 아니라 커밋 입니다. CD 는 사람이 트리거하는 작업이 아니라 항상 돌고 있는 루프입니다. 그래서 GitOps 에서 "배포 실패"와 "동기화 실패"는 다른 사건이고, 롤백도 파이프라인 재실행이 아니라 git revert 로 합니다. revert 는 이력을 지우지 않고 새 커밋을 쌓기 때문에 불변성 원칙과도 맞습니다.

한 가지 자주 나오는 함정: 웹훅은 필수가 아닙니다. 웹훅이 없어도 에이전트는 폴링 주기마다 Git 을 확인하므로 결국 수렴합니다. 웹훅은 그 지연을 줄이는 최적화일 뿐, 웹훅이 없으면 GitOps 가 아니라는 말은 틀립니다.

현장에서 만나는 모습

저자의 홈랩에서 실제로 겪은 장면 하나. KubeVirt 를 올렸을 때 모든 컴포넌트 상태가 AllComponentsReady 였는데 VM 은 뜨지 않았습니다. virt-launcher 파드 명세를 뜯어보니 init 컨테이너가 쓸 바이너리 볼륨 마운트가 빠져 있었습니다. 같은 클러스터에서 이런 종류의 사건을 세 번째 겪었다고 기록돼 있습니다.

이게 용어와 무슨 상관이냐면 — Sync 상태와 Health 상태는 다른 축 이기 때문입니다. Argo CD 도 Synced(원하는 상태와 실제 오브젝트가 같다)와 Healthy(그 오브젝트가 실제로 제 일을 한다)를 따로 보여줍니다. Synced 인데 Degraded 인 앱은 흔합니다. Git 이 시킨 대로 정확히 만들었는데 그 명세 자체가 틀린 경우니까요. 시험에서 "OutOfSync 인데 Healthy 일 수 있는가?" 를 물으면 답은 예입니다. 두 축은 독립입니다.

다음 퀴즈에서 확인할 것

다음 모듈에서 저장소 구조를 잡습니다. desired state 를 "어느 디렉터리에 어떤 모양으로 두는가"가 곧 저장소 전략이고, 환경 승격은 그 구조 위에서 이미지 태그 한 줄을 옮기는 PR 로 정리됩니다.