기존 Minecraft 월드를 Google Cloud로 옮기기

기존 월드 archive 검사부터 VM staging, 교체, 접속과 새 백업까지

기존 Java Edition 월드는 archive의 경로와 level.dat를 검사한 뒤 VM의 임시 디렉터리에 푼다. 검사가 끝나면 서버를 멈추고 월드를 한 번에 교체하며, 시작이 실패하면 기존 시험 월드를 원위치한다.

선수 조건

06편에서 Google Cloud 시험 월드의 백업과 격리 로드 시험을 마쳐야 한다. 이전할 원본 서버도 정상 종료할 수 있어야 한다.

검증 범위

archive 검사와 rollback 분기는 Ubuntu 컨테이너에서 시험했다. 실제 VM에 개인 월드를 업로드하거나 교체하지 않았다. 현재 상태는 로컬과 컨테이너 검증 완료, 실제 Google Cloud apply 미검증이다.

원본 서버와 월드 폴더

원본 서버가 파일을 쓰는 동안 복사하면 서로 다른 시점의 청크가 섞일 수 있다. 플레이어를 내보내고 원본 Minecraft 서버를 정상 종료한다. Java 프로세스가 끝난 뒤 월드 폴더를 복사한다.

폴더 바로 아래에 level.dat가 있어야 한다.

world/
├── level.dat
├── region/
├── data/
├── playerdata/
├── DIM-1/
└── DIM1/

world/world/level.dat처럼 폴더가 한 단계 더 들어가면 안 된다. 이렇게 됐다면 바깥 폴더가 아니라 level.dat가 바로 들어 있는 안쪽 world 폴더가 이전 대상이다. 안쪽 폴더를 바탕화면 같은 다른 위치로 꺼낸 뒤, 그 폴더를 기준으로 아래 압축을 다시 만든다. Paper 계열 서버에서 Nether와 End가 별도 최상위 폴더라면 이 vanilla 예제로 바로 합치지 않는다. 서버 구현의 차원 배치를 먼저 확인하고 별도 이전 계획을 세운다.

world.tar.gz 만들기

Windows PowerShell에서 world 폴더의 부모 디렉터리로 이동한 뒤 실행한다. 부모 디렉터리는 탐색기에서 world 폴더가 보이는 위치다. 탐색기 주소창을 눌러 경로를 복사한 뒤 cd 다음에 붙여 넣는다. 예를 들어 서버 폴더가 C:\my-server라면 cd C:\my-server를 먼저 실행한다.

조건부 실행: Windows

tar -czf world.tar.gz world
tar -tf world.tar.gz | Select-Object -First 20

macOS나 Linux에서도 같은 위치에서 실행한다.

조건부 실행: macOS 또는 Linux

tar -czf world.tar.gz world
tar -tf world.tar.gz | sed -n '1,20p'

목록의 첫 경로가 world/이고 world/level.dat가 보여야 한다. 원본 server.properties, whitelist와 운영자 목록은 이 archive에 넣지 않는다. Google Cloud 서버의 whitelist와 포트 설정을 유지하기 위해서다.

Cloud Shell의 archive 검사

Google Cloud Console에서 Cloud Shell을 열고 오른쪽 위 점 세 개 메뉴의 업로드를 누른다. 방금 만든 world.tar.gz를 선택한다. 업로드가 끝나면 서버 예제 디렉터리로 이동한다.

실행

cd "${HOME}/minecraft-one-root"
scripts/validate-world-archive.sh \
  "${HOME}/world.tar.gz" \
  world

검사는 절대 경로, .., 심볼릭 링크, 하드 링크, 장치 파일과 다른 최상위 폴더를 거부한다. world/level.dat가 없을 때도 실패한다. 정상 결과는 예상 압축 해제 크기와 SHA-256을 보여 준다.

오류가 나오면 VM으로 복사하지 않는다. 원본 폴더 구조를 고쳐 새 archive를 만들고 검사부터 다시 한다.

VM staging에 복사

Terraform 출력에서 VM 이름과 존을 읽고 archive를 /tmp에 보낸다.

실행

export MINECRAFT_INSTANCE="$(
  terraform output -raw minecraft_instance_name
)"
export MINECRAFT_ZONE="$(
  terraform output -raw minecraft_zone
)"

gcloud compute scp \
  "${HOME}/world.tar.gz" \
  "${MINECRAFT_INSTANCE}:/tmp/world.tar.gz" \
  --zone="${MINECRAFT_ZONE}"

전송이 끊기면 같은 명령을 다시 실행한 뒤 VM에서 해시를 비교한다.

확인

export LOCAL_SHA="$(
  sha256sum "${HOME}/world.tar.gz" | cut -d' ' -f1
)"
export REMOTE_SHA="$(
  gcloud compute ssh "${MINECRAFT_INSTANCE}" \
    --zone="${MINECRAFT_ZONE}" \
    --command="sha256sum /tmp/world.tar.gz" | cut -d' ' -f1
)"
printf 'local  %s\nremote %s\n' "${LOCAL_SHA}" "${REMOTE_SHA}"
[[ "${LOCAL_SHA}" == "${REMOTE_SHA}" ]] \
  && echo "SHA-256 OK" \
  || echo "SHA-256 MISMATCH"

64자리 값 두 개를 눈으로 비교하는 대신 마지막 줄의 SHA-256 OK를 확인한다. MISMATCH가 나오면 교체하지 않고 gcloud compute scp부터 다시 실행한다.

운영 월드 교체

이 명령은 VM에 설치된 minecraft-world-archive-check로 Cloud Shell에서 했던 archive 검사를 같은 기준으로 다시 실행한다. 업로드 뒤에도 검사한 구조가 유지되는지 확인하기 위한 중복이다. 그다음 임시 디렉터리에 풀고, 필요한 디스크 여유 공간이 없으면 서버를 멈추기 전에 실패한다. 검사가 끝난 뒤에만 현재 시험 월드를 rollback 디렉터리로 옮긴다.

실행: 운영 월드를 교체한다

gcloud compute ssh "${MINECRAFT_INSTANCE}" \
  --zone="${MINECRAFT_ZONE}" \
  --command="sudo minecraft-world-import \
    /tmp/world.tar.gz \
    world"

파일 이동, 소유권 변경, 서비스 시작이나 is-active 확인이 실패하면 스크립트가 가져온 월드를 치우고 이전 시험 월드를 원위치한다. rollback 중에도 오류가 보이면 추가 이동 명령을 실행하지 말고 /srv/minecraft의 현재 목록과 systemd 로그를 기록한다.

Done 로그와 첫 접속

확인: 최대 10분

gcloud compute ssh "${MINECRAFT_INSTANCE}" \
  --zone="${MINECRAFT_ZONE}" \
  --command='
    active_since="$(
      systemctl show minecraft \
        --property=ActiveEnterTimestamp \
        --value
    )"
    for attempt in $(seq 1 60); do
      sudo journalctl \
        -u minecraft \
        --since "${active_since}" \
        --no-pager |
        grep -q "Done (.*)! For help" && exit 0
      sudo systemctl is-active --quiet minecraft || exit 1
      sleep 10
    done
    exit 1
  '

명령이 실패하면 sudo journalctl -u minecraft -n 200 --no-pager의 첫 오류를 본다. 새 버전으로 이미 연 월드를 더 오래된 JAR에서 열지 않는다. 버전 불일치라면 원본이 마지막으로 정상 실행된 Minecraft 버전과 Java major를 08편 절차로 준비한 뒤 다시 이전한다.

Done이 나오면 05편에서 등록한 운영자 계정으로 접속한다. 이전 전 적어 둔 좌표, 상자 내용, 표지판과 플레이어 인벤토리를 확인한다. whitelist와 ops.json은 Google Cloud 서버의 기존 설정이 유지된다.

이전 직후의 새 백업

접속 확인이 끝나면 새 상태를 백업한다.

실행

gcloud compute ssh "${MINECRAFT_INSTANCE}" \
  --zone="${MINECRAFT_ZONE}" \
  --command="sudo systemctl start minecraft-backup.service"

06편과 같은 방식으로 새 archive 이름을 찾고 minecraft-backup-verify를 실행한다. 새 archive가 격리 로드 시험을 통과하기 전에는 원본 서버와 원본 archive를 지우지 않는다.

VM의 임시 업로드 파일은 새 백업 검증 뒤 삭제한다.

데이터 삭제: 새 백업 검증 뒤 VM의 임시 파일

gcloud compute ssh "${MINECRAFT_INSTANCE}" \
  --zone="${MINECRAFT_ZONE}" \
  --command="sudo rm -- /tmp/world.tar.gz"

완료 체크

  • 원본 서버를 정상 종료한 뒤 archive를 만들었다.
  • archive 검사와 로컬, VM의 SHA-256 비교를 통과했다.
  • 새 월드에서 Done (...)!을 확인했다.
  • 지정한 좌표와 플레이어 데이터를 직접 확인했다.
  • 이전 직후 만든 백업이 격리 로드 시험을 통과했다.
  • 원본 월드와 archive는 새 백업 검증 전까지 보존했다.

새 백업까지 검증한 뒤에는 서버 전원과 버전 변경에서 VM 중지와 JAR 교체 절차를 확인한다.

Comments

댓글

    이미지 확대