Skip to content

refactor: DB EC2 MySQL data volume 분리#58

Merged
Hexeong merged 4 commits into
mainfrom
refactor/57-seperation-data-volume
Jul 10, 2026
Merged

refactor: DB EC2 MySQL data volume 분리#58
Hexeong merged 4 commits into
mainfrom
refactor/57-seperation-data-volume

Conversation

@Hexeong

@Hexeong Hexeong commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

관련 이슈

작업 내용

  • DB EC2의 MySQL 데이터 디렉터리(/var/lib/mysql)를 root volume에서 분리하기 위해 별도 EBS data volume을 추가했습니다.
  • data volume은 DB EC2와 같은 AZ에 생성되며, gp3, encrypted, prevent_destroy 설정을 적용했습니다.
  • bootstrap 스크립트에서 EBS volume을 감지한 뒤 ext4 포맷, /var/lib/mysql 마운트, /etc/fstab 등록을 수행하도록 수정했습니다.
  • prod에서는 db_data_volume_size 값을 tfvars에서 주입하도록 연결했습니다.

특이 사항

  • 현재 RDS 실사용량은 약 1.9GiB 수준이라, root 8GiB + data 12GiB = 총 20GiB 구성으로 기존 RDS allocated storage와 총량을 맞췄습니다.
  • 이번 작업은 아직 prod 데이터 마이그레이션 전이므로 DB EC2 재생성을 전제로 진행합니다. 기존 DB EC2는 수동 종료해두었고, apply 시 Terraform이 새 DB EC2와 data volume을 생성하는 plan을 확인했습니다.
  • user_data_replace_on_change = true는 이번 bootstrap 반영을 위한 임시 운영 상태입니다. RDS 삭제 작업(refactor: DB 유저 생성 및 앱 datasource 변경 #52) 또는 운영 DB 전환 이후 PR에서 false로 되돌리고 user_data, user_data_base64, user_data_replace_on_changeignore_changes에 다시 포함할 예정입니다.

리뷰 요구사항 (선택)

  • data volume 크기 12GiB와 prevent_destroy 적용 방향이 적절한지 확인 부탁드립니다.
  • bootstrap에서 EBS volume을 /var/lib/mysql에 마운트하는 방식이 운영 전환 전 작업 흐름에 충분히 안전한지 봐주세요.

Summary by CodeRabbit

  • 새 기능

    • 프로덕션 DB에 별도의 영구 데이터 볼륨을 추가했습니다.
    • DB 데이터 볼륨 크기를 GiB 단위로 설정할 수 있습니다.
    • 데이터 볼륨은 암호화되며, DB 재배포 시에도 데이터 보존을 강화했습니다.
    • DB 시작 시 저장 장치를 자동으로 준비하고 MySQL 데이터 경로에 연결합니다.
  • 개선 사항

    • 데이터 볼륨 변경 시 DB 서버가 관련 리소스와 함께 안전하게 갱신됩니다.
    • DB 데이터 볼륨 ID를 외부 설정 및 운영 과정에서 확인할 수 있습니다.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Hexeong, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 33 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ccb3e2dd-83d3-4e49-9e25-a77c111f5950

📥 Commits

Reviewing files that changed from the base of the PR and between 905213b and 7c0493c.

📒 Files selected for processing (3)
  • modules/app_stack/db_ec2.tf
  • modules/app_stack/scripts/mysql_setup.sh.tftpl
  • modules/app_stack/variables.tf
📝 Walkthrough

Walkthrough

프로덕션 DB EC2에 별도 크기의 암호화된 gp3 EBS 데이터 볼륨을 생성·연결하고, MySQL 초기화 시 /var/lib/mysql에 마운트하도록 Terraform과 cloud-init 스크립트를 변경했습니다. 데이터 볼륨 ID output과 입력값 검증도 추가했습니다.

Changes

DB EC2 데이터 볼륨

Layer / File(s) Summary
데이터 볼륨 입력 계약
environment/prod/variables.tf, environment/prod/main.tf, modules/app_stack/variables.tf
프로덕션 DB 데이터 볼륨 크기 변수를 추가하고, DB EC2 활성화 시 필수 및 최소 1GiB 조건을 검증한 뒤 모듈에 전달합니다.
EBS 볼륨 프로비저닝 및 연결
modules/app_stack/db_ec2.tf, modules/app_stack/output.tf
동일 AZ의 암호화된 gp3 EBS 볼륨을 생성하고 /dev/sdf에 연결합니다. 볼륨 교체 시 인스턴스 교체를 연동하며 볼륨 ID를 output과 초기화 설정에 전달합니다.
MySQL 데이터 디렉터리 마운트
modules/app_stack/scripts/mysql_setup.sh.tftpl
데이터 장치를 최대 240초 동안 기다리고, 필요하면 ext4로 포맷한 뒤 UUID 기반 /etc/fstab 설정으로 /var/lib/mysql에 마운트합니다.

Secrets 서브프로젝트 참조

Layer / File(s) Summary
Secrets 참조 갱신
config/secrets
서브프로젝트가 참조하는 커밋 해시를 갱신합니다.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Terraform
  participant EBS
  participant DBEC2
  participant MySQLBootstrap
  Terraform->>EBS: 데이터 볼륨 생성
  Terraform->>DBEC2: EBS를 /dev/sdf에 연결
  DBEC2->>MySQLBootstrap: 볼륨 ID가 포함된 user-data 실행
  MySQLBootstrap->>EBS: 장치 연결 대기 및 파일시스템 확인
  MySQLBootstrap->>DBEC2: /var/lib/mysql에 볼륨 마운트
Loading

Possibly related PRs

Suggested labels: 인프라

Suggested reviewers: Gyuhyeok99, lsy1307, JAEHEE25, wibaek, sukangpunch, whqtker

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning DB 볼륨 작업과 무관한 config/secrets 서브모듈 포인터 변경이 함께 포함되어 있습니다. DB 볼륨과 직접 관련 없는 config/secrets 변경은 분리하거나, 필요성이 있다면 PR 설명에 근거를 추가하세요.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 DB EC2 MySQL 데이터 볼륨 분리라는 핵심 변경을 정확히 요약합니다.
Description check ✅ Passed 필수 섹션인 관련 이슈, 작업 내용, 특이 사항, 리뷰 요구사항이 모두 채워져 있어 템플릿을 대부분 충족합니다.
Linked Issues check ✅ Passed 별도 EBS data volume 생성, 동일 AZ 배치, /var/lib/mysql 마운트, 12GiB 크기, prevent_destroy 적용이 #57 요구와 일치합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/57-seperation-data-volume

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 10, 2026

Copy link
Copy Markdown

Terraform Plan: stage

No changes. Your infrastructure matches the configuration.

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

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

Terraform Plan: monitoring

No changes. Your infrastructure matches the configuration.

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

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

Terraform Plan: global

No changes. Your infrastructure matches the configuration.

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

@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

Terraform Plan: prod

Plan: 3 to add, 0 to change, 0 to destroy.

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

@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: 905213bf72

ℹ️ 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 modules/app_stack/scripts/mysql_setup.sh.tftpl Outdated

@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: 1

🧹 Nitpick comments (2)
modules/app_stack/db_ec2.tf (1)

78-80: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

replace_triggered_by가 전체 리소스를 참조합니다 — 볼륨 in-place 변경 시에도 인스턴스가 교체될 수 있습니다.

aws_ebs_volume.db_data[count.index]를 전체 리소스로 참조하면 db_data_volume_size 증가와 같은 in-place 업데이트에도 DB EC2가 교체 대상이 될 수 있습니다. 반대로 볼륨에 prevent_destroy = true가 있어 볼륨 "교체(replace)" 자체가 차단되므로, 볼륨 교체를 트리거로 삼으려던 의도가 실제로는 동작하지 않을 여지도 있습니다. 볼륨 교체(id 변경) 시에만 인스턴스 재생성을 유도할 의도라면 속성 참조(.id)가 더 정확합니다. 각 환경의 "Terraform Plan" 결과에서 볼륨 크기 변경이 인스턴스 교체를 유발하지 않는지 확인해 주세요.

♻️ 속성 참조로 변경 제안
     replace_triggered_by = [
-      aws_ebs_volume.db_data[count.index],
+      aws_ebs_volume.db_data[count.index].id,
     ]

As per path instructions: "plan에 예상치 못한 resource destroy 또는 replace가 포함된 경우", "lifecycle.ignore_changes 설정이 의도에 맞게 사용되었는지" 검토가 필요합니다.

🤖 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 `@modules/app_stack/db_ec2.tf` around lines 78 - 80, replace_triggered_by의 전체
리소스 참조로 인해 EBS 볼륨의 in-place 변경이 DB 인스턴스 교체를 유발할 수 있습니다. aws_instance.db의
lifecycle 설정에서 aws_ebs_volume.db_data[count.index] 참조를 해당 볼륨의 .id 속성 참조로 변경하고,
prevent_destroy 및 lifecycle.ignore_changes 설정이 의도에 맞는지 확인하세요. 각 환경의 Terraform
plan에서 볼륨 크기 변경이 인스턴스 교체나 예상치 못한 destroy를 발생시키지 않는지도 검증하세요.

Source: Path instructions

modules/app_stack/scripts/mysql_setup.sh.tftpl (1)

49-53: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

마운트 성공 여부를 검증한 뒤 진행하는 것을 권장합니다.

nofail 옵션과 mount ... || true 성격상, 마운트가 실패해도 스크립트가 계속 진행되어 MySQL이 root 볼륨의 /var/lib/mysql에 데이터를 쓰게 될 수 있습니다. 이는 데이터/OS 볼륨 분리 목적을 무력화합니다. 최소한 최초 부트스트랩에서 마운트 성공을 확인하고 실패 시 종료하도록 가드를 추가하세요.

🛡️ 마운트 검증 가드 추가 제안
 mountpoint -q /var/lib/mysql || mount /var/lib/mysql
+mountpoint -q /var/lib/mysql || { echo "Failed to mount data volume at /var/lib/mysql" >&2; exit 1; }
🤖 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 `@modules/app_stack/scripts/mysql_setup.sh.tftpl` around lines 49 - 53, 스크립트가
/var/lib/mysql 마운트 실패 후에도 계속 진행할 수 있으므로, mountpoint 확인 직후 마운트 성공 여부를 검증하는 가드를
추가하세요. `mount /var/lib/mysql`이 실패하거나 여전히 `mountpoint -q /var/lib/mysql`가 false이면
명확한 오류를 stderr에 출력하고 비정상 종료하도록 수정해 MySQL 초기화가 진행되지 않게 하세요.
🤖 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 `@modules/app_stack/scripts/mysql_setup.sh.tftpl`:
- Around line 25-27: Restrict db_ec2_instance_type to Nitro-based instance types
using Terraform variable validation, preventing unsupported non-Nitro values
from reaching the MySQL setup script and generating an unavailable NVMe device
path. Locate the db_ec2_instance_type variable declaration and add validation
that accepts only the supported Nitro naming patterns.

---

Nitpick comments:
In `@modules/app_stack/db_ec2.tf`:
- Around line 78-80: replace_triggered_by의 전체 리소스 참조로 인해 EBS 볼륨의 in-place 변경이 DB
인스턴스 교체를 유발할 수 있습니다. aws_instance.db의 lifecycle 설정에서
aws_ebs_volume.db_data[count.index] 참조를 해당 볼륨의 .id 속성 참조로 변경하고, prevent_destroy
및 lifecycle.ignore_changes 설정이 의도에 맞는지 확인하세요. 각 환경의 Terraform plan에서 볼륨 크기 변경이
인스턴스 교체나 예상치 못한 destroy를 발생시키지 않는지도 검증하세요.

In `@modules/app_stack/scripts/mysql_setup.sh.tftpl`:
- Around line 49-53: 스크립트가 /var/lib/mysql 마운트 실패 후에도 계속 진행할 수 있으므로, mountpoint
확인 직후 마운트 성공 여부를 검증하는 가드를 추가하세요. `mount /var/lib/mysql`이 실패하거나 여전히 `mountpoint
-q /var/lib/mysql`가 false이면 명확한 오류를 stderr에 출력하고 비정상 종료하도록 수정해 MySQL 초기화가 진행되지
않게 하세요.
🪄 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: a4b89de7-bdd0-406c-8a61-3acd40c8616a

📥 Commits

Reviewing files that changed from the base of the PR and between a076eed and 905213b.

📒 Files selected for processing (7)
  • config/secrets
  • environment/prod/main.tf
  • environment/prod/variables.tf
  • modules/app_stack/db_ec2.tf
  • modules/app_stack/output.tf
  • modules/app_stack/scripts/mysql_setup.sh.tftpl
  • modules/app_stack/variables.tf

Comment thread modules/app_stack/scripts/mysql_setup.sh.tftpl

@lsy1307 lsy1307 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.

수고하셨습니다!

Comment on lines +51 to +53
awk -v mount="$DATA_VOLUME_MOUNT" '$2 != mount { print }' /etc/fstab > /etc/fstab.tmp
printf 'UUID=%s %s ext4 defaults,nofail 0 2\n' "$DATA_VOLUME_UUID" "$DATA_VOLUME_MOUNT" >> /etc/fstab.tmp
mv /etc/fstab.tmp /etc/fstab

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.

현재 /etc/fstabnofail로 등록하고 있고, MySQL 컨테이너는 --restart always입니다. 첫 부팅 때는 bootstrap script가 EBS attachment를 기다린 뒤 mount하지만, 이후 재부팅에서는 cloud-init이 다시 돌지 않고 Docker가 컨테이너를 자동 시작할 수 있습니다.

이때 EBS mount가 실패하거나 지연되면 /var/lib/mysql이 root volume의 빈 디렉터리로 열리고, MySQL이 다른 datadir로 떠버릴 가능성이 있습니다. 운영 DB에서는 꽤 위험한 케이스라서 nofail 제거 또는 MySQL 컨테이너 systemd unit/drop-in에 RequiresMountsFor=/var/lib/mysql 같은 mount 의존성을 추가하는 방식이 필요해 보입니다.

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.

지적해주신 부분 감사합니다! mount 의존성을 추가하는 방식이 가장 안정적일 것 같아서 해당 내용 반영했습니다!

@lsy1307 lsy1307 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.

좋아용

@Hexeong Hexeong merged commit 8bba772 into main Jul 10, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor: DB EC2 MySQL data volume 분리

2 participants