CGOA — GitOps 인증 어소시에이트 · 자동화를 끄는 위치: 부모와 자식의 조정 루프 · 이론
같은 설정을 다시 쓰는 두 조정기
한 줄 요약
ApplicationSet이 만든 Application을 직접 고치면 부모가 다시 맞출 수 있습니다. 작업을 멈추려면 누가 그 필드를 소유하는지부터 확인해야 합니다.
왜 이게 필요했나
장애를 조사하려고 자동 동기화를 껐습니다. 화면에서 꺼진 것을 확인하고 잠시 자리를 비웠는데 다시 켜져 있습니다.
다른 동료가 켰다고 생각해 물어보지만 아무도 만지지 않았다고 합니다. 컨트롤러를 재시작하거나 같은 버튼을
여러 번 눌러도 문제를 설명할 수 없습니다. 설정을 바꾼 대상이 최상위 원본이 아니었을 수 있기 때문입니다.
GitOps의 조정 루프는 하나만 있는 것이 아닙니다. Application controller는 Application이 지정한 Git 목표를
실제 리소스에 맞춥니다. ApplicationSet controller는 generator와 template로 만든 Application의 목표를
실제 Application 객체에 맞춥니다. 운영자가 자식 Application의 자동화 필드를 바꾸면 두 번째 루프가 그것을
드리프트로 보고 복원할 수 있습니다. Git에서 읽은 ConfigMap을 고친 것과 Application 자체를 고친 것은
서로 다른 층의 변경입니다.
어떻게 동작하나
이번 실습에서는 list generator에 alpha 한 항목만 둡니다. 서비스 수를 늘리는 실습이 아니라 소유 관계를
좁혀 관측하는 실습입니다. ApplicationSet 템플릿은 alpha의 Application을 만들고, 그 Application은 내부
Git의 apps/alpha 디렉터리를 읽어 작은 ConfigMap을 만듭니다. 비교 대상으로 독립 Application과 별도
ConfigMap도 둡니다. 독립 대상까지 함께 바뀌면 범위를 잘못 잡은 것입니다.
| 조정기 | 목표를 읽는 곳 | 바꾸는 대상 | 유지보수 때 묻는 질문 |
| --- | --- | --- | --- |
| ApplicationSet controller | generator와 template | Application의 설정 | 누가 이 자동화 값을 다시 쓰는가? |
| Application controller | Application이 지정한 Git | ConfigMap 같은 실제 리소스 | 어느 Git 커밋을 실제로 적용하는가? |
ownerReferences는 첫 번째 관계의 중요한 단서입니다. 자식 Application의 ownerReferences에서 kind,
name, uid, controller를 확인하면 어느 ApplicationSet에 연결됐는지 알 수 있습니다. 이름만 비교하면
같은 이름으로 다시 만든 부모를 놓칠 수 있으므로 UID도 함께 대조합니다. ConfigMap은 Argo CD의 추적
주석을 읽어 어느 Application이 관리하는지 구별합니다. 이 두 종류의 소유 정보를 같은 것으로 취급하지 마세요.
자동 동기화를 명시적으로 끄는 값은 spec.syncPolicy.automated.enabled의 false입니다. null이나 필드
누락을 false와 같은 뜻으로 읽으면 안 됩니다. prune와 selfHeal이 true여도 enabled=false이면 자동
동기화가 꺼진 상태입니다. 이번 환경은 enabled를 항상 불리언으로 명시하여 기본값의 추측을 피합니다.
자식에 enabled=false를 썼을 때 API가 그 변경을 받아들였다는 것과 그 상태가 유지된다는 것도 다릅니다.
실습은 patch 응답의 false와 resourceVersion을 먼저 보존하고, 뒤 관측에서 같은 Application UID의
enabled가 true로 되돌아온 것을 확인합니다. 처음부터 false가 반영되지 않은 요청을 복원 실험이라고
부르지 않기 위해서입니다. resourceVersion은 관측 버전을 구별하는 불투명 문자열이며 시간이나 전역 순번을
계산하는 숫자로 쓰지 않습니다.
부모 템플릿에서 enabled=false를 선언하면 생성될 자식의 목표 자체가 바뀝니다. 자식의 false가 이제는
부모와의 차이가 아니므로 유지될 수 있습니다. 템플릿은 여러 자식에 공통으로 적용될 수 있으므로, 실제
팀 환경에서는 변경 전에 generator 결과와 영향을 받는 Application 목록부터 확인해야 합니다.
실습은 자식 한 개로 그 범위를 한정하지만 이 사실을 대규모 운영에서도 한 개만 바뀐다는 뜻으로 일반화하지 않습니다.
현장에서 만나는 모습
개발 환경은 자동 배포하고 검증 환경은 수동 확인 후 배포하는 조직을 생각해 보세요. 한 템플릿을 모든
환경에 적용한 뒤 검증 환경에서만 버튼으로 꺼 두면 원본과 실제 상태가 충돌합니다. 팀이 보장하려는
운영 방식을 템플릿이나 명시적인 예외 정책으로 표현해야 합니다. 누군가 기억해서 매번 다시 끄는 절차는
원하는 상태의 선언이 아니라 반복되는 수작업입니다.
조사할 때는 다음처럼 서로 다른 층의 문서를 읽습니다. 모두 개인 실습 VM 안에서 실행할 명령입니다.
kubectl -n argocd get applicationset cgoa-appset-ownership -o jsonkubectl -n argocd get application cgoa-appset-ownership-alpha -o jsonkubectl -n cgoa-appset-ownership get configmap alpha-config -o json첫 문서에서는 template와 generator, 둘째에서는 ownerReferences와 자동화 정책, 셋째에서는 실제 데이터를
보세요. 자동화가 꺼졌다는 설명 한 줄만으로 어느 조정 루프가 멈췄는지 알 수 없습니다.
다음 실습에서 할 것
먼저 API가 자식의 변경을 받아들인 기록과 부모가 되돌린 기록을 비교합니다. 다음으로 부모 템플릿을 고치고
자식의 설정과 Git 변경의 적용 여부를 따로 봅니다. ApplicationSet 자체는 실습의 부트스트랩 선언 파일을
도우미가 적용하며, 상위 Application이 그것까지 Git에서 조정하는 세 번째 루프는 이번 범위에 넣지 않습니다.
이 경계를 명시해야 실습에서 직접 적용한 선언과 운영의 전체 GitOps 배선을 혼동하지 않습니다.
공식 문서
- [ApplicationSet 변경 제어](https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/Controlling-Resource-Modification/): 자식 변경과 예외 규칙을 구별하세요.
- [자동 동기화](https://argo-cd.readthedocs.io/en/stable/user-guide/auto_sync/): enabled의 true·false·null 의미를 확인하세요.