Skip to content

feat: MySQL S3 백업 systemd 파이프라인 구성 - #71

Open
Hexeong wants to merge 3 commits into
mainfrom
feat/66-mysql-backup-systemd-pipeline
Open

feat: MySQL S3 백업 systemd 파이프라인 구성#71
Hexeong wants to merge 3 commits into
mainfrom
feat/66-mysql-backup-systemd-pipeline

Conversation

@Hexeong

@Hexeong Hexeong commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

관련 이슈

다음 작업: 백업 실패 감지 후 내부 알림 API를 거쳐 Discord로 전달하는 경로를 구성합니다.

작업 내용

  • 매일 03:00 KST에 mysqldump를 생성하고 복구 기준 binlog 위치, 체크섬, manifest와 함께 S3에 저장하도록 구성했습니다.
  • 5분마다 binlog를 회전하고 닫힌 파일만 순서대로 S3에 저장하며, 번호 누락과 역행을 감지하도록 구성했습니다.
  • 동일 객체 재업로드 방지, 버킷별 상태 관리, 동일 주기 중복 회전 방지 및 설치 실패 롤백을 적용했습니다.
  • DB EC2 데이터 EBS를 백업 staging 및 상태 저장 경로로 사용하도록 구성했습니다.
  • EC2 Instance Connect 임시 키와 API EC2의 SSM 포트 포워딩을 이용한 validate/install 수동 워크플로우를 추가했습니다.

특이 사항

  • 버킷 이름, DB 이름, DB EC2 SSH host fingerprint는 GitHub Repository Variable로 주입하며 값이 없으면 설치 전에 실패합니다.
  • IAM 역할과 정책은 기존 원칙대로 Terraform에 선언하지 않고 수동으로 관리합니다.
  • 다음 단계에서 DB EC2가 API EC2의 내부 전용 Spring POST API로 실패 이벤트를 전달하고, Spring이 Discord Webhook을 호출하는 구조를 고려하고 있습니다. Nginx 공개 경로 차단과 Blue/Green 활성 upstream 연동을 포함한 이 방향에 의견 부탁드립니다.

리뷰 반영 사항

  • 설치 전에는 GitHub 입력값으로 전제 조건을 검사하고, 설치 후에는 systemd가 실제 사용하는 환경 파일을 다시 읽어 검증하도록 구분했습니다. DB 존재 여부와 binlog·내구성 설정도 출력만 하지 않고 값까지 검사합니다.
  • S3 상태 복구 시 가장 큰 binlog 번호를 바로 신뢰하지 않고 manifest의 연속 구간까지만 복구 상태로 인정합니다. 중간 누락이 있으면 마지막 연속 지점부터 로컬 binlog를 다시 순회하며, 로컬 파일이 있으면 동일 체크섬 객체는 건너뛰면서 체인을 복구하고 로컬에도 없으면 gap 검증에서 실패합니다.
  • dump 완료 후 성공 시각을 원자적으로 기록하고 작업 포인터를 먼저 제거한 뒤 staging을 삭제합니다. 포인터 제거 직후 중단되어 staging이 남더라도 다음 실행에서 현재 작업과 무관한 이전 staging을 정리하도록 구성했습니다.
  • GitHub Actions는 전체 commit SHA로 고정했습니다. Session Manager plugin은 AWS S3의 1.2.835.0 버전 경로에서 패키지와 서명을 함께 내려받고, 패키지 버전 1.2.835.0-1, AWS 공개 키 fingerprint, GPG 서명이 모두 일치할 때만 설치하는 fail-closed 방식으로 변경했습니다.
  • 백업 테스트를 연속 두 번 실행해 동일 객체 재업로드 생략, S3 manifest gap 복구, dump 재시도, 누락 DB 차단 및 이전 staging 정리를 확인했습니다.

리뷰 요구사항 (선택)

  • 재설치 또는 중간 실패 후 재시도해도 동일한 백업 파이프라인 상태로 수렴하는지 확인 부탁드립니다.
  • binlog 회전 상태와 S3 manifest를 기준으로 복구 체인의 연속성이 유지되는지 확인 부탁드립니다.
  • 공개 저장소의 수동 배포 워크플로우에 민감한 값이나 장기 SSH 키가 노출되지 않는지 확인 부탁드립니다.

Summary by CodeRabbit

  • 새 기능

    • MySQL 전체 덤프와 바이너리 로그를 S3에 자동 백업합니다.
    • 체크섬, 매니페스트, 재시도 및 중복 업로드 방지를 지원합니다.
    • 덤프는 매일, 바이너리 로그는 5분마다 실행됩니다.
    • 백업 설치와 원격 환경 사전 검증을 수동으로 실행할 수 있습니다.
  • 안정성 개선

    • 저장 공간, MySQL 설정, S3 접근성을 자동 검증합니다.
    • 설치 실패 시 이전 구성을 복원하고 동시 실행을 방지합니다.
  • 문서 및 테스트

    • 운영·배포 절차와 실패 처리 정책을 문서화했습니다.
    • 백업 시나리오를 자동 검증하는 테스트를 추가했습니다.

- systemd service 배포 워크플로우 작성
- validate 모드와 install 모드로 나누어 구현
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bf1196fb-1980-4639-9e5c-980c56669fbb

📥 Commits

Reviewing files that changed from the base of the PR and between b91ea93 and e1f728f.

📒 Files selected for processing (11)
  • .github/workflows/mysql-backup-deploy.yml
  • .github/workflows/mysql-backup-test.yml
  • scripts/mysql_backup/README.md
  • scripts/mysql_backup/bin/mysql-backup-binlog
  • scripts/mysql_backup/bin/mysql-backup-dump
  • scripts/mysql_backup/bin/mysql-backup-validate
  • scripts/mysql_backup/install.sh
  • scripts/mysql_backup/lib/backup-common.sh
  • scripts/mysql_backup/systemd/mysql-backup-dump.service
  • scripts/mysql_backup/tests/run.sh
  • scripts/mysql_backup/validate-remote.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • scripts/mysql_backup/systemd/mysql-backup-dump.service
  • scripts/mysql_backup/install.sh

📝 Walkthrough

Walkthrough

MySQL S3 백업 파이프라인을 추가한다. 공통 검증·업로드 유틸리티, dump/binlog 실행 스크립트, systemd 타이머, 원자적 설치와 롤백, AWS·SSM 원격 배포, 회귀 테스트와 운영 문서를 구성한다.

Changes

MySQL 백업 파이프라인

Layer / File(s) Summary
백업 공통 계약과 사전 검증
modules/app_stack/scripts/mysql_setup.sh.tftpl, scripts/mysql_backup/lib/*, scripts/mysql_backup/bin/mysql-backup-validate, scripts/mysql_backup/validate-remote.sh
백업 디렉터리와 상태 경로를 초기화한다. 환경, MySQL 설정, 스키마, 디스크 공간, S3 버킷 및 설치 상태를 검증한다.
덤프와 binlog 백업 실행
scripts/mysql_backup/bin/mysql-backup-dump, scripts/mysql_backup/bin/mysql-backup-binlog
덤프 파일, 체크섬, 매니페스트를 생성하고 업로드한다. binlog 회전, 연속성 검증, 상태 복구 및 중복 업로드 방지를 처리한다.
원자적 설치와 예약 실행
scripts/mysql_backup/install.sh, scripts/mysql_backup/systemd/*
후보 파일과 환경을 검증한다. 설치 락과 롤백을 사용하고 파일과 systemd 유닛을 원자적으로 교체한다. dump와 binlog 예약 실행을 구성한다.
AWS 기반 원격 배포
.github/workflows/mysql-backup-deploy.yml, scripts/mysql_backup/README.md
수동 실행 모드에 따라 SSM 포트포워딩, EC2 Instance Connect, SSH 지문 검증 후 원격 검증 또는 설치를 수행한다. 운영 변수와 절차를 문서화한다.
백업 회귀 검증
.github/workflows/mysql-backup-test.yml, scripts/mysql_backup/tests/run.sh
S3 중복 업로드, 공간 검증, binlog 체인 복구, dump 매니페스트 재시도, 오래된 작업 폐기 동작을 격리 환경에서 검증한다.

Estimated code review effort: 5 (Critical) | ~100 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant AWS
  participant DBEC2
  participant BackupInstaller
  participant S3
  GitHubActions->>AWS: AWS 역할 설정 및 SSM 포트포워딩 시작
  AWS->>DBEC2: DB SSH 연결 전달
  GitHubActions->>DBEC2: SSH 호스트키 지문 확인
  GitHubActions->>DBEC2: validate-remote.sh 실행 또는 설치 번들 전송
  DBEC2->>BackupInstaller: install.sh 실행
  BackupInstaller->>S3: 버킷 확인 및 백업 산출물 업로드
Loading

Possibly related issues

Possibly related PRs

Suggested reviewers: gyuhyeok99, wibaek, lsy1307

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 MySQL S3 백업 systemd 파이프라인 구성이라는 주요 변경 사항을 명확하게 요약합니다.
Description check ✅ Passed 관련 이슈, 작업 내용, 특이 사항, 리뷰 요구사항을 포함하며 변경 목적과 운영 조건을 충분히 설명합니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/66-mysql-backup-systemd-pipeline

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

Terraform Plan: stage

No changes. Your infrastructure matches the configuration.

전체 plan 결과는 보안을 위해 댓글에 포함되지 않습니다. 워크플로우 실행 아티팩트를 확인하세요.

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

Terraform Plan: prod

No changes. Your infrastructure matches the configuration.

전체 plan 결과는 보안을 위해 댓글에 포함되지 않습니다. 워크플로우 실행 아티팩트를 확인하세요.

@Hexeong Hexeong self-assigned this Jul 16, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b91ea935c2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/mysql_backup/bin/mysql-backup-validate Outdated
Comment thread scripts/mysql_backup/validate-remote.sh

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (1)
scripts/mysql_backup/tests/run.sh (1)

147-152: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

binlog 객체가 manifest보다 먼저 업로드되는지 검증하세요.

현재 개수만 확인하므로 순서가 뒤집혀도 통과합니다. manifest가 먼저 노출되면 불완전한 binlog를 복구 가능 상태로 오인할 수 있습니다.

검증 추가안
   assert_equals "8" "$(wc -l <"$upload_log" | tr -d ' ')" "four closed binlogs and manifests must be uploaded"
+  mapfile -t uploaded_keys <"$upload_log"
+  for ((i = 0; i < ${`#uploaded_keys`[@]}; i += 2)); do
+    assert_equals \
+      "${uploaded_keys[i]}.manifest.json" \
+      "${uploaded_keys[i + 1]}" \
+      "each binlog must be uploaded immediately before its manifest"
+  done
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/mysql_backup/tests/run.sh` around lines 147 - 152, Update the
assertions in the test around upload_log to verify upload ordering, not only the
total count: confirm each closed binlog entry is recorded before its
corresponding manifest entry. Preserve the existing count, persisted state, and
rotation assertions while using the upload_log contents to fail when a manifest
is exposed before its binlog.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/mysql-backup-deploy.yml:
- Around line 31-45: Pin the actions used by the checkout and AWS credential
configuration steps to their full immutable commit SHAs instead of version tags.
Replace the Session Manager plugin’s latest download with a specific versioned
artifact, obtain its AWS-provided signature, verify the downloaded package with
the official signing key before installation, and only then run dpkg.

In `@scripts/mysql_backup/bin/mysql-backup-binlog`:
- Around line 94-115: Update the S3 recovery logic around uploaded_keys and
last_uploaded to validate manifest continuity before recording progress. Iterate
through the sorted binlog manifest numbers in order, require each adjacent
number to increase by exactly one, and set last_uploaded only to the final entry
in the contiguous sequence; stop before any gap so missing binlogs are not
treated as uploaded. Preserve the existing state reset and recovery message
behavior.

In `@scripts/mysql_backup/bin/mysql-backup-dump`:
- Around line 91-93: 백업 정리 순서를 조정하여 완료된 작업 포인터인 CURRENT_JOB_FILE을 staging 디렉터리인
JOB_DIR보다 먼저 삭제하세요. rm -f "$CURRENT_JOB_FILE"을 rm -rf "$JOB_DIR" 앞에 배치하고, 성공 상태
기록은 기존처럼 정리 작업 이후에 수행하세요.

In `@scripts/mysql_backup/install.sh`:
- Line 47: Separate the command substitution from the readonly declaration for
both SOURCE_DIR at scripts/mysql_backup/install.sh:4-4 and TRANSACTION_DIR at
scripts/mysql_backup/install.sh:47-47: assign each value first, then declare the
variable readonly on the following line so mktemp or other command failures
remain visible to set -e.

In `@scripts/mysql_backup/README.md`:
- Around line 10-17: Update the “배포 전 GitHub 설정” section in README.md to
document the required Repository Secret AWS_ROLE_ARN, including that it must
contain the AWS IAM role ARN used by the workflow. Keep the existing Repository
Variables guidance unchanged.

In `@scripts/mysql_backup/tests/run.sh`:
- Around line 282-295: Remove the previous manifest capture after copying it to
first_manifest and before the retry invocation of mysql-backup-dump. Update the
test flow around manifest_capture so the second run must recreate the capture,
ensuring cmp validates that the retry regenerated and reuploaded the manifest.
- Around line 4-5: run.sh의 PROJECT_DIR와 TEST_ROOT 선언을 readonly 선언과 값 할당으로 분리하세요.
먼저 readonly PROJECT_DIR/TEST_ROOT를 선언한 뒤 각 명령 치환을 별도 할당문으로 실행해 cd 또는 mktemp의 실패
상태가 호출자에게 전달되도록 하세요.

In `@scripts/mysql_backup/validate-remote.sh`:
- Around line 31-36: Update the pre-validation query in the
mysql-backup-validate workflow to evaluate the returned MySQL settings instead
of only checking whether the docker exec succeeds. Apply the same validation
conditions used by mysql-backup-validate for binlog enabled, binlog format,
server_id, sync_binlog, and innodb_flush_log_at_trx_commit, and fail validation
when any requirement is not met.

---

Nitpick comments:
In `@scripts/mysql_backup/tests/run.sh`:
- Around line 147-152: Update the assertions in the test around upload_log to
verify upload ordering, not only the total count: confirm each closed binlog
entry is recorded before its corresponding manifest entry. Preserve the existing
count, persisted state, and rotation assertions while using the upload_log
contents to fail when a manifest is exposed before its binlog.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 75a09b7a-f531-42b8-b099-88ff56d600f4

📥 Commits

Reviewing files that changed from the base of the PR and between c3bcc8f and b91ea93.

📒 Files selected for processing (14)
  • .github/workflows/mysql-backup-deploy.yml
  • modules/app_stack/scripts/mysql_setup.sh.tftpl
  • scripts/mysql_backup/README.md
  • scripts/mysql_backup/bin/mysql-backup-binlog
  • scripts/mysql_backup/bin/mysql-backup-dump
  • scripts/mysql_backup/bin/mysql-backup-validate
  • scripts/mysql_backup/install.sh
  • scripts/mysql_backup/lib/backup-common.sh
  • scripts/mysql_backup/systemd/mysql-backup-binlog.service
  • scripts/mysql_backup/systemd/mysql-backup-binlog.timer
  • scripts/mysql_backup/systemd/mysql-backup-dump.service
  • scripts/mysql_backup/systemd/mysql-backup-dump.timer
  • scripts/mysql_backup/tests/run.sh
  • scripts/mysql_backup/validate-remote.sh

Comment thread .github/workflows/mysql-backup-deploy.yml Outdated
Comment thread scripts/mysql_backup/bin/mysql-backup-binlog
Comment thread scripts/mysql_backup/bin/mysql-backup-dump Outdated
Comment thread scripts/mysql_backup/install.sh Outdated
Comment thread scripts/mysql_backup/README.md
Comment thread scripts/mysql_backup/tests/run.sh Outdated
Comment thread scripts/mysql_backup/tests/run.sh
Comment thread scripts/mysql_backup/validate-remote.sh Outdated

@whqtker whqtker left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다 ~

@@ -0,0 +1,382 @@
#!/usr/bin/env bash

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혹시 해당 스크립트는 로컬에서만 실행해야 하나요 ? 워크플로우 등에서 동작하도록 하면 좋을 거 같습니다 !

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 것 같습니다! CI로써 실행하기보다는 원래 명시적 실행 방식을 유지하도록 work_dispatch로 구성하겠습니다!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영했습니다. 자동 CI로 실행되지는 않도록 workflow_dispatch 방식의 MySQL Backup Test 워크플로우를 추가했습니다. AWS 권한이나 운영 환경 접근 없이 백업 스크립트 단위 테스트만 수동으로 실행됩니다!

@sukangpunch sukangpunch left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체 구조(멱등 업로드 → manifest를 완료 표식으로, 회전 의도 선기록, 설치 트랜잭션/롤백)는 설계가 탄탄합니다.
머지 전에 짚어야 할 것 4가지만 인라인으로 남겼습니다.

@@ -0,0 +1,208 @@
#!/usr/bin/env bash

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git에 기록된 파일 모드가 100644입니다. 워크플로우가 이 스크립트를 직접 실행하고(mysql-backup-deploy.yml:227) tar가 모드를 그대로 보존하므로, install 모드는 Permission denied로 즉시 실패합니다.

chmod +x scripts/mysql_backup/install.sh

방어적으로 워크플로우 쪽도 bash "$install_dir/install.sh" ...로 호출하면 확실합니다.

(bin/mysql-backup-binlog도 혼자 644인데, 이쪽은 install -m 755로 정규화되니 동작에는 영향 없습니다. 일관성 차원에서만 참고해주세요.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영했습니다! install.sh의 파일 모드를 100755로 변경했고, 파일 모드가 달라지는 상황에도 실행할 수 있도록 배포 워크플로우에서도 bash install.sh 형태로 호출하도록 보완했습니다. mysql-backup-binlog는 설치 과정에서 755로 정규화되므로 별도로 변경하지 않았습니다.


jobs:
deploy:
runs-on: ubuntu-latest

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

workflow_dispatch는 이 파일이 존재하는 아무 브랜치에서나 실행됩니다. 지금은 environment:도 브랜치 조건도 없어서, write 권한이 있으면 feature 브랜치에서 install.sh를 수정한 뒤 dispatch → prod DB에 root로 임의 코드 실행이 가능합니다. 리뷰·승인 경로를 전혀 거치지 않습니다.

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: prod-db   # required reviewers 지정
    if: github.ref == 'refs/heads/main' || inputs.mode == 'validate'

추가로 secrets.AWS_ROLE_ARN 역할의 trust policy sub 조건이 repo:...:ref:refs/heads/main으로 제한돼 있는지 확인 부탁드립니다. IAM은 코드로 확인이 안 돼서요. 제한돼 있지 않다면 위 게이트가 실질적인 유일한 방어선입니다.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지적해 주신 feature branch 기반 운영 실행 문제는 반영하겠습니다. 다만 validate 모드도 선택한 브랜치의 스크립트를 운영 서버에서 sudo로 실행하므로 main || validate 조건만으로는 충분하지 않은 것으로 확인했습니다. 두 모드 모두 main 브랜치에서만 실행되도록 제한하고, prod-db Environment의 승인 및 배포 브랜치 정책을 함께 적용하겠습니다. Environment 적용에 따라 IAM OIDC 신뢰 정책의 subject도 수동으로 점검하겠습니다!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OIDC와 연결된 Role의 trust policy 확인 결과, repo:...:ref:refs/heads/main로 정상적으로 반영되어 있습니다!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영했습니다! validate, install 모두 main 브랜치에서만 실행되도록 제한했고, prod-db Environment의 승인 절차를 거치도록 설정했습니다. Environment에는 required reviewer, self-review 차단, main 배포 브랜치 제한이 적용되어 있습니다.

done
install -d -m 700 "$JOB_DIR"

if [[ ! -s "$DUMP_FILE" ]]; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

실패한 dump가 다음 날 성공으로 종료됩니다.

dump-current 포인터와 staging/dump-<job_id>가 실패 시 보존되고, 재실행하면 [[ ! -s "$DUMP_FILE" ]]가 false라 덤프를 다시 뜨지 않고 기존 파일을 업로드합니다. 그런데 재시도 주기가 타이머와 같은 하루입니다.

시각 동작 결과
D일 03:00 dump 성공 → manifest 업로드 실패 exit 1, 포인터·staging 보존
D+1일 03:00 job_id를 그대로 재사용, 재덤프 없음 D일 데이터를 D일 키 프리픽스에 업로드
" exit 0 D+1일 백업은 존재하지 않음

created_atjob_id에서 유도되니 타임스탬프 자체가 거짓말을 하지는 않지만, 종료 코드는 성공이고 해당 날짜 백업은 없습니다.

제안:

  • job_id 나이 상한 (예: 6시간 초과면 포인터·staging 폐기하고 새 job 시작)
  • 하루를 기다리지 않는 당일 재시도 경로 — Type=oneshotRestart=를 못 쓰니 OnFailure=로 짧은 간격 타이머를 킥하거나 ExecStart 내부 제한 재시도

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 제안 감사합니다 ㅎㅎ 바로 반영했습니다~ 실패 시 10분 간격으로 최대 3회 재시도하고, 완성된 dump가 남아 있으면 dump를 다시 생성하지 않고 업로드만 재시도하도록 구성했습니다.

Type=oneshot에서도 Restart=on-failure는 사용할 수 있어 해당 방식으로 구성했습니다. 작업 생성 후 6시간이 지나면 기존 staging과 포인터를 폐기하고 새 dump를 생성하므로 다음 날 이전 데이터를 성공 처리하는 문제도 방지했습니다.


docker exec "$MYSQL_CONTAINER" sh -lc \
'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" exec mysqldump -uroot --single-transaction --quick --source-data=2 --routines --events --triggers --hex-blob --set-gtid-purged=OFF --no-tablespaces "$1"' \
sh "$MYSQL_DATABASE" | gzip -1 >"$partial_dump"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dump 시작 전 여유 공간 검사가 없습니다. 공간 검사(db_bytes * 2 + 256MB)는 bin/mysql-backup-validate:43-52에만 있고 설치 시점에 한 번 돕니다.

그런데 staging이 MySQL datadir와 같은 EBS입니다(backup-common.shBACKUP_ROOT, MYSQL_DATA_DIR 모두 /mnt/mysql-data). 데이터가 커진 뒤 03:00에 이 gzip이 볼륨을 채우면 MySQL이 쓰기 실패로 죽습니다. 백업이 프로덕션을 죽이는 실패 모드라 머지 전에 막는 게 좋겠습니다.

  • 이 스크립트 시작부에 validate와 동일한 검사를 넣고, 부족하면 덤프를 시작하지 않고 실패 처리
  • 여유가 되면 staging 전용 볼륨 분리

(gzip 스트림을 aws s3 cp -로 바로 흘리는 방법도 있지만 재시도 멱등성이 깨지니 공간 검사 쪽을 권합니다.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영했습니다~ 새 dump를 생성하기 직전에 DB 크기의 2배와 256MiB를 기준으로 여유 공간을 검사하고, 부족하면 mysqldump를 실행하지 않고 실패하도록 변경했습니다.

이미 dump 생성이 끝난 상태에서 S3 업로드만 재시도하는 경우에는 추가 디스크 공간을 사용하지 않으므로 공간 검사를 다시 수행하지 않도록 했습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants