LabHub
배우기 러닝패스 코스

CGOA — GitOps 인증 어소시에이트 · 삭제도 배포다: 보존과 승인 사이의 경계 · 이론

Git에서 지운 것과 실제로 사라진 것

LabHub 에서 이어서 보기

한 줄 요약

Git에서 지운 것은 삭제 의도이고, 실제 삭제 여부는 자동 prune 정책과 객체별 보호 규칙, 승인에 달려 있습니다.

왜 이게 필요했나

배포 저장소에서 쓰지 않는 설정 파일을 정리했습니다. 리뷰에는 파일 하나 삭제라고 표시됩니다.
그런데 그 파일이 Namespace나 영속 데이터의 연결을 정의했다면 리뷰의 작은 차이가 운영에서는 큰 삭제가 됩니다.
GitOps의 장점인 지속적인 조정은 생성과 수정에만 적용되지 않습니다. 삭제도 원하는 상태를 맞추는 동작입니다.
반대로 Git에서 사라진 모든 객체를 영원히 남기면 쓰지 않는 자원이 쌓이고 책임자가 누구인지 알기 어려워집니다.
필요한 것은 삭제를 전부 끄는 것이 아니라 무엇을 자동으로 지우고 무엇을 검토 뒤에 지울지 정하는 기준입니다.

이 실습은 실제 데이터를 쓰지 않습니다. disposable-exercise라는 짧은 값을 담은 ConfigMap으로 수명주기를 재현합니다.
운영과 같은 판단 구조를 배우되 데이터 손실의 대가는 만들지 않기 위한 선택입니다. 실제 PVC의 보존·복원까지
시험했다고 해석하면 안 됩니다. 같은 이름의 YAML을 다시 적용할 수 있다는 것과 데이터를 복구할 수 있다는 것은 다릅니다.

어떻게 동작하나

먼저 세 대상을 분리합니다. Git 디렉터리는 희망 상태를 담고, Application은 어느 디렉터리를 어느 클러스터에
적용할지 지정하며, ConfigMap은 그 결과로 생성된 실제 객체입니다. Git 경로에서 객체를 없애는 prune와
Application 자체를 삭제할 때 따라오는 자원 정리는 서로 다른 사건입니다.

자동 동기화를 켰다고 자동 삭제까지 켜지는 것은 아닙니다. Application의 automated.prune가 삭제 자동화를
결정합니다. 이 실습은 그 값을 true로 두고 객체별 옵션을 비교합니다. 다음 표의 핵심은 서로 다른 상태 열을
한 단어인 성공으로 압축하지 않는 것입니다.

| Git에서 제거한 객체 | 실제 객체 | sync.status | operationState.phase |
| --- | --- | --- | --- |
| 별도 보호가 없는 normal | 삭제됨 | Synced | Succeeded |
| Prune=false인 retained | 남음 | OutOfSync | Succeeded가 될 수 있음 |
| Prune=confirm인 confirmed, 승인 전 | 남음 | OutOfSync | Running |
| confirmed, 승인 후 | 삭제됨 | Synced | Succeeded |

Prune=false는 삭제 작업을 건너뛰게 합니다. Argo CD가 원래 하려던 삭제는 남아 있으므로 희망 상태와 실제 상태는
다릅니다. 그렇다고 조정기가 고장 난 것은 아닙니다. 이때 syncResult의 해당 객체에는 PruneSkipped가 남습니다.
보호된 객체가 남는 이유를 파악한 뒤 Git에 정의를 되돌리면 같은 UID인 채 다시 Synced가 될 수 있습니다.
OutOfSync를 없애겠다고 실제 객체를 수동 삭제하면 보호 규칙의 목적부터 깨뜨리게 됩니다.
이 복원은 이미 남아 있던 실제 객체와 Git을 다시 일치시키므로 새 동기화 작업이 필요 없을 수도 있습니다.
따라서 현재 sync.revision과 Synced, 동일 UID를 확인하며 새 operation 생성 자체를 성공 조건으로 요구하지 않습니다.

Prune=confirm은 검토가 필요한 삭제를 보류합니다. 이때 Running은 무한 장애라는 뜻이 아니라 승인 대기일 수
있습니다. 기다리는 원인은 operationState.message와 삭제 예정 리소스 목록에서 확인합니다.
승인은 Application의 argocd.argoproj.io/deletion-approved 주석에 시각을 기록하는 방법으로도 수행할 수 있습니다.
중요한 점은 승인 표시가 ConfigMap 한 개가 아니라 Application에 붙는다는 것입니다. 검토한 것 이외에
다른 삭제 대상이 함께 생겼다면 예전의 판단을 그대로 적용할 수 없습니다.

Delete=false는 이름이 비슷하지만 Application 삭제 시의 정리에 관한 옵션입니다. Git에서 리소스를 제거하는
prune의 대체 이름이 아닙니다. 운영 문서를 쓸 때는 삭제라는 단어 뒤에 주어를 붙이세요.
Git에서 무엇을 제거했는지, Application을 지우는지, 실제 객체를 직접 지우는지부터 구분해야 옵션도 맞게 고릅니다.

현장에서 만나는 모습

팀이 설정 소유권을 다른 저장소로 이전할 때 이전 Application의 Git 정의를 먼저 제거하면 자동 prune가 먼저
객체를 지울 수 있습니다. 보호 옵션 하나를 복사하는 것만으로 이전 설계가 완성되는 것은 아닙니다.
이전과 새 소유자의 범위, 같은 객체를 두 조정기가 동시에 관리하는 기간, 실패하면 어느 원본으로 돌아갈지까지
정해야 합니다. 이 단원의 두 Application은 서로 다른 ConfigMap을 관리하여 그런 이중 소유를 만들지 않습니다.

증거를 읽을 때는 이름과 UID를 같이 보세요. Kubernetes에서 같은 이름으로 새 객체를 만들 수 있으므로 이름이
같다는 이유로 보존됐다고 판정할 수 없습니다. 반대로 Git 커밋이 바뀌었다고 객체도 새로 생긴 것은 아닙니다.
다음처럼 실제 상태와 원하는 상태의 좌표를 나란히 남기는 습관이 도움이 됩니다.

git -C /srv/cgoa-prune-safety rev-parse HEADkubectl -n argocd get application cgoa-prune-safety -o jsonkubectl -n cgoa-prune-safety get configmaps -o json

여기서 읽을 것은 커밋 SHA, source.path, destination.namespace, sync.revision, 삭제 예정 목록과 UID입니다.
각각의 뜻을 설명하지 못한 채 출력 전체를 보고서에 붙이는 것은 검증을 대신하지 못합니다.

다음 실습에서 할 것

일반 삭제, 삭제 보존, Git 복원, 승인 대기를 직접 만들고 확인합니다. 승인 단계에서는 앞 관측의 Application UID와
대상 ConfigMap UID를 답안에 적습니다. 도우미는 지금의 대상과 다르면 멈춥니다. 이 제한은 잘못된 범위에 대한
학습 중 실수를 막는 장치이며 관리자 root의 모든 조작을 차단한다는 보안 보증은 아닙니다.

공식 문서