Google Cloud Minecraft 서버의 Terraform 구성

VPC, 방화벽, 고정 IP, VM, 권한과 저장소를 한 작업 디렉터리에 둔 구성

minecraft-one-root는 VPC, 방화벽, 고정 IP, VM과 저장소를 한 작업 디렉터리에 둔다. 같은 사람이 한 번의 plan으로 함께 검토하고 변경할 대상이기 때문이다. Spot 선점 뒤 VM을 다시 시작하는 함수는 실행 주기와 권한이 달라 09편의 별도 작업 디렉터리로 분리한다.

검증 범위

Terraform과 셸 스크립트는 로컬과 컨테이너에서 검사했다. 실제 Google Cloud plan, apply, VM 생성과 접속은 비용을 만들 수 있어 로컬과 컨테이너 검증에서 실행하지 않았다. 현재 상태는 로컬과 컨테이너 검증 완료, 실제 Google Cloud apply 미검증이다.

Terraform 루트와 state

Terraform 루트는 함께 실행할 .tf 파일이 있는 작업 디렉터리다. 다운로드할 minecraft-one-root가 서버 루트에 해당한다.

minecraft-one-root/
├── README.md                  루트 개요와 명령 요약
├── versions.tf                Provider와 Terraform 버전
├── variables.tf               입력값과 거부 조건
├── project.tf                 필요한 Google Cloud API
├── network.tf                 VPC, 서브넷, IP와 방화벽
├── storage.tf                 백업 버킷과 권한
├── compute.tf                 서비스 계정과 Spot VM
├── outputs.tf                 접속에 쓸 이름과 IP
├── terraform.tfvars.example   입력값 샘플 (04편에서 복사해 채움)
├── backend.hcl.example        state 버킷 설정 샘플 (03편에서 사용)
├── scripts/                   설치, 검사, 백업과 복원
└── tests/                     실제 Provider 없이 실행하는 구성·컨테이너 시험

루트를 실행하면 Terraform은 리소스 주소와 실제 Google Cloud ID의 대응을 state에 기록한다. 예를 들어 google_compute_address.minecraft와 서울 리전의 고정 IP가 연결된다. state는 별도 Cloud Storage 버킷에 둔다. 백업 버킷과 state 버킷은 용도도 삭제 시점도 다르다.

backend 설정 파일에는 state 버킷 이름과 객체 접두어(prefix)가 들어간다. prefix는 버킷 안에서 이 서버의 state가 놓일 폴더 경로 같은 것으로, 한 버킷을 여러 용도로 나눠 쓸 때 서로 섞이지 않게 한다. terraform.tfvars에는 프로젝트, 방화벽 IP와 Minecraft JAR 값이 들어간다. 둘 다 개인 환경의 값이므로 ZIP에는 예시 파일만 넣고 Git에서 제외한다.

서버를 이루는 Google Cloud 리소스

서버에 들어오는 트래픽은 방화벽에서 시작해 VM의 고정 외부 IP로 도착한다. VM 안의 systemd 서비스가 Minecraft Java Edition 포트에서 요청을 받는다.

flowchart LR
    P["플레이어"] -->|"TCP 25565"| GF["게임 방화벽"]
    A["운영자"] -->|"TCP 22"| SF["SSH 방화벽"]
    GF --> IP["고정 외부 IPv4"]
    SF --> IP
    IP --> VM["Spot VM"]
    VM --> MC["minecraft.service"]
    VM -->|"백업 업로드"| BB["백업 버킷"]
    TF["Cloud Shell의 Terraform"] --> STATE["state 버킷"]
    TF --> VPC["VPC와 서브넷"]
    TF --> VM
    TF --> BB

각 리소스는 다음 일을 맡는다.

리소스맡은 일사라지면 생기는 결과
VPC와 서브넷VM이 놓일 사설 네트워크VM 네트워크를 연결할 수 없다.
게임 방화벽Minecraft TCP 포트를 허용서버가 실행돼도 외부에서 접속하지 못한다.
SSH 방화벽운영자 공인 IPv4의 22번 포트만 허용Cloud Shell SSH 점검이 막힌다.
고정 외부 IPv4재시작 뒤에도 같은 접속 주소 제공플레이어가 새 주소를 받아야 한다.
VM 서비스 계정VM이 백업 버킷에 객체를 쓰고 읽게 함백업 업로드와 검증이 실패한다.
Spot VM과 부팅 디스크Java와 Minecraft 프로세스, 현재 월드 저장서버가 멈추고 디스크 삭제 시 월드도 사라진다.
백업 버킷월드와 운영 설정 archive, 해시 보관VM 밖의 복구 사본이 사라진다.
state 버킷Terraform 관리 기록 보관코드와 실제 리소스의 연결을 잃는다.

게임 방화벽 기본값은 0.0.0.0/0이다. 이 표기는 CIDR라고 부르며, 0.0.0.0/0은 “모든 인터넷 주소”, 뒤에 나오는 /32는 “정확히 그 주소 하나”를 뜻한다. 기본값은 이동 통신망처럼 플레이어 IP가 자주 바뀌어도 포트에는 도달할 수 있게 한다. 대신 Minecraft는 첫 기동부터 whitelist를 켜고 빈 whitelist 상태에서는 모든 플레이어 접속을 거부한다. 고정 공인 IP가 있는 플레이어만 접속한다면 04편에서 각 주소를 /32로 제한할 수 있다.

한 디렉터리에서 함께 바꿀 범위

minecraft-one-root가 리소스를 한 루트에 둔 이유는 변경하는 사람과 배포 시점이 같기 때문이다. 한 운영자가 방화벽, VM 사양, JAR와 백업 버킷을 함께 검토한다. 서버를 처음 만들 때도 한 계획에서 생성 대상을 읽고, 운영을 끝낼 때도 VM과 네트워크의 삭제 순서를 함께 확인한다. 머신 유형을 바꾼 뒤에는 VM을 확인하고, 방화벽을 바꾼 뒤에는 접속을 시험한다. 서로 다른 팀이 각 리소스를 독립적으로 배포하는 환경은 이 구성의 대상이 아니다.

한 루트는 선언형 Google Cloud 리소스만 관리한다. VM 전원은 gcloud compute instances start|stop으로 다루고, whitelist와 운영자는 Minecraft 콘솔에서 바꾼다. 월드 백업과 복원은 VM의 스크립트가 담당한다. 이 명령을 Terraform 리소스로 억지로 표현하지 않아야 다음 plan이 운영자의 일상 작업과 충돌하지 않는다.

Terraform 루트를 나눠야 하는 경우

다음 중 하나가 생기면 별도 루트를 검토한다.

  • 변경하는 사람이나 승인 권한이 다르다.
  • 서버 기반보다 훨씬 자주 배포한다.
  • 서로 다른 서비스 계정과 최소 권한이 필요하다.
  • 한쪽 장애나 삭제가 다른 쪽 state를 잠그지 않아야 한다.
  • 다른 서버에서도 같은 기능을 공유한다.

09편의 Spot 복구가 이 경우다. 복구 함수는 VM이 중지된 뒤에도 실행돼야 하고, 함수 코드를 독립적으로 시험한다. 런타임 계정은 지정한 VM 조회와 시작만 허용받는다. Eventarc trigger 계정은 이벤트 수신과 함수 호출만 맡는다. 서버 루트와 state를 나누면 복구 코드를 바꿀 때 VM 교체 계획이 섞이지 않는다.

루트를 너무 일찍 잘게 나누면 backend와 적용 순서가 늘어난다. 한 사람이 항상 같이 바꾸는 VPC, IP와 VM까지 쪼개면 출력값 전달과 state 의존성을 관리해야 한다.

예상 비용과 Spot 중단

가격은 리전, 사용 시간, 디스크와 송신량에 따라 달라진다. 고정 금액을 기준으로 예산을 잡으면 가격표가 바뀐 뒤 잘못된 판단을 할 수 있다. apply를 승인하기 직전에 계산기를 다시 열고 계획의 VM·디스크·주소·저장소 조건을 입력한다.

확인: 2026년 7월 31일 기준 화면 이름

  1. Google Cloud Pricing Calculator에 접속한다.
  2. Compute Engine 항목에서 리전을 서울(asia-northeast3)로 고른다.
  3. 머신 유형에 e2-standard-2, 사용 모델에 Spot을 고른다.
  4. 한 달 동안 실제 켜 둘 시간을 입력한다. 24시간 운영과 필요한 때만 운영하는 경우를 각각 계산한다.
  5. 부팅 디스크에 Balanced persistent disk와 30 GiB를 넣는다.
  6. 고정 외부 IPv4 항목을 확인한다. 중지한 VM에 주소가 계속 연결돼 있으면 Google Cloud는 이 주소를 사용 중인 것으로 계산한다.
  7. Cloud Storage에 state와 백업의 예상 저장량을 넣는다. 백업 개수와 보존 기간을 곱해 대략적인 용량을 잡는다.
  8. 플레이어에게 전송할 네트워크 송신량을 추가한다.

네트워크 송신량도 계산에 넣어야 한다. 2026년 8월 공개 가격표에서 한국으로 나가는 Premium Tier 인터넷 트래픽의 첫 1TiB 구간은 GiB당 $0.19다. 실제 금액은 출발 리전, 목적지와 월간 사용량에 따라 달라지므로 적용 직전에 가격표를 다시 보고, 운영 뒤에는 결제 보고서의 Network 항목을 확인한다.

계산 결과는 입력 시점의 추정치다. 세금, 할인, 가격표 변경과 실제 사용 패턴 때문에 청구액이 달라질 수 있다. 02편의 예산 알림도 비용을 차단하지 않고 알림만 보낸다.

VM을 중지하면 vCPU와 메모리 사용료는 멈춘다. 부팅 디스크, 예약한 외부 IPv4, 백업과 state 객체의 비용은 계속될 수 있다. 11편에서는 이 항목을 리소스 목록과 결제 보고서에서 다시 확인한다.

Spot VM은 일반 VM보다 저렴하지만 Google Cloud가 자원을 회수할 수 있다. compute.tf는 선점 종료 동작을 STOP으로 설정하므로 VM 상태는 TERMINATED가 된다. 자동 재시작은 기본 구성에 넣지 않았다. 먼저 06편에서 백업 복원을, 08편에서 수동 시작을 확인한다. 자동 복구가 필요한 독자만 09편을 추가한다.

실제 리소스를 만들기 전에는 프로젝트와 Cloud Shell 준비에서 프로젝트, 결제 연결과 실행 환경을 확인한다.

참고

Comments

댓글

    이미지 확대