CGOA — GitOps 인증 어소시에이트 · 동기화 성공과 업무 복구 사이의 틈 · 이론
초록불 네 개가 답하는 서로 다른 질문
한 줄 요약
Git과 같다는 것, 쿠버네티스가 준비됐다는 것, 사용자의 요청이 성공했다는 것은 서로 다른 주장입니다.
왜 이게 필요했나
당직 채널에 “결제가 안 됩니다”라는 메시지가 왔습니다. 배포 화면에는 Synced와 Healthy가 보이고 Pod도 Ready입니다.
여기서 “인프라는 정상이니 사용자가 다시 시도하면 된다”고 답하면, 확인한 범위보다 큰 결론을 내린 것입니다.
화면의 초록색이 잘못됐다고 단정할 필요도 없습니다. 그 표시가 답하는 질문과 사용자가 하는 질문이 다를 수 있습니다.
이번 실습은 결제 시스템을 연결하지 않습니다. nginx의 업무 경로가 의도적으로 500을 반환하는 작은 모형으로
이 차이를 재현합니다. 실제 장애 대응처럼 보이게 만든 가짜 상태 파일이 아니라 개인 VM의 Argo CD와 HTTP 서버를 씁니다.
어떻게 동작하나
조사할 때는 다음 네 질문을 순서대로 분리하세요.
| 질문 | 확인할 근거 | 이것만으로 모르는 것 |
| --- | --- | --- |
| 어떤 변경을 배포하려 했는가 | 원격 main과 Git 커밋의 파일 | 컨트롤러가 그 커밋을 봤는가 |
| 그 목표가 클러스터에 반영됐는가 | Application의 sync revision과 Synced | 실행 중 프로세스가 새 설정을 읽었는가 |
| 리소스가 준비 조건을 충족하는가 | health, observedGeneration, updatedReplicas, Pod Ready | 업무 경로가 올바른 본문을 반환하는가 |
| 우리가 조사한 요청이 성공하는가 | 요청 경로·응답 코드·본문·관측 시각 | 외부 사용자 전체의 성공률과 장기 가용성 |
Argo CD의 기본 health 평가는 리소스 종류별 쿠버네티스 상태를 사용합니다. 예를 들어 Deployment의
현재 세대가 관측됐는지와 갱신된 복제본을 확인하는 것은 중요하지만, 쇼핑몰의 주문 의미까지 자동으로 알지는 못합니다.
Synced도 애플리케이션의 의미를 평가하는 기능이 아닙니다. 잘못된 설정을 Git에 저장했다면 그 설정을 충실하게
배포한 결과가 Synced일 수 있습니다. 따라서 GitOps의 선언적 관리와 좋은 애플리케이션 검증은 서로 대체하지 않습니다.
[공식 리소스 health 문서](https://argo-cd.readthedocs.io/en/stable/operator-manual/health/).
readiness는 이 Pod로 트래픽을 보낼 준비가 됐는지 판단하기 위한 신호입니다. 하지만 실제로 무엇을 검사하는지는
우리가 작성한 probe와 앱의 구현에 달려 있습니다. 실습의 /healthz는 프로세스가 응답한다는 뜻의 200만 냅니다.
업무 경로 /는 500을 냅니다. 이 설계는 일부러 불완전하며 운영 권장 probe가 아닙니다.
그렇다고 외부 결제 API가 잠깐 느릴 때 모든 Pod의 liveness가 실패하도록 바꾸면 해결되는 것도 아닙니다.
readiness의 전달 제어와 liveness의 재시작 판단은 다른 목적입니다. 외부 의존성 장애를 재시작으로 고칠 수 있는지
확인하지 않은 채 두 신호를 연결하면 복구 대신 재시작 부하를 만들 수 있습니다.
[공식 probe 개념](https://kubernetes.io/docs/concepts/workloads/pods/probes/).
현장에서 만나는 모습
첫 번째 함정은 커밋을 확인하지 않고 녹색 화면만 보는 것입니다. 방금 올린 변경이 아니라 이전 커밋의 Healthy를
보고 있을 수 있습니다. 로컬 HEAD, 서버의 원격 main, Application의 status.sync.revision을 함께 비교하세요.
브랜치 이름 main은 움직이는 이름이고, 커밋 SHA는 그 순간의 구체적인 소스입니다. push 명령이 끝났다는 사실은
배포 완료의 증거가 아닙니다. 실습에서는 refresh로 해당 Application의 재비교를 요청하지만, 그것도 성공 선언이
아니므로 실제 revision과 상태 수렴을 기다립니다. 전체 컨트롤러 설정이나 다른 Application은 바꾸지 않습니다.
두 번째 함정은 응답 코드만 남기는 것입니다. 200이더라도 오래된 본문이나 다른 버전의 응답일 수 있습니다.
서비스 주소, 경로, 본문, 시각을 함께 남기고 배포된 Pod의 UID와 연결하면 주장이 더 분명해집니다.
반대로 500은 서버가 HTTP 응답을 보냈다는 관측입니다. DNS 실패나 연결 실패를 같은 사건으로 뭉뚱그리지 마세요.
이 실습의 500은 nginx 설정으로 재현하므로 외부 API나 DNS 장애를 원인으로 적으면 관측과 맞지 않습니다.
실습은 VM에서 ClusterIP를 호출합니다. 이 경로의 성공만으로 외부 DNS·인그레스·TLS·인증이 정상이라고 말할 수
없습니다. 마지막 보고서에는 외부 경로 확인이 남아 있다는 결론을 적습니다. 짧은 시간에 세 번 성공했다는 결과를
한 달 가용성이나 실제 결제 성공률로 바꾸지 않는 것도 엔지니어의 검증 능력입니다.
다음 실습에서 할 것
첫 관측에서 Git revision과 리소스 신원을 보존하고, readiness와 업무 응답을 따로 읽습니다. 원인은 공개된 nginx
설정과 실제 응답으로 좁힙니다. 그 뒤 Git에서 설정을 고치되, 설정 수정만으로 기존 프로세스까지 바뀌었는지는
별도의 관측으로 확인합니다. 숫자나 UID를 꾸며 쓰지 말고 도우미가 남긴 실제 관측에서 조사하세요.