Dev/Prod 환경 로그 & DB 백업 자동화 적용하기

2025. 8. 13. 23:56·YAPP

현재 상황

저희 서비스는 Dev 환경과 Prod 환경을 분리해서 배포하고 있으며, 각 환경마다 독립적인 데이터베이스를 운영하고 있습니다.

  • Dev 환경: EC2 인스턴스에서 Spring과 MySQL을 컨테이너로 운영
  • Prod 환경: RDS를 활용한 관리형 데이터베이스 사용

또한 이전 포스트모템 과정에서 각 환경의 Spring 컨테이너에 Datadog을 연동해놨기 때문에, 현재 모든 애플리케이션 로그는 Datadog을 통해 수집되고 모니터링되고 있는 상황입니다.


문제점

Datadog 의존성 문제

가장 먼저 떠오른 의문은 "Datadog이 우리 로그를 언제까지 보관해줄까?" 였습니다.

현재 팀원이 보유한 Datadog 학생 계정 라이센스를 통해 Pro 기능을 무료로 사용하고 있습니다. 하지만 트레이스는 최근 15분, 로그는 30일 정도만 보관되고 그 이후에는 삭제됩니다.

실제 서비스를 배포한 후에도 이런 짧은 보관 기간과 외부 서비스 의존성만으로는 장기적인 로그 분석이나 문제 추적에 한계가 있을 것이라 판단했습니다.


Dev 환경 데이터 휘발성 문제

Dev 환경의 경우 초기 더미 데이터가 대부분이지만, 새로운 기능 개발이나 UT 진행 과정에서 생성된 실제 데이터들이 남아있는 경우가 있었습니다.

문제는 DB 테이블이나 값이 변경되거나 API 스펙이 변경되면서 기존 데이터와 호환되지 않는 상황이 발생한다는 점이었습니다.

현재 Flyway를 통해 마이그레이션 기록을 남기고 있지만, 때로는 데이터를 완전히 초기화해야 하는 경우도 생기곤 했습니다.

 

더하여 인프라 변경으로 인한 Dev 인스턴스 교체 상황입니다. 인스턴스가 종료되면 EBS도 함께 반납하게 되는데, 이때 컨테이너로 운영 중인 MySQL의 모든 데이터가 사라져버리는 문제가 있었습니다.

결국 로그 백업과 Dev 환경 DB의 정기적인 백업이 모두 필요하다는 결론에 도달했습니다.


해결 방안

백업 문제를 해결하기 위해 여러 방법을 검토해봤습니다.

1. EBS 스냅샷 + Glacier 보관

EBS 전체를 스냅샷으로 백업하고 Glacier 같은 저비용 스토리지에 보관하는 방법입니다.

단점: 비용 효율성이 떨어지고, EBS 전체를 백업할 필요가 없어 효율적이지 않다고 판단했습니다.

2. Lambda + EventBridge 조합

주기적으로 Lambda 함수를 실행해 백업하는 방식입니다.

장점: 확장성이 좋고 비용도 거의 발생하지 않습니다.

단점: 현재 작업 규모에 비해 설정할 것이 많습니다. Terraform 변경, Lambda Layer 구성 등 초기 세팅이 복잡한 편입니다.

3. Cron Job 활용

가장 원시적이지만 간단한 방법입니다.

장점: 직관적이고 구현이 쉽습니다. 스크립트를 Terraform에 통합하면 관리도 편합니다.

단점: 상대적으로 불안정하고 확장에 제약이 있습니다.

4. CloudWatch Logs 장기 보관

CloudWatch를 통해 로그를 장기간 보관하는 방법입니다.

단점: 메트릭당 비용이 발생해서 가장 비쌉니다. 게다가 DB 백업은 별도로 필요합니다.

 

최종 결정

종합적으로 검토한 결과, 일단 3번(Cron Job)으로 시작하고 추후 2번(Lambda)으로 발전시키는 방향이 가장 합리적이라고 판단했습니다.


Dev 환경 적용

백업 시스템을 안정적으로 운영하기 위해 다음과 같은 순서로 진행했습니다.

1. Terraform + S3 기반 스크립트 관리 

먼저 백업 스크립트들을 S3에 통합 관리하도록 설정했습니다. S3 버킷 생성 시 백업 스크립트들도 함께 업로드되도록 Terraform에 구성하여, 스크립트와 배포를 자동화했습니다. mysql 컨테이너에 접속하기 위한 시크릿들은 SSM에서 불러와 스크립트에 주입되게 구성하였습니다.

 

2. EC2와 S3 연동 구성

EC2 인스턴스가 S3에서 필요한 스크립트를 다운로드할 수 있도록 의존성을 설정했습니다. 인스턴스 생성 시 언제든 스크립트에 접근할 수 있도록 역할과 권한을 구성했습니다.

 

3. Terraform User-Data 스크립트 적용

Terraform에 인스턴스 user-data 스크립트를 추가하고 인스턴스 템플릿에 등록했습니다. 이를 통해 인스턴스가 교체되더라도 백업 시스템이 자동으로 구성되도록 보장했습니다.

 

4. 백업 환경 자동 구성

Dev 인스턴스 시작 시 다음 작업들이 자동으로 수행되도록 구성하였습니다.

  • 백업용 디렉토리 생성
  • S3에서 백업 스크립트 다운로드
  • Cron 설치
  • Cron 서비스 정상화 대기
  • mariadb 설치
  • 백업 cron job 등록
#!/bin/bash
echo ECS_CLUSTER=${ecs_cluster_name} >> /etc/ecs/ecs.config

mkdir -p /home/ec2-user/logs/backup
mkdir -p /home/ec2-user/mysql
mkdir -p /home/ec2-user/scripts

chown -R ec2-user:ec2-user /home/ec2-user/logs /home/ec2-user/mysql /home/ec2-user/scripts

aws s3 cp s3://eatda-storage-dev/scripts/app-backup-dev-logs.sh /home/ec2-user/scripts/app-backup-dev-logs.sh
chmod +x /home/ec2-user/scripts/app-backup-dev-logs.sh

aws s3 cp s3://eatda-storage-dev/scripts/mysql-backup.sh /home/ec2-user/scripts/mysql-backup.sh
chmod +x /home/ec2-user/scripts/mysql-backup.sh

yum install -y cronie
systemctl enable crond
systemctl start crond

until systemctl is-active --quiet crond; do
  sleep 1
done

sudo chown -R ec2-user:ec2-user /home/ec2-user/mysql

sudo dnf install -y mariadb105

(
  sudo crontab -u ec2-user -l 2>/dev/null || true
  echo "0 0 * * 0 /home/ec2-user/scripts/app-backup-dev-logs.sh >> /home/ec2-user/logs/backup/app-backup.log 2>&1"
  echo "30 0 * * 0 /home/ec2-user/scripts/mysql-backup.sh >> /home/ec2-user/logs/backup/mysql-backup.log 2>&1"
) | sudo crontab -u ec2-user -

 

5. 백업 프로세스 실행

DB 백업 스크립트는 아래와 같은 작업을 수행합니다.

  • SSM에서 DB 접속, S3 접근에 필요한 시크릿 가져오기
  • MySQL 컨테이너 기동중인지 확인
  • DB 백업
  • 압축 파일을 S3에 업로드
#!/bin/bash
set -e

BACKUP_DIR="/home/ec2-user/mysql"
S3_BUCKET="s3://eatda-storage-dev/backup/mysql/"
TIMESTAMP=$(date +%Y-%m-%d-%H%M%S)
ARCHIVE_PATH="${BACKUP_DIR}/mysql-backup-${TIMESTAMP}.sql"

MYSQL_URL=$(aws ssm get-parameter --name "/dev/MYSQL_URL" --with-decryption --query "Parameter.Value" --output text)
MYSQL_USER=$(aws ssm get-parameter --name "/dev/MYSQL_USER_NAME" --with-decryption --query "Parameter.Value" --output text)
MYSQL_PASSWORD=$(aws ssm get-parameter --name "/dev/MYSQL_PASSWORD" --with-decryption --query "Parameter.Value" --output text)

HOST=$(echo "$MYSQL_URL" | sed -E 's|jdbc:mysql://([^:/]+):([0-9]+)/([^?]+).*|\1|')
PORT=$(echo "$MYSQL_URL" | sed -E 's|jdbc:mysql://([^:/]+):([0-9]+)/([^?]+).*|\2|')
DB_NAME=$(echo "$MYSQL_URL" | sed -E 's|jdbc:mysql://([^:/]+):([0-9]+)/([^?]+).*|\3|')

retries=10
count=0
until mysqladmin ping -h "$HOST" -P "$PORT" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" --silent || [ $count -eq $retries ]; do
  echo "[INFO] Waiting for MySQL to be ready... ($count/$retries)"
  sleep 2
  count=$((count+1))
done

if mysqldump --no-tablespaces -h "$HOST" -P "$PORT" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$DB_NAME" > "$ARCHIVE_PATH"; then
  echo "[INFO] MySQL backup successful: $ARCHIVE_PATH"

  if aws s3 cp "$ARCHIVE_PATH" "$S3_BUCKET"; then
    echo "[INFO] Upload successful: $ARCHIVE_PATH -> $S3_BUCKET"
    rm "$ARCHIVE_PATH"
  else
    echo "[ERROR] Failed to upload backup to S3." >&2
    exit 1
  fi

else
  echo "[ERROR] mysqldump failed." >&2
  exit 1
fi

 

로그 백업 스크립트는 아래와 같은 작업을 수행합니다.

  • SSM에서 S3에 접근에 필요한 시크릿 가져오기
  • 로그 압축
  • 압축 파일을 S3에 업로드
  • 백업 완료 후 로컬의 이전 백업 파일들 정리
#!/bin/bash
set -e

LOG_DIR="/home/ec2-user/logs"
S3_BUCKET="s3://eatda-storage-dev/backup/logs/"
TIMESTAMP=$(date +%Y-%m-%d-%H%M%S)
ARCHIVE_PATH="/tmp/eatda-logs-${TIMESTAMP}.tar.gz"

if [ ! -d "$LOG_DIR" ]; then
  echo "[ERROR] Log directory does not exist: $LOG_DIR" >&2
  exit 1
fi

tar -czf "$ARCHIVE_PATH" -C "$LOG_DIR" .

if aws s3 cp "$ARCHIVE_PATH" "$S3_BUCKET"; then
  echo "[INFO] Upload successful: $ARCHIVE_PATH -> $S3_BUCKET"

  find "$LOG_DIR" -type f -name "*.log" -delete
  echo "[INFO] Old log files deleted from $LOG_DIR"

  rm "$ARCHIVE_PATH"
else
  echo "[ERROR] Failed to upload archive to S3." >&2
  exit 1
fi

Prod 환경 적용

Prod 환경은 RDS를 사용하고 있어 상대적으로 간단하게 처리할 수 있었습니다.

 

DB 백업

RDS 자동 스냅샷 기능을 활용해 7일간 백업 보관을 활성화했습니다. 이를 통해 DB는 AWS에서 관리되므로 별도 백업 스크립트가 불필요합니다.

 

로그 백업

애플리케이션 로그는 Dev 환경과 동일한 백업 시스템을 적용했습니다. 인스턴스에서 cron job을 통해 정기적으로 로그를 압축하여 S3에 업로드합니다.


결과

  • 로그 백업: 매주 일요일 00:00
  • DB 백업: 매주 일요일 00:30

구현 후 몇 주간 모니터링한 결과, 설정된 스케줄에 따라 안정적으로 백업이 수행되고 있음을 확인했습니다.


한계점 및 향후 개선점

하지만 현재 방식은 한계점이 뚜렷한데요.

  • 로그 백업이 인스턴스와 EBS에 완전히 의존적이어서, 인스턴스나 EBS에 갑작스러운 문제가 발생하면 해당 주의 백업이 실패하고 데이터가 유실될 가능성이 있습니다.
  • 분산 환경으로 확장할 경우 각 인스턴스마다 중복된 백업 작업이 실행되면서 로그가 꼬이거나 중복될 가능성이 있습니다.
  • 백업 상태를 확인하려면 각 인스턴스에 직접 접속해야 하는 번거로움이 있습니다.

이런 문제들을 해결하기 위해 Lambda 기반 백업 시스템으로의 마이그레이션을 고려하고 있습니다.

 

저작자표시 비영리 변경금지 (새창열림)

'YAPP' 카테고리의 다른 글

Datadog을 활용한 SLI/SLO 모니터링 및 Burn Rate 알람 적용기  (0) 2025.09.18
격리된 Prod 복제 환경에서 안전하게 DB 마이그레이션 수행하기  (2) 2025.08.29
API Latency Postmortem - 2 : 이미지 업로드 아키텍처 개선으로 주요 API 레이턴시 단축  (3) 2025.08.28
API Latency Postmortem – 1 : AWS t2.micro 환경에서의 병목 분석과 최적화  (8) 2025.08.12
인프라 자동화를 위한 Terraform 도입기  (4) 2025.08.01
'YAPP' 카테고리의 다른 글
  • 격리된 Prod 복제 환경에서 안전하게 DB 마이그레이션 수행하기
  • API Latency Postmortem - 2 : 이미지 업로드 아키텍처 개선으로 주요 API 레이턴시 단축
  • API Latency Postmortem – 1 : AWS t2.micro 환경에서의 병목 분석과 최적화
  • 인프라 자동화를 위한 Terraform 도입기
로승리
로승리
  • 로승리
    Roy's Blog
    로승리
  • 전체
    오늘
    어제
    • 분류 전체보기
      • Issuefy
      • Language
      • Spring
      • Kubernetes
      • AWS
      • YAPP
      • 코드스쿼드
      • 코딩 테스트
      • 국비지원
      • 회고
      • 컨퍼런스, 세미나
  • 블로그 메뉴

    • 홈
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
로승리
Dev/Prod 환경 로그 & DB 백업 자동화 적용하기
상단으로

티스토리툴바