Minecraft 월드 백업과 복원 시험
월드와 운영 설정 백업, SHA-256 검증, 운영 서버와 분리한 복원 시험
백업은 archive의 SHA-256이 맞고 Minecraft가 월드를 실제로 불러와야 복구에 사용할 수 있다. 시험 월드를 백업한 뒤 운영 월드는 그대로 두고 임시 디렉터리와 별도 포트에서 Minecraft가 archive를 읽는지 검사한다.
선수 조건
05편의 서버가
Done (...)!까지 도달했고 시험용 블록을 놓아 두어야 한다. 별도 안내가 없는 명령은 Cloud Shell의minecraft-one-root에서 실행한다.
검증 범위
백업과 검증 스크립트는 로컬과 Ubuntu 컨테이너에서 구문, 실패 분기와 격리 경로를 검사했다. 실제 VM, Cloud Storage 업로드와 Google Cloud 안의 Minecraft 월드 로드는 실행하지 않았다. 현재 상태는
로컬과 컨테이너 검증 완료, 실제 Google Cloud apply 미검증이다.
백업하는 동안 서버를 멈추는 이유
Minecraft가 월드 파일을 쓰는 중에 디렉터리를 압축하면 서로 다른 시점의 파일이 한
archive에 섞일 수 있다. minecraft-backup.service는 다음 순서를 따른다.
- 실행 중인
minecraft.service를 정상 종료한다. - Java 프로세스가 끝난 뒤 지정한 월드와 운영 설정을 압축한다.
- archive의 SHA-256 manifest를 만든다.
- 두 파일을 Cloud Storage에 올린다.
- 업로드 성공 여부와 관계없이 이전에 실행 중이던 서비스를 다시 시작한다.
이 구성은 서버를 잠시 중단해 파일 시점을 고정한다. 접속자가 적고 정해진 백업 시간을 알릴 수 있어 RCON 비밀번호와 온라인 snapshot 절차를 추가하지 않은 서버에 맞는다.
파일 일관성과 백업 주기의 설계 근거는 Minecraft 월드 백업과 복원에 정리돼 있다.
자동 백업 활성화
terraform.tfvars를 연다.
실행: minecraft-one-root에서
nano terraform.tfvars
다음 값을 확인한다.
enable_automatic_backup = true
backup_schedule = "*-*-* 04:30:00"
backup_world_directories = [
"world",
]
backup_schedule은 systemd OnCalendar 형식이고 VM의 기본 시간대는 UTC다. 예시의
04시 30분은 서울 시각 13시 30분이다. server.properties의 level-name을 바꿨다면
실제 월드 디렉터리 이름도 함께 바꾼다. 공식 vanilla 서버는 Nether와 End 차원을
world 아래에 함께 저장한다. Paper처럼 차원마다 최상위 디렉터리를 만드는 서버
구현으로 바꿨을 때만 실제 이름을 목록에 추가한다.
사전 검사를 다시 실행하고 metadata 변경만 계획되는지 본다.
실행
terraform fmt
scripts/preflight.sh
terraform plan -out=enable-backup.tfplan
terraform show enable-backup.tfplan
계획에서 VM metadata의 백업 설정이 바뀌어야 한다. VM 교체, 디스크 삭제 또는 방화벽 변경이 보이면 적용하지 않는다.
비용 영향: 실행 중인 VM의 metadata 변경
terraform apply enable-backup.tfplan
metadata를 바꿔도 실행 중인 시작 스크립트가 자동으로 다시 실행되지는 않는다. VM을 한 번 중지했다가 시작해 timer와 검증 명령을 설치한다.
실행: Cloud Shell에서
export MINECRAFT_INSTANCE="$(
terraform output -raw minecraft_instance_name
)"
export MINECRAFT_ZONE="$(
terraform output -raw minecraft_zone
)"
gcloud compute instances stop "${MINECRAFT_INSTANCE}" \
--zone="${MINECRAFT_ZONE}"
gcloud compute instances start "${MINECRAFT_INSTANCE}" \
--zone="${MINECRAFT_ZONE}"
중지 명령 뒤 상태가 TERMINATED, 시작 명령 뒤 RUNNING이 될 때까지 기다린다.
시작 실패를 반복하지 말고 Spot 용량 오류인지 확인한다.
timer와 서버 준비 상태
systemd timer는 정해진 시각에 백업 service를 시작하는 예약 작업이다.
확인
gcloud compute ssh "${MINECRAFT_INSTANCE}" \
--zone="${MINECRAFT_ZONE}" \
--command="sudo systemctl status \
minecraft-backup.timer \
--no-pager"
Active: active (waiting)과 다음 실행 시각이 보여야 한다. timer가 없으면 startup
script가 새 metadata로 끝났는지 먼저 확인한다.
백업 전에 서버가 다시 준비됐는지도 본다.
확인
gcloud compute ssh "${MINECRAFT_INSTANCE}" \
--zone="${MINECRAFT_ZONE}" \
--command="sudo journalctl \
-b \
-u minecraft \
-n 100 \
--no-pager"
새 부팅 뒤의 Done (...)!이 있어야 한다.
첫 수동 백업
예약 시각을 기다리지 않고 백업 서비스를 한 번 시작한다. 이때 접속자는 끊길 수 있다.
실행
gcloud compute ssh "${MINECRAFT_INSTANCE}" \
--zone="${MINECRAFT_ZONE}" \
--command="sudo systemctl start minecraft-backup.service"
확인
gcloud compute ssh "${MINECRAFT_INSTANCE}" \
--zone="${MINECRAFT_ZONE}" \
--command="sudo journalctl \
-u minecraft-backup.service \
-n 100 \
--no-pager"
정상 로그에는 Uploaded gs://.../backups/minecraft-...tar.gz가 나온다. 업로드가
실패했더라도 아래 명령은 Minecraft 서비스가 다시 살아났는지 확인해야 한다.
확인
gcloud compute ssh "${MINECRAFT_INSTANCE}" \
--zone="${MINECRAFT_ZONE}" \
--command="sudo systemctl is-active minecraft"
active가 아니면 archive 검사를 실행하지 않는다. 백업 service journal의 첫 오류와
재시작 trap 동작을 확인한다.
archive와 manifest 선택
확인
export BACKUP_BUCKET="$(
terraform output -raw backup_bucket_name
)"
gcloud storage ls "gs://${BACKUP_BUCKET}/backups/"
한 번의 백업은 timestamp가 같은 두 객체를 만든다.
gs://.../backups/minecraft-20260729T043000Z.tar.gz
gs://.../backups/minecraft-20260729T043000Z.tar.gz.sha256
두 파일 중 하나라도 없으면 백업으로 선택하지 않는다. 시험할 archive의 버킷 내부 경로만 변수에 넣는다.
archive의 config/에는 존재하는 파일만 들어간다.
server.propertieswhitelist.jsonops.jsonbanned-players.jsonbanned-ips.json
복원 스크립트는 이 설정을 월드와 함께 자동 적용하지 않는다. 백업 시점의 whitelist나 운영자가 현재 정책과 다를 수 있기 때문이다.
실행
export BACKUP_OBJECT="backups/minecraft-YYYYMMDDTHHMMSSZ.tar.gz"
YYYY... 전체를 실제 목록의 timestamp로 바꾼다. 목록에는
gs://버킷-이름/backups/minecraft-20260729T043000Z.tar.gz처럼 전체 주소가
나오지만, 변수에는 gs://버킷-이름/ 부분을 뺀
backups/minecraft-20260729T043000Z.tar.gz만 넣는다. archive 경로는 .tar.gz로 끝난다.
설정을 되돌릴 때는 먼저 현재 파일과 archive의 차이를 읽는다.
확인: 설정 차이만 출력
gcloud compute ssh "${MINECRAFT_INSTANCE}" \
--zone="${MINECRAFT_ZONE}" \
--command="sudo minecraft-restore-config \
${BACKUP_OBJECT}"
출력은 파일별 diff 형식이다. -로 시작하는 줄이 현재 VM의 설정이고, +로
시작하는 줄이 백업 시점의 설정이다. 차이가 없는 파일은 파일 이름만 나온다.
모든 차이를 읽고 백업 시점 설정으로 되돌리려는 경우에만 --apply를 붙여 실행한다.
미리보기와 같은 Cloud Shell에서 실행해야 위에서 export한 BACKUP_OBJECT가
전달된다. 대화형 SSH로 VM에 들어가면 이 변수가 없는 새 셸이라 명령이 빈 인수로
실패한다.
실행: 설정 파일 교체
gcloud compute ssh "${MINECRAFT_INSTANCE}" \
--zone="${MINECRAFT_ZONE}" \
--command="sudo minecraft-restore-config \
${BACKUP_OBJECT} --apply"
명령은 서버를 중지하고 파일을 교체한다. 소유권 변경이나 서비스 재시작이 실패하면
기존 설정을 원위치한다. 적용 뒤 whitelist, 운영자 목록과 Done (...)!을 다시
확인한다.
운영 월드를 건드리지 않는 로드 시험
검증 명령은 선택한 archive와 manifest를 VM의 임시 디렉터리에 내려받는다. 안전하지
않은 절대 경로, .., 링크와 장치 파일을 거부하고 설정한 월드 디렉터리만 푼다.
그다음 운영 서버의 JAR를 복사해 127.0.0.1:25566에서 별도 Minecraft 프로세스를
실행한다. 운영 서비스와 /srv/minecraft의 월드는 중지하거나 교체하지 않는다.
검증하는 동안에는 운영 서버(-Xmx4G)와 검증 프로세스(-Xmx2G)가 같은 VM에서
동시에 실행된다. 기본 e2-standard-2의 메모리 8GiB 가운데 두 Java heap의 상한이
합계 6GiB라서 운영체제와 다른 프로세스의 여유가 크지 않다. 플레이어가 없는 시간에
검증하고, 메모리 오류가 나면 검증 실패로 기록한 뒤
08편의 머신 유형 변경을 검토한다.
실행
gcloud compute ssh "${MINECRAFT_INSTANCE}" \
--zone="${MINECRAFT_ZONE}" \
--command="sudo minecraft-backup-verify \
${BACKUP_OBJECT}"
정상 결과는 SHA-256의 OK와 다음 문장이다.
Backup backups/minecraft-...tar.gz loaded successfully in an isolated working directory.
검증 프로세스는 준비 로그를 확인한 뒤 종료하고 임시 디렉터리를 지운다. 120초 안에
Done (...)!이 나오지 않거나 JAR가 종료되면 로그를 출력하고 실패한다. 실패한
archive를 “복구 가능한 백업”이라고 부르지 않는다.
이 검사는 월드가 서버에서 로드된다는 사실까지 확인한다. 블록, 표지판과 상자 내용이 정확한지는 운영 월드를 바꾸지 않고 자동 확인하기 어렵다. 중요한 서버라면 별도 테스트 VM이나 로컬 Minecraft에서 접속해 지정 좌표도 확인한다.
운영 월드 복원은 필요할 때만
아래 명령은 실행 중인 월드를 실제로 교체한다. 서버 장애로 복원이 필요하고, 같은 archive가 격리 시험을 통과했을 때만 사용한다.
조건부 실행: 운영 월드를 교체한다
gcloud compute ssh "${MINECRAFT_INSTANCE}" \
--zone="${MINECRAFT_ZONE}" \
--command="sudo minecraft-restore \
${BACKUP_OBJECT}"
복원 명령은 해시와 archive 경로를 다시 검사하고 staging 디렉터리에 모두 푼 뒤
Minecraft 서비스를 중지한다. 기존 월드를 임시 rollback 디렉터리로 옮기고 복원
월드를 배치한다. 이동, 소유권 변경, 서비스 시작이나 is-active 확인이 실패하면
새 월드를 치우고 기존 월드를 원위치한 뒤 서비스를 다시 시작한다. 성공하면 임시
rollback 디렉터리를 정리한다. 설정 파일은 교체하지 않는다.
서비스 로그에 새 Done (...)!이 나온 뒤 Java Edition으로 접속해 05편에서 만든
시험용 블록을 확인한다. 좌표까지 맞아야 사람이 확인한 복원 시험도 끝난다.
백업 보존 기간
기본 백업 버킷은 라이브 객체를 7일 뒤 삭제 대상으로 표시한다. Cloud Storage soft delete 정책이 있으면 삭제된 객체의 저장 비용과 보존 시간이 따로 적용될 수 있다.
확인
gcloud storage buckets describe \
"gs://${BACKUP_BUCKET}" \
--format="yaml(lifecycle_config,soft_delete_policy)"
복구해야 하는 과거 시점과 저장 비용을 기준으로 backup_live_days를 정한다. Terraform
state 버킷과 월드 백업 버킷은 목적이 다르므로 같은 lifecycle을 복사하지 않는다.
중단 조건
| 증상 | 확인할 곳 |
|---|---|
| timer가 없음 | enable_automatic_backup, startup script 완료 여부 |
업로드 403 | VM 서비스 계정의 버킷 objectCreator |
다운로드 403 | VM 서비스 계정의 버킷 objectViewer |
| 해시 불일치 | archive와 manifest의 timestamp 조합 |
| 월드 디렉터리 누락 | backup_world_directories와 level-name |
| 검증 JAR 조기 종료 | 검증 명령이 출력한 Minecraft 로그 |
| 백업 뒤 서버가 꺼짐 | backup service journal과 restart trap |
완료 체크
- archive와 같은 이름의
.sha256객체가 있다. minecraft-backup-verify가 해시와 격리 로드에 성공했다.- 운영
minecraft.service가 계속active다. - 자동 백업을 켰다면 timer가
active (waiting)이다.
기존 월드를 옮길 때는 기존 Minecraft 월드 가져오기를 따른다. 시험 월드를 계속 쓴다면 새 월드의 전원·버전 관리에서 전원과 JAR 변경 절차를 확인한다.
참고
Comments
아직 댓글이 없습니다. 첫 댓글을 남겨주세요.
검토 대기 중