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
AandSRVrecords for Minecraft servers
gcloud auth application-default logingcloud services enable compute.googleapis.com container.googleapis.com dns.googleapis.com storage-component.googleapis.comnano terraform/terraform.tfvars-
regionstring- Cluster VPC region
-
zonestring- Cluster zone
-
storage_locationstring- GCS storage location
-
agones_versionstring- Agones helm chart version
-
cluster_versionstring- Kubernetes master and node version (set to 1.18.18 as recommended by Agones)
-
auto_scalingbool- enable node auto scaling. Only recommended for strictly ephemeral game server clusters
-
min_node_countnumber- minimum node count for auto scaling
-
max_node_countnumber- 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
TCPandUDPtraffic on ports7000-8000from 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 tfTerraform 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-xxxxxOutputs 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=publicPoint an owned domain to the zone's NS record. This is done on the domain name registrar.
gcloud dns managed-zones describe agones-minecraftWorld 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-4Optionally, 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-autoscalingSet cluster as default and get credentials for kubectl
gcloud config set container/cluster minecraft
gcloud container clusters get-credentials minecraftPlayers 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.yamlor
helm repo add agones https://agones.dev/chart/stable
helm repo update
helm install agones --namespace agones-system --create-namespace agones/agoneskubectl get pods -n agones-systemThis 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.ymlFleets 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.ymlPlayers 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.ymlPlayers 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