Game Server Hosting on Kubernetes: 13 Steps, 75 Min [2026]
![Game Server Hosting on Kubernetes: 13 Steps, 75 Min [2026]](https://trendintech.com/wp-content/uploads/2026/10/game-server-hosting-kubernetes-tutorial-2026-gen.webp)
Players expect a multiplayer match to start in seconds, not minutes, and they expect it to run on a server close enough that their shots land where they aim. Delivering that at scale used to mean renting racks of bare metal or wrangling fleets of virtual machines by hand. In 2026, most studios have moved that job onto Kubernetes, using Agones to turn a standard cluster into a game server host that can spin up, allocate, and tear down dedicated servers in seconds. Agones shipped version 1.61.0 in the last week of September 2026, adding a restricted security context for its SDK sidecar, a fix for GameServer health detection, and a patch for a memory leak that had been quietly eating node capacity on long-running fleets. At the same time, Amazon GameLift Servers rolled out support for 13 additional AWS Regions and Local Zones and extended its newer Gen-8 Graviton4 (c8g) instance family to more regions, free of extra network charges on both On-Demand and Spot capacity.
The sections below cover through deploying a working dedicated game server fleet on Kubernetes using Agones 1.61 and Amazon EKS, step by step, from a bare cluster to an autoscaling fleet that a matchmaker can request servers from. Along the way you will build and containerize a minimal Go game server, write the Agones manifests that turn it into a managed fleet, wire up health checks and rolling updates, and load test the result before it ever touches real players. The last third of the article compares what you just built against Amazon GameLift Servers and Azure PlayFab Multiplayer Servers, so you can decide which path actually fits your studio’s size, budget, and ops team before you commit.
Don't miss new tech stories on Google
Add TrendinTech once in the Google app and our stories appear in your news suggestions.
Why Game Server Hosting Is Moving to Kubernetes in 2026
Dedicated game servers are a strange workload for any orchestrator. Unlike a web service, a game server session usually can’t be killed mid-match and restarted somewhere else without ruining the experience for everyone connected to it. It holds state in memory, it needs a stable network identity for the length of a match, and it needs to scale up and down in lockstep with how many players are queued, not with CPU load. Kubernetes was not built with any of that in mind, which is exactly why Agones exists. Mark Mandel, the founder of the Agones project and a Google Cloud for Games developer advocate, put it directly on the Kubernetes Podcast: “Kubernetes itself is not going to help you build the game server. What Kubernetes actually does is help us host and run this game server,” a distinction that explains why Agones is a thin operational layer rather than a game engine.
Craig Box, host of the same podcast, summarized the project in one line while introducing it alongside Agones co-creator Cyril Tovena: “So Agones is a library for hosting, running, and scaling dedicated game servers on Kubernetes.” That framing matters because it tells you what you are and are not getting. Agones does not write matchmaking logic, it does not replace your game engine’s networking code, and it will not pick a region for your players automatically. What it gives you is a Kubernetes-native way to request a ready server, mark it allocated, watch its health, and recycle it when the match ends, all through custom resources that feel like any other Kubernetes object.
The pull toward Kubernetes for this workload is mostly about consolidation. Studios running live-service titles already operate Kubernetes clusters for matchmaking, backend APIs, and analytics pipelines. Running the dedicated servers on the same control plane means one set of monitoring dashboards, one IAM and RBAC model, and one team that understands the infrastructure instead of two. Mandel has made this argument directly to studios considering the move, telling Nutanix’s The Forecast: “There are still absolutely VM-based orchestration systems out in the wild. But from what I’ve seen, Kubernetes is the standard everywhere,” and he has credited the platform with absorbing most of the undifferentiated operational work: “It does so much of the work that you need to do for running software at scale.”
That consolidation argument shows up most clearly once a studio has more than one live title. A team running two or three online games on separate VM-based stacks typically needs separate on-call rotations, separate patching schedules, and separate monitoring dashboards for each one, even when the games themselves share almost nothing in common. Moving the dedicated server layer onto the same Kubernetes clusters already running everything else collapses that duplicated overhead into a single operational surface. It does not make game server hosting simple, matches still hold state, still need stable connections, and still cannot be rescheduled mid-session the way a stateless web pod can, but it does mean the people who understand Kubernetes RBAC, node pools, and rolling updates for one workload already understand most of what the game server layer needs too.
None of that means Kubernetes and Agones are the only sane option. Amazon GameLift Servers and Azure PlayFab Multiplayer Servers both offer a managed path that trades flexibility for a much smaller operations burden, and the sections below cover that trade-off in detail later on. But if you want to understand how the open-source path actually works, control your own infrastructure, or avoid being locked into a single cloud’s game-hosting product, Agones on Kubernetes is the current standard, and building it by hand once is the fastest way to understand what a managed service is doing for you under the hood.
Prerequisites: Tools, Accounts, and Exact Versions
Before touching a terminal, get every tool installed at the versions below. Agones is picky about the Kubernetes minor version it runs on, and mismatched CLI versions are the single most common reason this kind of tutorial breaks halfway through. Budget about 75 minutes for the full walkthrough if your tools are already installed, closer to two hours if you are starting from a clean machine and need to wait on an EKS cluster to provision.
| Tool or Account | Minimum Version | Why You Need It |
|---|---|---|
| kubectl | 1.30 or newer | Talks to your Kubernetes API server and applies manifests |
| eksctl | 0.210 or newer | Provisions the Amazon EKS cluster and node groups |
| AWS CLI | v2, latest | Authenticates eksctl and manages IAM roles |
| Helm | 3.14 or newer | Installs the Agones controller and CRDs |
| Agones | 1.61.0 | The game server orchestration layer itself |
| Kubernetes cluster | 1.34, 1.35, or 1.36 | The only minor versions Agones 1.61 officially supports |
| Docker or Podman | 24.0 or newer | Builds and pushes the game server container image |
| Go | 1.22 or newer | Compiles the sample dedicated game server and SDK client |
| AWS account | Active, with billing enabled | Hosts the EKS cluster, ECR repository, and load balancer |
You also need an AWS account with permission to create an EKS cluster, an Elastic Container Registry (ECR) repository, and the associated VPC, security groups, and IAM roles. If you have never run eksctl create cluster before, expect the AWS bill for a small two-node cluster used only for this tutorial to land in the ten to twenty dollar range for a few hours of testing, provided you tear it down afterward using the cleanup step near the end of this article.
Step 1: Install kubectl, eksctl, and the Agones Prerequisites
Start by confirming every CLI tool is on your path and reports a version in the ranges listed above. Run the checks below before moving on, since a stale kubectl binary is the fastest way to get confusing “unknown field” errors later when you apply an Agones custom resource.
kubectl version --client
eksctl version
aws --version
helm version
docker --version
go version
If any command fails or reports a version below the table above, update it before continuing. On macOS, Homebrew handles all five with brew install kubectl eksctl awscli helm. On Windows, use winget or Chocolatey equivalents, and on Linux distributions use your package manager or the official install scripts from each project’s documentation.
Step 2: Provision an Amazon EKS Cluster for Game Workloads
Game server pods need predictable networking, so this cluster uses host networking later for the actual game traffic. For now, create a small two-node cluster sized for testing. Save the following as cluster.yaml.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: agones-demo
region: us-east-1
version: "1.34"
nodeGroups:
- name: game-workers
instanceType: c6g.large
desiredCapacity: 2
minSize: 2
maxSize: 4
volumeSize: 20
labels:
workload: game-servers
tags:
agones.dev/role: gameserver
Create the cluster with eksctl. This step alone takes 15 to 20 minutes because EKS has to stand up the control plane, VPC, and node group.
eksctl create cluster -f cluster.yaml
kubectl get nodes
You should see two nodes in Ready status. If a node sits in NotReady for more than five minutes, check the node group’s security group rules and confirm outbound internet access, since kubelet needs to reach the EKS API endpoint to register.
Step 3: Install Agones 1.61 on Your Kubernetes Cluster
Agones installs through Helm and creates its own namespace, controller deployment, and the custom resource definitions for GameServer, Fleet, FleetAutoscaler, and GameServerAllocation objects. The official Agones installation guide covers alternative install methods, but Helm is the fastest path for a demo cluster like this one.
helm repo add agones https://agones.dev/chart/stable
helm repo update
kubectl create namespace agones-system
helm install agones-release --namespace agones-system agones/agones --version 1.61.0
Confirm the controller and the allocator service are both running before moving on.
kubectl get pods --namespace agones-system
Expected output looks like this, with every pod showing Running and a healthy restart count of zero or one:
NAME READY STATUS RESTARTS AGE
agones-allocator-7d9f8c6b4d-x2jpn 1/1 Running 0 48s
agones-controller-5b7c9d9f4f-k8m2q 1/1 Running 0 48s
agones-ping-6c8d7f9b5c-m4n7p 1/1 Running 0 48s
The 1.61.0 release is worth pinning deliberately rather than installing “latest,” since it is the version that fixed the GameServer health detection bug and the Fleet rolling-update stability issue that affected earlier builds in the 1.60 line, according to the release notes published on the Agones GitHub releases page.
Step 4: Build a Minimal Dedicated Game Server Binary
Agones ships SDKs for Go, C++, Node.js, Rust, REST, and several other languages, all of which talk to a sidecar container that runs inside the same pod as your game server. The sidecar handles the handshake with the Agones controller so your binary never talks to the Kubernetes API directly. Here is a minimal Go server that marks itself ready, accepts a UDP connection, and shuts down cleanly when the match ends.
package main
import (
"log"
"net"
"time"
sdk "agones.dev/agones/sdks/go"
)
func main() {
s, err := sdk.NewSDK()
if err != nil {
log.Fatalf("could not connect to sdk server: %v", err)
}
if err := s.Ready(); err != nil {
log.Fatalf("could not mark server ready: %v", err)
}
go func() {
for {
time.Sleep(10 * time.Second)
if err := s.Health(); err != nil {
log.Printf("health ping failed: %v", err)
}
}
}()
conn, err := net.ListenPacket("udp", ":7654")
if err != nil {
log.Fatalf("could not open udp listener: %v", err)
}
defer conn.Close()
log.Println("game server listening on udp 7654")
buf := make([]byte, 1024)
for {
_, addr, err := conn.ReadFrom(buf)
if err != nil {
continue
}
conn.WriteTo([]byte("pong"), addr)
}
}
This is intentionally bare. It is not a real game loop, it just proves the full allocation, readiness, and health check cycle works before you plug in an actual game engine’s dedicated server build. Swap this binary for your Unreal, Unity, or custom engine’s headless server build once the plumbing checks out.
Swapping In the Unity SDK Instead of Go
If your dedicated server build comes from Unity rather than a custom Go binary, the Agones C# SDK exposes the same three calls shown above: connect to the local sidecar, call Ready() once your server’s game loop has finished initializing, and call Health() on a repeating timer. The main difference is where that code lives. In Unity, the SDK client typically initializes inside a MonoBehaviour’s Start method on your headless server build, with the health ping wired into a coroutine instead of a goroutine. The GameServer and Fleet manifests shown in later steps do not change at all, since Agones only cares about the container exposing the right port and the sidecar receiving the expected gRPC calls, not which engine or language produced them.
Swapping In the Unreal Engine SDK Instead of Go
Unreal Engine dedicated servers typically wire the Agones C++ SDK into the game mode’s initialization path, calling Ready() once the level has finished loading rather than immediately on process start, since Unreal’s level streaming can take longer than a simple Go binary’s startup. One detail that trips up teams moving from a prototype to a real Unreal build: Unreal dedicated servers are frequently built with a different port range convention than a typical Go or Node service, so double-check the containerPort value in your GameServer manifest actually matches what your packaged server binary binds to, rather than assuming it inherited the value from your editor-side testing configuration.
Step 5: Containerize and Push Your Game Server Image
Build a small container image and push it to ECR so your EKS cluster can pull it. Create a repository first if one does not already exist.
aws ecr create-repository --repository-name demo-gameserver --region us-east-1
docker build -t demo-gameserver:1.0 .
docker tag demo-gameserver:1.0 ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/demo-gameserver:1.0
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com
docker push ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/demo-gameserver:1.0
Replace ACCOUNT_ID with your actual AWS account number. Keep the image small. A statically compiled Go binary in a distroless base image typically lands under 20MB, which matters once you are pulling this image across dozens of nodes during a traffic spike.
Step 6: Write Your First GameServer Manifest
A GameServer is the smallest unit Agones manages, roughly equivalent to a Pod but with a lifecycle tuned for match hosting. Save this as gameserver.yaml.
apiVersion: agones.dev/v1
kind: GameServer
metadata:
name: demo-gameserver
spec:
ports:
- name: default
containerPort: 7654
protocol: UDP
template:
spec:
containers:
- name: demo-gameserver
image: ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/demo-gameserver:1.0
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "250m"
Apply it and watch the state transition. A freshly created GameServer goes from Scheduled to RequestReady to Ready once your binary calls the SDK’s ready method.
kubectl apply -f gameserver.yaml
kubectl get gameserver demo-gameserver
NAME STATE ADDRESS PORT NODE
demo-gameserver Ready 34.201.88.112 7654 ip-192-168-41-2
That public address and port are exactly what a game client would connect to for a direct-connect test. In production, a matchmaker requests this address through a GameServerAllocation rather than a client fetching it directly.
Step 7: Deploy a Fleet and Verify Allocation
A single GameServer is useful for testing, but production traffic needs a Fleet, which keeps a pool of warm, ready-to-allocate servers so players never wait on a cold container start. Save this as fleet.yaml.
apiVersion: agones.dev/v1
kind: Fleet
metadata:
name: demo-fleet
spec:
replicas: 5
template:
spec:
ports:
- name: default
containerPort: 7654
protocol: UDP
template:
spec:
containers:
- name: demo-gameserver
image: ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/demo-gameserver:1.0
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "250m"
kubectl apply -f fleet.yaml
kubectl get fleet demo-fleet
kubectl get gameservers
You should see five GameServer objects, all in Ready state, each on a different port if they share a node. Request an allocation the same way your matchmaking service would, using a GameServerAllocation object.
cat allocation.yaml
# apiVersion: allocation.agones.dev/v1
# kind: GameServerAllocation
# spec:
# selectors:
# - gameServerSet: demo-fleet
kubectl create -f allocation.yaml
The response includes the IP and port of a newly Allocated server, and Agones automatically spins up a replacement so the fleet’s pool of ready servers stays at five.
Step 8: Configure a FleetAutoscaler for Player Demand
Fixed replica counts waste money overnight and run out of capacity during a launch spike. A FleetAutoscaler watches the ratio of ready to allocated servers and adjusts the fleet size automatically.
apiVersion: autoscaling.agones.dev/v1
kind: FleetAutoscaler
metadata:
name: demo-fleet-autoscaler
spec:
fleetName: demo-fleet
policy:
type: Buffer
buffer:
bufferSize: 3
minReplicas: 5
maxReplicas: 40
With a buffer size of three, Agones keeps at least three unallocated, ready servers on hand at all times, scaling the fleet up as players consume that buffer and down again once demand drops, never going below five or above forty total servers.
kubectl apply -f fleetautoscaler.yaml
kubectl get fleetautoscaler demo-fleet-autoscaler
Buffer Policy vs Webhook Policy: Which One to Pick
The Buffer policy used above is the right default for most fleets, since it is simple to reason about and needs no extra infrastructure. It works purely off the ratio of ready to allocated GameServers, which fits any game where demand roughly tracks how many servers are currently in a match. A smaller studio running one title with a fairly predictable traffic curve rarely needs anything more sophisticated than this.
A Webhook policy hands scaling decisions to an external HTTP endpoint you control, which Agones calls every time it evaluates whether to resize the fleet. This is worth the extra complexity when your scaling logic needs context Agones does not have on its own, for example a known scheduled tournament start time, a marketing push expected to spike signups at a specific hour, or a custom cost ceiling that should cap growth even if player demand would otherwise justify more servers. Most studios start with Buffer and only move to Webhook once they have a concrete, data-backed reason the simple ratio-based approach is leaving capacity on the table or wasting it.
Step 9: Connect a Matchmaker to Request Game Server Allocations
Your matchmaking service, whether custom-built or a third-party product, needs to call the Agones allocator service over gRPC rather than touching the Kubernetes API with a service account token. The allocator runs inside the agones-system namespace and exposes a secured endpoint for exactly this purpose.
kubectl get service agones-allocator --namespace agones-system
Point your matchmaker’s gRPC client at that service’s external address, using the TLS client certificate Agones generates during install. Every allocation request returns a ready server’s address immediately, which your matchmaker then hands to the players who were just matched, letting them connect directly.
Step 10: Set Health Checks, Readiness, and Rolling Updates
Agones considers a GameServer unhealthy if its sidecar stops receiving health pings, which is why the sample binary in Step 4 calls s.Health() every ten seconds. Tune the tolerance in the Fleet spec if your game loop is heavier and can’t ping that often.
spec:
health:
disabled: false
periodSeconds: 10
failureThreshold: 3
initialDelaySeconds: 5
For rolling updates, Agones defaults to replacing a percentage of the fleet at a time rather than all at once, which the 1.61.0 release specifically hardened after reports of fleets getting stuck mid-rollout in earlier builds. Set an explicit strategy so a bad image never takes down the whole fleet at once.
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
Step 11: Load Test Your Fleet Before Launch
Before any real traffic hits this fleet, simulate a burst of matches by firing a batch of GameServerAllocation requests and watching how fast the FleetAutoscaler reacts. A simple loop works for a smoke test.
for i in $(seq 1 20); do
kubectl create -f allocation.yaml
sleep 1
done
watch kubectl get fleet demo-fleet
Watch the fleet’s replica count climb toward the buffer target and confirm new GameServer pods reach Ready within a few seconds of being scheduled. If pods take longer than 15 to 20 seconds to go ready, check your container image size and node pull-through cache, since image pull time is the most common cause of slow scale-up.
Step 12: Monitor Fleets With Metrics and Logs
Agones exposes Prometheus metrics for fleet replica counts, allocation latency, and GameServer state transitions out of the box. Point an existing Prometheus or Grafana stack at the controller’s metrics endpoint, or export the same metrics into CloudWatch if you are already standardized on AWS-native observability. At minimum, track three numbers: ready server count versus buffer target, allocation request latency, and GameServer restart count, since a climbing restart count almost always means a crash loop in your game binary rather than an Agones problem.
Step 13: Tear Down Safely and Control Cloud Costs
Delete resources in the reverse order you created them, and don’t skip the EKS cluster teardown, since a forgotten two-node cluster billing by the hour is the most common surprise charge from a tutorial like this one.
kubectl delete fleetautoscaler demo-fleet-autoscaler
kubectl delete fleet demo-fleet
helm uninstall agones-release --namespace agones-system
eksctl delete cluster -f cluster.yaml
Confirm the cluster is actually gone with eksctl get cluster, and check the EC2 and EKS consoles directly if you want to be certain no orphaned load balancer or node group is still billing in the background.
Agones vs Amazon GameLift Servers vs Azure PlayFab Multiplayer Servers
Having built the self-managed path by hand, it’s easier to see exactly what a managed service buys you. Amazon GameLift Servers now spans more regions and newer compute than it did a year ago, having added 13 additional AWS Regions and Local Zones in a September 24, 2026 update, alongside Graviton4-based Gen-8 (c8g) instances rolling out to more regions throughout the year. Those Gen-6-and-newer instance families also include inbound and outbound network bandwidth at no extra charge, across both On-Demand and Spot capacity, which removes one of the more annoying line items studios used to budget around separately. AWS has leaned into the comparison directly, publishing documentation that walks studios through migrating existing Kubernetes and Agones workloads onto GameLift Servers rather than maintaining both.
| Factor | Agones on Kubernetes | Amazon GameLift Servers | Azure PlayFab Multiplayer Servers |
|---|---|---|---|
| Hosting model | Self-managed, open source | Fully managed by AWS | Fully managed by Microsoft |
| Kubernetes versions supported | 1.34, 1.35, 1.36 | Not applicable, no Kubernetes layer | Not applicable, no Kubernetes layer |
| Supported cluster environments | EKS, GKE, AKS, Minikube | AWS only, with Graviton4 Gen-8 instances | Azure only, PlayFab control plane |
| Recent regional expansion | Runs wherever your cluster runs | 13 additional Regions and Local Zones added Sept. 2026 | Tied to existing Azure region footprint |
| Autoscaling control | Full control via FleetAutoscaler policies | Managed autoscaling, less granular tuning | Managed autoscaling, less granular tuning |
| Operational overhead | Highest, you own patching and cluster ops | Low, AWS owns the control plane | Low, Microsoft owns the control plane |
| Best fit | Studios already running Kubernetes, wanting cloud portability | AWS-committed studios wanting minimal ops | Studios already standardized on Azure and Xbox services |
Mandel’s own pitch for Agones, delivered at a KubeCon session on how large studios orchestrate global multiplayer capacity, is that the Kubernetes-native approach gives studios geographic control a managed product can’t always match: “Agones allows us to easily place capacity where players actually are.” That matters most for studios running their own regional infrastructure deals or needing to place servers somewhere neither AWS nor Azure has a region, since Agones runs on any conformant Kubernetes cluster, including on-premises hardware.
Cost Breakdown: Kubernetes Game Servers vs Managed Alternatives
Cost is usually the deciding factor once the technical comparison is settled, and it rarely favors the option a studio originally assumed. An industry cost analysis published by unixgaming.org, titled GameLift vs PlayFab vs Agones: $700 vs $3,127/Mo, modeled a 3,000 concurrent-user fleet across all three platforms and found a wide gap between the cheapest self-managed option and the most expensive fully managed one. The underlying logic is straightforward: a managed platform bundles its control plane, autoscaling engine, and regional routing into its per-hour compute price, while a self-managed Agones cluster only pays for raw EC2 or equivalent compute plus whatever your own team’s time is worth.
| Platform | Cost Driver | What You’re Paying For | Best Suited To |
|---|---|---|---|
| Self-managed Agones on EKS | Raw node compute plus your own ops time | Full control, no platform markup, but you staff the on-call rotation | Studios with an existing Kubernetes platform team |
| Amazon GameLift Servers | Per-instance-hour pricing with bundled bandwidth | Managed scaling, matchmaking integration, Graviton4 Gen-8 instances | AWS-committed studios wanting to skip cluster ops entirely |
| Azure PlayFab Multiplayer Servers | Per-core-hour pricing tied to Azure compute tiers | Managed scaling plus tight Xbox and Azure PlayFab backend integration | Studios already on Xbox Live and Azure PlayFab services |
The honest takeaway is that raw compute cost is only part of the equation. A two-person ops team babysitting a self-managed Agones cluster at 2 a.m. during a launch spike has a cost too, it just doesn’t show up on the AWS invoice. Run the numbers for your own team’s size and on-call tolerance before assuming the cheaper sticker price on paper is actually the cheaper option in practice.
Common Pitfalls When Deploying Game Servers on Kubernetes
- Running game server pods behind a ClusterIP service. Dedicated game servers need a directly reachable address and port, not a load-balanced virtual IP. Agones handles this by assigning each GameServer a real node port, but if you add a standard Kubernetes Service in front of it out of habit, you break the direct-connect model entirely.
- Forgetting UDP in security group rules. Most engineers default to opening TCP ranges and forget that almost every real-time game protocol runs over UDP. Double-check your EKS node group’s security group allows inbound UDP on the port range your Fleet spec uses.
- Setting resource requests too low. A game server pod with no memory headroom gets OOMKilled mid-match under player load, which looks like a mysterious “server vanished” bug to players and a confusing GameServer state flip to you. Always load test before trusting your resource limits.
- Skipping the health ping in your game binary. If your game loop blocks for more than a few seconds doing something like a level load, and you haven’t moved the SDK health call to its own goroutine or thread, Agones marks the server unhealthy and kills it mid-load.
- Ignoring the FleetAutoscaler buffer size. A buffer set too small means players queue behind cold-starting servers during a traffic spike. A buffer set too large wastes compute 23 hours a day. Tune this against your actual traffic curve, not a guess.
- Treating a Fleet update like a stateless deployment rollout. Rolling update settings that work fine for a web API can evict active matches on a game server fleet if maxUnavailable is set too aggressively. Players mid-match should never be the ones absorbing your deployment risk.
Troubleshooting Guide for Agones and EKS Errors
- GameServer stuck in Scheduled and never reaches Ready. This almost always means your binary never called the SDK’s ready method, or the sidecar container can’t reach the Agones controller. Check sidecar logs with kubectl logs POD_NAME -c agones-gameserver-sidecar.
- Pods crash-loop immediately after the image pull succeeds. Check that your container’s entrypoint actually binds to the port declared in the GameServer spec, and confirm the image’s base OS has the dynamic libraries your binary needs if you didn’t build a fully static binary.
- FleetAutoscaler never scales past minReplicas. Verify the autoscaler’s fleetName field matches your Fleet’s metadata name exactly, including case. A typo here fails silently rather than throwing an obvious error.
- Allocation requests time out. Confirm the agones-allocator service is reachable from wherever your matchmaker runs, and check that its TLS client certificate hasn’t expired, since Agones rotates these periodically.
- Health check failures right after a node drains. This is expected behavior, not a bug. When a node drains for a Kubernetes upgrade, every GameServer on it loses its health pings and gets marked unhealthy. Plan node upgrades around low-traffic windows.
- Helm install fails with a CRD conflict. This usually means a previous Agones install wasn’t fully uninstalled. Run kubectl get crds | grep agones and manually delete any leftover CustomResourceDefinitions before reinstalling.
- EKS node group stuck Creating for over 20 minutes. Check your VPC’s subnet IP exhaustion and the node IAM role’s attached policies, since both silently block node registration without an obvious error in the eksctl output.
- GameServer IP is unreachable from outside the cluster. Confirm your node group’s security group allows inbound traffic on the specific port range Agones assigned, and check that the node has a public IP or is behind a properly configured NAT and load balancer path for game traffic.
Advanced Tips: Multi-Region Fleets, Spot Capacity, and Security Hardening
Once a single-region fleet is stable, the next step for most studios is running identical Fleet and FleetAutoscaler manifests across multiple clusters in different regions, with a global matchmaker that picks the closest cluster based on player latency rather than a fixed region assignment. Agones does not handle cross-region routing itself, so this layer has to be built on top, typically with a thin service that queries each regional allocator and picks the fastest response.
For cost control, mix Spot capacity into your node groups for the warm buffer servers, since a Spot interruption just means Agones reschedules that particular GameServer, and the FleetAutoscaler backfills it from the buffer automatically. Keep allocated, in-match servers on On-Demand or Reserved node pools using node taints and tolerations, since losing a server mid-match to a Spot interruption is a far worse player experience than losing an idle, unallocated one.
On security, take advantage of the restricted security context Agones 1.61.0 added for the SDK sidecar, and apply the same principle to your own game server container by running as a non-root user wherever your engine allows it. Lock down the Agones allocator’s TLS configuration to only the client certificates your matchmaker actually uses, and rotate those certificates on a schedule rather than leaving the defaults in place indefinitely.
The Complete Working Project: File Structure Recap
By the end of this tutorial, your project directory should contain everything needed to redeploy this fleet from scratch on a fresh cluster.
agones-demo/
cluster.yaml
Dockerfile
main.go
go.mod
gameserver.yaml
fleet.yaml
fleetautoscaler.yaml
allocation.yaml
That’s the full loop: a provisioned EKS cluster, Agones 1.61 installed and managing the custom resources, a containerized game binary that speaks the Agones SDK, a Fleet keeping warm capacity ready, a FleetAutoscaler reacting to demand, and a tested allocation path a real matchmaker can call. From here, the realistic next step is swapping the placeholder Go binary for your actual engine’s dedicated server build and pointing your production matchmaking service at the allocator endpoint instead of the manual kubectl create commands used for testing.
If this self-managed path feels heavier than your team wants to own long-term, pair it with the broader container orchestration options covered in our ECS vs EKS cost comparison, or look at how AWS Fargate handles container deployment without node management for workloads that don’t need Agones’ game-specific allocation model. Studios tracking spend across a growing cluster footprint may also want the monitoring setup in our Kubecost and OpenCost tutorial, and anyone provisioning this infrastructure repeatedly across environments should look at the Terraform and Kubernetes multi-cloud walkthrough rather than running eksctl by hand every time. For the broader pricing picture across providers, our AWS vs Azure vs GCP cost comparison covers how compute pricing diverges once you’re running clusters at scale. For more tutorials and news covering the rest of the cloud computing stack, see our ongoing cloud computing coverage.
Frequently Asked Questions
Is Agones free to use?
Yes. Agones is an open-source project and carries no licensing fee. The only cost is the underlying compute, storage, and networking for the Kubernetes cluster it runs on.
Which Kubernetes versions does Agones 1.61 support?
Agones 1.61.0 officially supports Kubernetes 1.34, 1.35, and 1.36, and runs on Amazon EKS, Google Kubernetes Engine, Azure Kubernetes Service, and Minikube for local development.
Do I need Amazon EKS specifically, or can I use any Kubernetes cluster?
Any conformant Kubernetes cluster in the supported version range works. This tutorial uses EKS because of its tight integration with ECR and IAM, but the same Agones manifests apply unchanged on GKE, AKS, or a self-managed cluster.
Can Agones and Amazon GameLift Servers run side by side?
Yes, though most studios pick one as their primary path rather than running both in production simultaneously. AWS has published migration documentation specifically for studios moving from a Kubernetes and Agones setup onto GameLift Servers, which suggests this is a common transition rather than a rare one.
Why did my GameServer never reach Ready state?
The most common cause is a game binary that never calls the SDK’s ready function. Check the sidecar container’s logs first, since Agones logs the handshake attempt there before it ever touches your controller dashboard.
How many players can a single Agones fleet support?
There’s no hard cap in Agones itself. The real ceiling is your node group’s total CPU, memory, and network capacity, plus how many concurrent GameServer pods a single node can schedule. Studios running large live-service titles typically run dozens of fleets across multiple node groups rather than one giant fleet.
Does Agones support Windows containers for Windows-only game engines?
Agones primarily targets Linux containers, which covers the majority of dedicated server builds for modern engines. Windows container support exists in the broader Kubernetes ecosystem but is less commonly used for Agones-managed fleets in production.
Is it cheaper to self-host with Agones than to use a managed service?
It depends on your team size and on-call capacity, not just raw compute pricing. A published cost analysis comparing a 3,000 concurrent-user fleet found a meaningful gap between the cheapest self-managed Agones setup and a fully managed alternative, but that comparison doesn’t account for the engineering time needed to operate the cluster, which can close or even reverse the gap for smaller teams.
Related Coverage
Update log
Yusuf Demir
Yusuf Demir is the Cloud & Software Reporter at TrendinTech, where he covers cloud infrastructure, enterprise platforms, developer tools and the digital transformation of businesses in the UK and the United States. He is most interested in the gap between vendor roadmaps and the systems engineers actually run, and in what the cloud bill looks like once the free credits expire.
All stories by Yusuf Demir (365)
![AWS Fargate: Deploy Containers in 13 Steps, 70 Min [2026]](https://trendintech.com/wp-content/uploads/2026/10/aws-fargate-tutorial-deploy-containers-2026-gen-640x360.webp)
![Nvidia, AMD, Google, Meta Set 2-Second Grid Standard [2026]](https://trendintech.com/wp-content/uploads/2026/10/nvidia-amd-google-meta-data-center-standard-2026-640x360.webp)