website: 배포 서버 Git 드리프트 감지 메트릭 추가
서버의 Git 파일 상태를 실시간으로 감지하여 배포 과정의 숨겨진 오류를 즉시 파악할 수 있는 메트릭을 추가했습니다.
요약
이번 커밋에서는 배포 서버에서 Git 상태 드리프트(직접 수정되거나 예상치 못한 파일의 등장)를 감지하는 파이썬 스크립트를 개발하여 OCI Monitoring 커스텀 메트릭으로 전송하도록 구현했습니다. 이 작업은 infra/push-git-drift-metric.py 파일에 91줄의 새로운 코드를 추가하는 것으로 이루어졌습니다. 이 메트릭은 서버 추적 파일이 예기치 않게 변경되거나 .gitignore에 포함되지 않은 새로운 파일이 생성될 경우, 5분 안에 이를 감지하여 CD 파이프라인의 잠재적인 실패를 조기에 인지하고 대응할 수 있도록 돕습니다.
배경 및 목적
최근 CD(Continuous Deployment) 파이프라인에서 간헐적으로 발생하는 무음 실패의 근본 원인을 파악하는 과정에서, 서버의 Git 워킹 디렉토리가 의도치 않게 변경되는 현상이 발견되었습니다. 특히, git pull 명령어가 untracked 파일과 경로가 겹쳐 조용히 실패함에도 불구하고 이를 인지하지 못해 배포가 3번이나 실패한 사례가 있었습니다. 이러한 문제를 해결하기 위해, 서버의 Git 상태에 드리프트가 발생하면 즉시 이를 감지하고 알림을 받을 수 있는 시스템이 필요했습니다. 이 메트릭을 통해 개발자는 배포 실패를 사전에 방지하고, 서버의 무결성을 유지할 수 있습니다.
구현 내용
새롭게 추가된 infra/push-git-drift-metric.py 스크립트는 배포 서버의 Git 상태를 주기적으로 확인하고, 변경 사항이 있을 경우 이를 OCI Monitoring 서비스로 전송하는 역할을 수행합니다.
주요 변경사항 상세 설명
git status --porcelain실행 및 분석: 스크립트는 현재 Git 저장소의 상태를--porcelain옵션을 사용하여 기계가 읽기 쉬운 형식으로 가져옵니다. 이 출력에서 변경되거나 추적되지 않는 파일의 수를 계산합니다.- OCI IMDS(Instance Metadata Service) 활용: 서버의 OCID와 Compartment ID를 하드코딩하는 대신, IMDS를 통해 런타임에 동적으로 조회합니다. 이는 보안을 강화하고, 인스턴스 교체 시 코드 수정의 필요성을 줄여줍니다.
- OCI Monitoring SDK 사용: Python용 OCI SDK를 사용하여 조회된 Git 상태 정보를
custom_likelion네임스페이스의GitDriftFileCount라는 커스텀 메트릭으로 OCI Monitoring 서비스에 게시합니다. - Instance Principals 인증:
push-disk-metric.py등 기존 스크립트와 동일한 IAM 설정을 재사용하여 별도의 자격 증명 없이 안전하게 메트릭을 전송합니다. - Cron 작업 예정: 이 스크립트는 cron 작업을 통해 5분마다 실행되도록 설정될 예정이며, 이를 통해 실시간에 가까운 Git 드리프트 감지가 가능해집니다.
변경된 파일 목록
infra/push-git-drift-metric.py
추가/삭제된 코드 라인 수
- 추가: 91 라인
- 삭제: 0 라인
핵심 코드 설명
# ... (import 및 네임스페이스/메트릭 이름 정의)
def dirty_file_count():
"""
Git 상태를 확인하여 변경되거나 추적되지 않는 파일의 수를 반환합니다.
"""
result = subprocess.run(
["git", "status", "--porcelain"],
cwd=REPO_DIR,
capture_output=True,
text=True,
check=True,
)
# --porcelain 출력에서 실제 내용이 있는 라인만 세어 0보다 큰지 확인
return len([line for line in result.stdout.splitlines() if line.strip()])
def main():
count = dirty_file_count()
instance_id, compartment_id = instance_metadata()
# OCI Monitoring 클라이언트 설정
signer = oci.auth.signers.InstancePrincipalsSecurityTokenSigner()
client = oci.monitoring.MonitoringClient(
config={},
signer=signer,
service_endpoint="https://telemetry-ingestion.ap-tokyo-1.oraclecloud.com",
)
# 메트릭 데이터 객체 생성
metric_data = oci.monitoring.models.MetricDataDetails(
namespace=NAMESPACE,
compartment_id=compartment_id,
name=METRIC_NAME,
dimensions={"resourceId": instance_id, "resourceDisplayName": "likelion-prod"},
datapoints=[
oci.monitoring.models.Datapoint(
timestamp=datetime.now(timezone.utc),
value=count,
)
],
)
# 메트릭 게시
client.post_metric_data(
post_metric_data_details=oci.monitoring.models.PostMetricDataDetails(
metric_data=[metric_data]
)
)
print(f"posted GitDriftFileCount={count}")
if __name__ == "__main__":
main()
이 코드 블록은 Git 상태를 확인하고 OCI Monitoring으로 메트릭을 전송하는 핵심 로직을 담고 있습니다. dirty_file_count 함수는 Git 상태를 파싱하여 변경된 파일 수를 계산하며, main 함수는 이 정보를 바탕으로 OCI SDK를 사용하여 메트릭 데이터를 게시합니다.
기술적 의사결정
이번 작업에서는 Git 상태를 파싱하기 위해 git status --porcelain 명령어를 사용했습니다. 다른 대안으로는 Git Python 라이브러리(예: GitPython)를 사용하는 방법도 고려할 수 있었습니다.
git status --porcelain명령어 사용:- 장점: 별도의 라이브러리 설치 없이 표준 Git 명령어를 활용하므로 환경 구성이 간편합니다. 출력 형식이 명확하고 기계가 읽기 쉬워 파싱이 용이합니다.
- 단점: Git 명령어가 실행되지 않는 환경에서는 사용할 수 없습니다.
GitPython라이브러리 사용:- 장점: Python 코드 내에서 Git 저장소를 직접 제어할 수 있어 더 추상화된 방식으로 Git 상태를 다룰 수 있습니다. Git 자체에 대한 깊은 이해 없이도 다양한 Git 기능을 활용할 수 있습니다.
- 단점: 별도의 라이브러리 설치가 필요하며, 의존성이 추가됩니다. 또한, 복잡한 Git 명령어 옵션을 일일이 매핑해야 할 수 있습니다.
결론적으로, 서버 환경에 이미 Git이 설치되어 있고, 단순히 git status의 결과를 파싱하는 것이 목적이었기 때문에, 별도의 라이브러리 의존성을 추가하지 않는 git status --porcelain 방식이 더 간결하고 효율적인 선택이라고 판단했습니다.
배운 점 및 개선점
이번 작업을 통해 배포 서버의 Git 상태를 실시간으로 모니터링하는 것이 CD 파이프라인의 안정성 확보에 얼마나 중요한지 다시 한번 깨달았습니다. 예상치 못한 파일 변경으로 인해 배포가 실패하는 상황을 미리 감지할 수 있다는 것은 매우 큰 이점입니다.
배운 점
- Git 상태를 효과적으로 파싱하기 위한
--porcelain옵션의 유용성 - OCI IMDS를 활용하여 민감한 정보를 안전하게 조회하는 방법
- OCI Monitoring SDK를 이용해 커스텀 메트릭을 생성하고 전송하는 방법
개선점 및 다음 단계
- 알림 시스템 연동: 현재는 메트릭만 전송되므로, 특정 임계값(예:
count > 0)을 초과할 경우 OCI 알림(Notifications) 서비스를 통해 Slack이나 이메일로 즉시 알림을 받을 수 있도록 설정해야 합니다. gitignore파일 관리:git status --porcelain은.gitignore에 명시된 파일은 추적하지 않습니다. 서버에서 관리되어야 하지만 Git 추적 대상에서 제외해야 하는 파일 목록(nginx.conf,.env*등)이 제대로 관리되고 있는지 주기적으로 점검해야 합니다.- 테스트 보강: 이 스크립트가 실제 드리프트 상황에서 제대로 동작하는지 다양한 시나리오에 대한 테스트를 추가하는 것이 좋습니다.