Skip to content

GSMSV 운영 컨테이너 상태 및 오류 로그 Discord 알림 구축 - #42

Open
exijn wants to merge 1 commit into
developfrom
ops/40-runtime-discord-alerts
Open

GSMSV 운영 컨테이너 상태 및 오류 로그 Discord 알림 구축#42
exijn wants to merge 1 commit into
developfrom
ops/40-runtime-discord-alerts

Conversation

@exijn

@exijn exijn commented Aug 31, 2026

Copy link
Copy Markdown
Member

✨ 작업 내용

GSMSV 운영 VM에서 컨테이너 상태·readiness·restart·ERROR 로그·디스크·메모리를 주기적으로 확인하고 Discord 장애/복구 알림을 보내는 systemd 감시 구성을 추가했습니다.


🔍 리뷰 시 참고사항

  • 관련 Issue: GSMSV 운영 컨테이너 상태 및 오류 로그 Discord 알림 구축 #40
  • 감시 대상은 Compose label로 식별하는 mudda-prod project의 app, postgres, redis입니다.
  • systemd oneshot service와 1분 주기 timer를 사용하며 자동 재시작·복구·volume 조작은 하지 않습니다.
  • health failure, 종료, restart 증가, readiness 실패와 자원 임계치를 구조화된 주요 신호로 사용하고 app ERROR 로그는 보조 신호로 사용합니다.
  • 동일 fingerprint는 기본 10분 억제하고, 최초 정상 알림은 생략하며 장애 정상화 시 복구 알림을 한 번 보냅니다.
  • webhook은 서버의 root:600 /etc/mudda/discord-alert.env에서만 읽습니다. GitHub Secret은 서버 프로세스에서 직접 읽지 않습니다.
  • 로그와 요약은 JSON 직렬화 전에 마스킹하고 약 2,500자 이내로 제한합니다.
  • 실제 Secret 등록, Discord 호출, systemd 설치·활성화, GSMSV 서버 접속은 수행하지 않았습니다.
  • 작업 A의 CD 파일에 의존하지 않으며 별도 worktree에서 독립적으로 구현했습니다.

변경 파일

  • ops/runtime/의 감시·알림·마스킹 스크립트, systemd unit/timer, 설치·제거 스크립트, fixture 테스트
  • ops/runtime/discord-alert.env.example
  • docs/GSMSV_RUNTIME_ALERTS.md

설계·보안

  • Docker socket과 root:600 webhook 파일 접근 때문에 service는 root로 실행하되 NoNewPrivileges, PrivateTmp, ProtectSystem, read-only 경로를 적용했습니다.
  • 감시 프로세스는 docker ps, docker inspect, docker logs, readiness GET, 시스템 지표 조회만 수행하며 restart, down, prune, volume 명령을 실행하지 않습니다.
  • flock과 atomic temp-file + mv로 동시 실행과 상태 갱신 race를 제어합니다.
  • webhook URL을 process argument나 로그에 출력하지 않으며, Webhook 오류는 URL 없이 상태만 기록합니다.

검증 결과

  • bash -n ops/runtime/*.sh ops/runtime/tests/test.sh: 통과
  • bash ops/runtime/tests/test.sh: 통과
  • fixture: 정상, app unhealthy, PostgreSQL 중지, Redis unhealthy, readiness 실패, restart 증가, ERROR, 디스크/메모리 임계치, 중복 억제, 복구, JSON 특수문자, 마스킹 확인
  • git diff --check: 통과
  • systemd-analyze: 로컬 Windows 환경에 명령이 없어 실행하지 못함
  • shellcheck: 설치되어 있지 않아 실행하지 못함
  • ./gradlew test: JDK 25/전역 JDK 26 설정 및 Kotlin DSL 호환 오류가 있었고, JDK 23 재시도는 Docker/Testcontainers 환경에서 중단됨
  • 실제 Docker·Webhook·systemd 운영 통합 검증: Secret과 GSMSV 서버가 없어 실행하지 않음

자체 코드 리뷰

  • 1차: webhook·로그 Secret 노출, shell·JSON injection, Docker socket 권한, 상태 race, 중복 알림 폭주, 운영 컨테이너 영향 여부를 확인했고 요약 필드 마스킹을 보강했습니다.
  • 2차: 저장소 규칙, 작업 A와의 파일 충돌, 설치·제거 문서, fixture 정책 검증, 임시 파일·Secret 포함 여부를 확인했고 추가 수정 사항 없음.

설치 전 사용자 작업

  • 서버에서 설치 스크립트를 root로 실행
  • /etc/mudda/discord-alert.env에 실제 webhook을 직접 입력하고 root:600 권한 유지
  • Docker socket 접근 정책과 systemd timer를 검토한 뒤 enable

제외 범위 및 후속 작업

  • 실제 Secret/서버 설치·배포, 자동 복구, PostgreSQL 백업
  • Loki/Grafana 모니터링 스택
  • 작업 A의 CD 구현 자체
  • 후속으로 전체 로그 보관이 필요하면 Loki/Grafana, 데이터 보호가 필요하면 PostgreSQL 백업을 별도 작업으로 진행

✅ 체크리스트

  • 문서(README, .env.example 등) 변경이 필요한 경우 작성 또는 수정했나요?
  • 작업한 코드가 정상적으로 동작하는 것을 직접 확인했나요?
  • 필요한 경우 테스트 코드를 작성하거나 수정했나요?
  • Merge 대상 브랜치를 올바르게 설정했나요? (develop)
  • PR에 관련 없는 작업이 포함되지 않았나요?
  • 적절한 라벨과 리뷰어를 설정했나요? (🌏 Deploy, 리뷰어는 지정하지 않음)

📎 관련 이슈(선택)

@exijn exijn added the 🌏 Deploy 배포 관련 label Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🌏 Deploy 배포 관련

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant