Minecraft dedicated game server cluster hosting solution using GKE and Agones.
Suitable for both ephemeral and eternal game servers
Current architecture consists of:
-
Kubernetes cluster with Agones CRDs and controllers for deploying Minecraft server game pods
-
Custom Java and Bedrock Minecraft server kubernetes pods specs with sidecar services for health checking, auto world backup and, auto world loading
-
Controller managed DNS zone for auto provisioning custom DNS
A
andSRV
records for Minecraft servers
gcloud auth application-default login
gcloud services enable compute.googleapis.com container.googleapis.com dns.googleapis.com storage-component.googleapis.com
nano terraform/terraform.tfvars
-
region
string
- Cluster VPC region
-
zone
string
- Cluster zone
-
storage_location
string
- GCS storage location
-
agones_version
string
- Agones helm chart version
-
cluster_version
string
- Kubernetes master and node version (set to 1.18.18 as recommended by Agones)
-
auto_scaling
bool
- enable node auto scaling. Only recommended for strictly ephemeral game server clusters
-
min_node_count
number
- minimum node count for auto scaling
-
max_node_count
number
- maximum node count for auto scaling
The following Terraform configuration will provision:
-
A 2 n2-standard-4 (4 x vCPU, 16GB RAM) node zonal us-central1-a GKE cluster (with optional auto scaling)
-
A Custom us-central1 VPC network
-
Firewall rules for
TCP
andUDP
traffic on ports7000-8000
from anywhere for cluster nodes -
A Multi-regional us storage bucket for Minecraft world archives
-
A DNS zone for an owned or managed domain
-
Agones Helm chart installation with an HTTP ping service behind a cluster provisioned GCP Load Balancer
-
An ExternalDNS controller deployment for DNS record management
Command will run terraform init
, plan
, and apply
.
make tf
Terraform CLI will ask for inputs for your domain and GCP project ID
# Example
var.dns_name
managed dns zone name
Enter a value: example.com.
var.project_id
gcp project id
Enter a value: agones-minecraft-xxxxx
Outputs will include the name servers for your DNS zone. Configure your domain to point to these name servers
# Example
Outputs:
name_servers = tolist([
"ns-cloud-e1.googledomains.com.",
"ns-cloud-e2.googledomains.com.",
"ns-cloud-e3.googledomains.com.",
"ns-cloud-e4.googledomains.com.",
])
This public DNS zone will be used to assign A
and SRV
DNS record to Minecraft GameServers
gcloud dns managed-zones create agones-minecraft \
--description="externalDNS managed DNS zone" \
--dns-name=<DOMAIN> \
--visibility=public
Point an owned domain to the zone's NS record. This is done on the domain name registrar.
gcloud dns managed-zones describe agones-minecraft
World archives will be storage on GCP Cloud Storage buckets. Object storage offers better portability, easier management, and an overall better price over volumes.
The following command will make a multi-region bucket named agones-minecraft-mc-worlds
in the us
. In GCS, bucket names must be globally unique so use a different name.
Since bucket creation rate limited to 1 every 2 seconds, A single bucket containing all backups will be made.
gsutil mb -l us gs://agones-minecraft-mc-worlds
Creates GKE cluster with 2 n2-standard-4 (4 x vCPU, 16GB RAM), tags for firewall, and necessary scopes for Cloud DNS and Cloud Storage
gcloud container clusters create minecraft --cluster-version=1.18 \
--tags=mc \
--scopes=gke-default,storage-rw,"https://www.googleapis.com/auth/ndev.clouddns.readwrite" \
--num-nodes=2 \
--no-enable-autoupgrade \
--machine-type=n2-standard-4
Optionally, for strictly ephemeral game servers, you can enable node autoscaling
gcloud container clusters create minecraft --cluster-version=1.18 \
--tags=mc \
--scopes=gke-default,storage-rw,"https://www.googleapis.com/auth/ndev.clouddns.readwrite" \
--num-nodes=2 \
--no-enable-autoupgrade \
--machine-type=n2-standard-4 \
--enable-autoscaling
Set cluster as default and get credentials for kubectl
gcloud config set container/cluster minecraft
gcloud container clusters get-credentials minecraft
Players will connect to GameServer Pods using controller allocated hostPorts. Assign firewall rules to open all Agones allocatable ports. TCP is for Java and UDP is for Bedrock servers
gcloud compute firewall-rules create mc-server-firewall \
--allow tcp:7000-8000,udp:7000-8000 \
--target-tags mc \
--description "Firewall rule to allow mc server tcp traffic"
kubectl create namespace agones-system
kubectl apply -f https://raw.githubusercontent.com/googleforgames/agones/release-1.14.0/install/yaml/install.yaml
or
helm repo add agones https://agones.dev/chart/stable
helm repo update
helm install agones --namespace agones-system --create-namespace agones/agones
kubectl get pods -n agones-system
This controller is a fork of kubernetes-sigs/external-dns custom support for Agones GameServer sources. It will manage A
and SRV
records for Agones GameServers and Fleets allowing players to connect using a unique subdomain.
kubectl apply -f https://raw.githubusercontent.com/saulmaldonado/agones-minecraft/main/k8s/external-dns.yml
Fleets will deploy and manage a set of Ready
GameServers that can immediately be allocated for players to connect to.
# replace 'example.com' with the domain of the managed zone
sed 's/<DOMAIN>/example.com/' k8s/mc-server-fleet.yml | kubectl apply -f -
Full Java server fleet example
Allocating a server will make sure it does not get shutdown in the event of fleet scaling or rolling restart.
kubectl create -f k8s/allocation.yml
Players can connect using unique subdomain
<GAMESERVER_NAME>.<MANAGED_ZONE_DOMAIN>
example:
NAME STATE ADDRESS PORT NODE
mc-dj4jq-52tsd Allocated 35.232.46.5 7701 gke-minecraft-default-pool-47e5fdf8-5h9q
external-dns.alpha.kubernetes.io/hostname: saulmaldonado.me.
mc-dj4jq-52tsd.saulmaldonado.me
Fleets will deploy and manage a set of Ready
GameServers that can immediately be allocated for players to connect to.
# replace 'example.com' with the domain of the managed zone
sed 's/<DOMAIN>/example.com/' k8s/mc-bedrock-fleet.yml | kubectl apply -f -
Full Bedrock server fleet example
Allocating a server will make sure it does not get shutdown in the event of fleet scaling or rolling restart.
kubectl create -f k8s/bedrock-allocation.yml
Players can connect using unique subdomain and allocated port (bedrock does not support SRV records)
<GAMESERVER_NAME>.<MANAGED_ZONE_DOMAIN>:<GAMESERVER_PORT>
example:
NAME STATE ADDRESS PORT NODE
mc-dj4jq-52tsd Allocated 35.232.46.5 7701 gke-minecraft-default-pool-47e5fdf8-5h9q
external-dns.alpha.kubernetes.io/hostname: saulmaldonado.me.
address: mc-dj4jq-52tsd.saulmaldonado.me
port: 7701