Skip to content

feat: MySQL 백업 실패 알림을 위한 내부 전용 Discord 알림 API 구현 #832

Description

@Hexeong

어떤 기능인가요?

Prod MySQL의 S3 백업이 실패하거나 지연될 때, DB EC2가 API 서버의 내부 전용 API로 이벤트를 전달하고 서버가 Discord Webhook을 호출해 알리는 기능을 구현합니다.

인프라 저장소 solid-connection-infra#66의 남은 작업 중 서버 측 구현에 해당합니다. 백업 파이프라인 자체는 solid-connection-infra#71에서 구성되었습니다.

배경

Prod DB는 RDS에서 EC2의 MySQL 8.4.8 컨테이너로 전환되었고, 일 1회 mysqldump와 5분 주기 binlog를 S3에 백업합니다. 목표 RPO는 5분입니다.

DB EC2가 Discord를 직접 호출할 수 없습니다. DB EC2는 private subnet에 있고 해당 서브넷의 라우팅 테이블에는 local과 S3 Gateway Endpoint만 있어 NAT나 IGW를 통한 아웃바운드 경로가 없습니다. 따라서 인터넷 접근이 가능한 API EC2를 경유해야 합니다.

DB EC2 (private, 인터넷 경로 없음)
└─ 백업 실패/지연 감지
   └─ POST → API EC2 (내부 전용 경로)
      └─ Spring → Discord Webhook

알림이 필요한 이벤트

  • mysqldump 실패
  • binlog 업로드 실패
  • binlog 누락(번호 불연속) 또는 역행 감지
  • 마지막 binlog 업로드 성공이 5분을 초과

작업 상세 내용

알림 전송

  • Discord Webhook 호출 컴포넌트를 구현합니다. 기존 RestTemplateConfig와 OAuth 클라이언트 패턴을 따릅니다.
  • Webhook URL은 AWS Parameter Store(/solid-connection/{env}/)에서 주입합니다. 코드와 저장소에 값을 포함하지 않습니다.
  • 이벤트 종류와 심각도에 따라 Discord 메시지 형식을 정의합니다.
  • 연결·읽기 타임아웃과 재시도 정책을 정의합니다.
  • Discord 호출 실패가 요청 처리 자체를 실패시키지 않도록 처리하고, 실패는 로그로 남깁니다.

내부 전용 API

  • 백업 이벤트를 수신하는 POST 엔드포인트를 구현합니다.
  • 요청 본문 스펙을 정의합니다. 이벤트 종류, 심각도, 발생 시각, 대상 인스턴스, 메시지를 포함합니다.
  • 요청 값을 검증하고, 알 수 없는 이벤트 종류는 거부합니다.
  • 동일 이벤트가 반복 전달될 때 Discord로 중복 발송되지 않도록 억제 정책을 정의합니다.

접근 제어

현재 SecurityConfiguration/connect/**/admin/**을 제외한 모든 요청이 permitAll()입니다. 경로를 추가하는 것만으로는 외부에서 호출할 수 있으므로 애플리케이션 레벨 방어가 필요합니다.

  • SecurityConfiguration에 이 경로의 접근 정책을 명시합니다.
  • 공유 시크릿 헤더 등 호출자 인증 수단을 적용하고, 값은 Parameter Store에서 주입합니다.
  • 인증 실패 시 응답으로 내부 구조가 드러나지 않도록 합니다.
  • 알림 API 경로가 Swagger 등 공개 문서에 노출되지 않는지 확인합니다.

테스트

  • 이벤트 수신부터 Discord 호출까지의 단위 테스트를 작성합니다.
  • 호출자 인증 실패, 잘못된 본문, Discord 호출 실패 상황을 검증합니다.

인프라 저장소에서 진행할 연계 작업

  • Nginx에서 알림 경로가 외부로 공개되지 않도록 차단합니다.
  • Blue/Green 배포의 활성 upstream으로 요청이 전달되도록 구성합니다.
  • DB EC2의 백업 스크립트에서 실패 시 이 API를 호출하도록 연동합니다.

완료 조건

  • 백업 실패와 지연 이벤트가 Discord 채널로 전달됩니다.
  • Webhook URL과 호출자 인증 값이 저장소와 코드에 포함되지 않습니다.
  • 알림 API가 외부에서 호출되지 않습니다.
  • Discord 호출이 실패해도 서버의 다른 기능에 영향이 없습니다.

참고할만한 자료(선택)

남은 논의 사항

  • DB EC2가 살아 있어야만 이 경로가 동작합니다. EC2 자체 장애나 네트워크 단절은 감지할 수 없으므로, S3의 마지막 객체 시각을 외부에서 관찰하는 freshness 모니터링이 별도로 필요합니다. 해당 작업의 범위와 저장소를 정해야 합니다.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions