LabHub
배우기 러닝패스 코스

CGOA — GitOps 인증 어소시에이트 · 동기화 성공과 업무 복구 사이의 틈 · 이론

설정은 바뀌었는데 프로세스는 왜 그대로일까

LabHub 에서 이어서 보기

한 줄 요약

설정을 저장한 위치뿐 아니라 프로세스가 그 설정을 언제 소비하는지 알아야 복구가 끝납니다.

왜 이게 필요했나

업무 경로가 500을 내는 설정을 찾았습니다. Git에서 200으로 고쳤고 Argo CD도 새 커밋에 Synced입니다.
쿠버네티스 API로 ConfigMap을 읽으면 분명히 새 값이 있습니다. 그런데 curl은 계속 500을 받습니다.
이때 “GitOps가 말을 안 듣는다”며 Pod를 지우면 잠깐은 문제가 사라질 수 있습니다. 하지만 어떤 설정이
어떤 과정으로 프로세스에 전달됐는지 놓치면 다음 변경에서 같은 장애를 반복합니다.
원본·전달된 파일·실행 중 프로세스라는 세 층을 먼저 나눠 봅시다.

어떻게 동작하나

ConfigMap은 쿠버네티스 API에 저장된 설정 데이터입니다. 소비 방식에 따라 갱신 동작이 다릅니다.
환경변수로 주입한 값은 기존 프로세스의 환경변수를 자동으로 갈아 끼우지 않습니다. 일반 볼륨으로 투영한 파일은
갱신될 수 있지만 전파에 시간이 걸릴 수 있습니다. 파일이 바뀌더라도 애플리케이션이 다시 읽는지는 별도 문제입니다.
특히 이번처럼 subPath로 파일 하나를 마운트한 컨테이너는 ConfigMap의 후속 갱신을 받지 않습니다.
“ConfigMap은 자동 갱신된다”라는 문장을 소비 방식을 생략한 채 외우면 바로 이 실험에서 틀립니다.
[공식 ConfigMap 갱신 조건](https://kubernetes.io/docs/concepts/configuration/configmap/).

이번 Deployment는 nginx.conf 한 파일을 /etc/nginx/nginx.conf에 subPath로 마운트합니다.
첫 설정 커밋은 ConfigMap의 nginx.conf만 고칩니다. Deployment의 spec.template은 보존합니다.
따라서 새 Pod가 만들어질 이유가 없습니다. 이전 Pod UID와 컨테이너가 남고, 컨테이너 안에서 읽은 파일도 이전 값이며
HTTP 응답도 여전히 500입니다. 이는 단순히 “캐시가 느려서 그렇다”고 추측한 결과가 아니라 파일과 신원의 비교로
확인한 전달 경계입니다. 무작정 sleep 시간을 늘리는 것이 이 소비 방식을 바꾸지는 않습니다.

두 번째 커밋은 새 설정 바이트의 SHA-256을 계산하여 Pod 템플릿의 checksum/config 주석에 넣습니다.
이 주석 이름에 쿠버네티스 내장 마법이 있는 것은 아닙니다. spec.template의 값이 달라져 Deployment가 새
ReplicaSet과 Pod를 만들도록 하는 규약입니다. 체크섬을 Deployment 최상위 metadata에만 붙이면 템플릿이
바뀌지 않으므로 같은 효과를 얻을 수 없습니다. 새 Pod는 현재 ConfigMap으로 마운트를 만들고 nginx를 시작합니다.
ConfigMap만 바꾼 커밋과 템플릿까지 바꾼 커밋을 분리하면 이 차이를 눈으로 따라갈 수 있습니다.
[공식 Deployment 갱신](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/).

체크섬은 문자열을 눈대중으로 적는 값이 아닙니다. 실제 설정 바이트를 계산해야 하며 마지막 줄바꿈 유무도
결과를 바꿉니다. 이번 도우미는 저장한 ConfigMap 관측의 nginx.conf 값을 그대로 인코딩해 계산합니다.
실제 운영에서는 설정 파일·템플릿 생성 파이프라인이 같은 규칙을 공유해야 합니다. 다른 파일의 체크섬이나
임의의 타임스탬프도 롤아웃을 유발할 수 있지만, 그것은 우리가 어떤 설정을 배포했는지 설명하는 근거가 아닙니다.

현장에서 만나는 모습

응급조치와 영구 복구를 구분해야 합니다. 수동으로 Pod를 지워 새 설정을 읽게 할 수 있더라도 그 조치는
원하는 배포 상태와 변경 의도를 Git에 남기지 않습니다. selfHeal이 켜진 리소스의 직접 수정은 Git의 상태로
다시 조정될 수 있습니다. 이번 실습에서는 플랫폼 운영 설정을 바꾸지 않고 학생 전용 저장소의 두 커밋으로
복구 과정을 남깁니다. 자동 동기화가 모든 잘못된 설정을 고치는 기능은 아니며, 사람의 검토와 테스트가 필요합니다.
[공식 자동 동기화](https://argo-cd.readthedocs.io/en/stable/user-guide/auto_sync/).

롤아웃 완료 확인에도 이름만으로는 부족합니다. 새 Pod의 UID는 바뀌어야 하지만 Application과 Deployment는
같은 UID를 유지해야 합니다. 이전 Pod를 지웠다가 같은 이름으로 자원을 통째로 다시 만든 것은 같은 복구 과정이
아닙니다. 원하는 템플릿의 체크섬, observedGeneration, updatedReplicas, Ready, 새 Pod 안의 파일, 실제 응답을
함께 확인해야 “새 설정을 읽은 새 프로세스가 응답했다”는 주장을 할 수 있습니다.

실습의 단계별 JSON은 보고서 작성 편의를 위한 학습 자료입니다. 원자료와 해시를 보존하여 실수로 이전 관측을
덮어쓰면 실패하도록 했지만, 같은 VM의 root가 모든 파일을 바꿀 수 있다는 한계는 남습니다. 해시가 있다는 이유로
원격 증명이나 위변조 불가능한 감사 시스템이라고 부르지 않습니다. 운영 감사라면 신뢰 경계 밖으로 보내는 로그와
접근 제어, 보존 정책을 별도로 설계해야 합니다.

다음 실습에서 할 것

설정 변경 전후와 템플릿 변경 후를 각각 보존합니다. 가운데 관측의 ConfigMap은 새 값인데 마운트 파일과 응답은
옛 값인지 조사하세요. 마지막으로 Git 커밋의 부모 관계까지 따라가며 두 변경을 구분하고, 새 Pod의 200 응답을
확인합니다. 과거 단계 재채점은 과거 기록을 읽어야지 장애를 다시 주입해서는 안 됩니다. 현재 상태 확인도 함께
통과했을 때 조사 범위 내 복구를 선언하고, 외부 경로 및 지속 관측은 남은 작업으로 기록합니다.