Running a multiplayer game at scale means solving a problem that has nothing to do with gameplay: how do you spin up, track, and tear down thousands of dedicated game server processes without losing a single active match? Kubernetes was built for stateless web apps, not long-lived UDP game sessions that can’t just be killed mid-round. That gap is exactly what Agones fills, and as of September 2026 it’s the most widely deployed open-source answer to the problem, backed by Google Cloud and Ubisoft and running in production behind titles from multiple major studios.
This tutorial walks through installing Agones 1.60 on a real Kubernetes cluster, deploying a Fleet of dedicated game servers, wiring up autoscaling so capacity tracks player demand, and allocating servers to matches through the SDK. By the end you’ll have a working multiplayer backend running on GKE, EKS, AKS, or Minikube, plus the troubleshooting knowledge to keep it healthy in production.
Expect roughly 90 minutes for the first pass through the entire setup, longer if this is your first time operating a Kubernetes cluster hands-on. Everything here assumes a working knowledge of kubectl and basic Kubernetes objects like Pods and Services — Agones builds on top of those concepts rather than replacing them, which is exactly why studios pick it over a fully proprietary game-hosting stack. You keep every bit of Kubernetes tooling you already know (Helm, kubectl, your existing CI/CD pipelines, your existing observability stack) and layer game-server-aware scheduling on top.
Don't miss new tech stories on Google
Add Tech Insider once in the Google app and our stories appear in your news suggestions.
What Is Agones and Why Kubernetes Needs It for Game Servers
Agones started as a joint project between Google Cloud Platform and Ubisoft, first shown publicly at Google Cloud Next. The project’s own documentation describes it plainly: Agones is a library for hosting, running and scaling dedicated game servers on Kubernetes, according to the project’s GitHub README. Google Cloud’s original announcement post framed it the same way, calling Agones “a batteries-included, open-source, dedicated game server hosting and scaling project built on top of Kubernetes, with the flexibility you need to tailor it to the needs of your multiplayer game.”
Stock Kubernetes doesn’t know the difference between a game server process mid-match and a stale pod it should reap. A Deployment will happily kill a Pod running an active 20-player match because a rolling update said so. Agones solves this by adding custom resources on top of Kubernetes: GameServer, Fleet, GameServerAllocation, and FleetAutoscaler. These extend the Kubernetes API so the scheduler understands game server lifecycle states like Ready, Allocated, and Shutdown, and won’t terminate a server that’s mid-match just because a node drain kicked off.
The project has kept a fast release cadence through 2026. As of early September 2026, the agones-dev/agones GitHub fork has crossed 7,000 stars, with v1.60.0 marked as the latest release (shipped August 12, 2026) after more than 116 tagged releases. The googleforgames/agones name now redirects to that same repository (GitHub’s API resolves it to agones-dev/agones) — there is no separate upstream repo with its own, lower star count. Both forks track the same core project; the tooling in this guide works against either.
The release history through 2026 shows a project actively chasing new Kubernetes features rather than coasting on a stable API. The 1.57.0 release (April 7, 2026) added Kubernetes 1.35 support, init sidecar containers, and a Grafana Helm chart upgrade. The 1.58.0 release followed with a Go version bump and official Python SDK support. By 1.60.0, the project had moved its own build toolchain to Go 1.26.5, added stable support for a PortPolicyNone mode, enhanced CRD patching so you can update running Fleets without a full replacement, and further polished the Minikube-based local development loop. None of that matters if you’re just kicking the tires, but it matters a lot once you’re running Agones against a fleet of production clusters and need confidence the project is still actively maintained against the Kubernetes versions your cloud provider ships.
Prerequisites and Versions You’ll Need
Get these installed and verified before you touch a single YAML file. Version mismatches are the single most common reason an Agones install silently fails to schedule game servers.
| Requirement | Minimum Version | Notes |
|---|---|---|
| Kubernetes cluster | 1.34, 1.35, or 1.36 | Agones 1.60 documentation lists these three as the officially supported versions; GKE, AKS, EKS, and Minikube are all supported |
| Agones | 1.60.0 | Latest stable release as of August 12, 2026, per the agones-dev/agones GitHub release page |
| Helm | 3.x | Used for the recommended install method |
| kubectl | Matching your cluster’s minor version | Client skew more than one minor version off the server can break CRD operations |
| Go | 1.26.5 (only if building from source) | Agones 1.60 upgraded its own build toolchain to Go 1.26.5 |
| Docker or Podman | Any current release | For building your game server container image |
| Local dev option | Minikube | Agones 1.60 shipped an improved Minikube development workflow specifically for local testing |
You’ll also need a game server binary that speaks the Agones SDK protocol (gRPC or REST), or you can start with the official SDK examples to get the plumbing right before wiring in real game logic. Agones ships SDKs for C++, C#, Go, Node.js, Python, Rust, and Unreal/Unity bindings, and as of the 1.58 release added first-class Python SDK support.
Step 1: Choose and Provision Your Kubernetes Cluster
Agones is cluster-agnostic by design. The official installation docs confirm support across Google Kubernetes Engine, Azure Kubernetes Service, Amazon EKS, and Minikube, with a compatibility table mapping each Agones release to its supported Kubernetes minor versions. For this tutorial we’ll use GKE as the primary example since it’s the reference platform the Agones maintainers test against most heavily, but the commands are nearly identical on EKS or AKS once the cluster exists.
A production game server cluster needs a dedicated node pool, separate from your regular workloads, because Agones game server Pods use hostPort networking and shouldn’t be packed alongside unrelated services.
gcloud container clusters create agones-tutorial \
--cluster-version=1.35 \
--machine-type=e2-standard-4 \
--num-nodes=3 \
--no-enable-autoupgrade \
--tags=game-server
gcloud container node-pools create game-server-pool \
--cluster=agones-tutorial \
--machine-type=e2-standard-4 \
--num-nodes=3 \
--node-taints=agones.dev/agones=true:NoExecute \
--tags=game-server
The taint on the dedicated node pool matters. It stops the Kubernetes scheduler from placing unrelated Pods on nodes reserved for game servers, and Agones automatically adds the matching toleration to Pods it creates for you.
Choosing Between GKE, EKS, and AKS for an Agones Cluster
All three managed Kubernetes offerings pass the compatibility bar Agones documents, but they aren’t identical in practice. GKE tends to be the smoothest path because the Agones maintainers themselves develop and test primarily against it, and Google Cloud’s own documentation cross-links to Agones directly. EKS requires a bit more manual work around node group taints and the AWS Load Balancer Controller if you’re also running other workloads in the same account, but is otherwise a straightforward target once the node pool and taints from this step are in place. AKS works the same way, though teams running Windows-based game server containers alongside Linux control-plane components should pay close attention to node pool OS types, since Agones’ controller components are Linux-only. None of this changes the YAML you write in later steps — a Fleet manifest is identical regardless of which managed Kubernetes service is underneath it, which is the entire point of building on standard Kubernetes APIs instead of a proprietary hosting layer.
Step 2: Install Agones 1.60 via Helm
Helm is the installation path the Agones project recommends and documents most thoroughly. Add the repo, then install into a dedicated namespace.
helm repo add agones https://agones.dev/chart/stable
helm repo update
kubectl create namespace agones-system
helm install agones --namespace agones-system \
--set agones.featureGates="PortRangesEnabled=true" \
agones/agones
Verify the controller, allocator, and extensions Pods all report Running before continuing:
kubectl get pods --namespace agones-system
# Expected output:
# NAME READY STATUS RESTARTS AGE
# agones-allocator-7b9d8f6c5d-2x4kp 1/1 Running 0 45s
# agones-controller-6c7f9b4d8f-8mzql 1/1 Running 0 45s
# agones-extensions-5d8c9f7b6c-p3wjm 1/1 Running 0 45s
# agones-ping-6f8d7c9b5d-9xnrt 1/1 Running 0 45s
If any Pod is stuck in Pending, it’s almost always the node taint from Step 1 blocking scheduling — the control plane Pods don’t need to run on the tainted game server pool, so double-check your node selectors before assuming Agones itself is broken.
Step 3: Define Your First GameServer
A GameServer is the smallest unit Agones manages: one Pod wrapping your game binary, with an Agones SDK sidecar handling health checks and lifecycle signaling. Here’s a minimal manifest using the Agones example “simple-game-server” image, useful for confirming the pipeline works before you swap in your real binary.
apiVersion: agones.dev/v1
kind: GameServer
metadata:
generateName: match-server-
spec:
ports:
- name: default
portPolicy: Dynamic
containerPort: 7654
protocol: UDP
template:
spec:
containers:
- name: game-server
image: us-docker.pkg.dev/agones-images/examples/simple-game-server:0.32
resources:
requests:
memory: "64Mi"
cpu: "20m"
limits:
memory: "128Mi"
cpu: "100m"
Apply it and watch the state transition from Scheduled to Ready:
kubectl apply -f gameserver.yaml
kubectl get gameserver -o wide
# NAME STATE ADDRESS PORT NODE
# match-server-4kd8n Ready 34.123.45.67 7681 gke-agones-tutorial-pool-abc123
The dynamically assigned port and node IP are exactly what a matchmaker needs to hand a client for a direct UDP connection — no extra load balancer hop, which is precisely the latency Agones is designed to strip out of the connection path.
Step 4: Deploy a Fleet Instead of One-Off Servers
Production traffic never needs exactly one game server. A Fleet manages a warm pool of identical GameServer replicas so there’s always capacity sitting Ready when a match needs to start.
apiVersion: agones.dev/v1
kind: Fleet
metadata:
name: match-fleet
spec:
replicas: 10
template:
spec:
ports:
- name: default
portPolicy: Dynamic
containerPort: 7654
protocol: UDP
template:
spec:
containers:
- name: game-server
image: us-docker.pkg.dev/agones-images/examples/simple-game-server:0.32
resources:
requests:
memory: "64Mi"
cpu: "20m"
limits:
memory: "128Mi"
cpu: "100m"
kubectl apply -f fleet.yaml
kubectl get fleet match-fleet
# NAME SCHEDULING DESIRED CURRENT ALLOCATED READY AGE
# match-fleet Packed 10 10 0 10 12s
Notice the ALLOCATED and READY columns — this distinction is the whole point of Agones. Ready servers are idle capacity waiting for a match; Allocated servers are actively hosting one. Your matchmaker only ever touches the Allocated count, and the Fleet controller backfills Ready capacity automatically as matches end.
Step 5: Allocate a GameServer for a Match
Allocation is how your matchmaking service claims one Ready server from the Fleet and marks it Allocated so nothing else grabs it. This happens through the Agones allocator service, either via gRPC directly or through a GameServerAllocation resource.
apiVersion: allocation.agones.dev/v1
kind: GameServerAllocation
spec:
selectors:
- matchLabels:
agones.dev/fleet: match-fleet
kubectl create -f allocation.yaml -o yaml
# status:
# state: Allocated
# address: 34.123.45.67
# port: 7724
# nodeName: gke-agones-tutorial-pool-abc123
In a real matchmaking pipeline you wouldn’t hit the Kubernetes API from a public-facing service. Instead your matchmaker calls the agones-allocator gRPC endpoint directly over mTLS, which is the pattern the project documents for anything internet-facing. The allocator service is deployed automatically by the Helm chart and exposes a dedicated Service you can front with your own internal load balancer.
Step 6: Wire In the Agones SDK for Health Checks and Shutdown
Your game server binary needs to talk to the Agones SDK sidecar to report health and signal state transitions — this is what lets Agones tell the difference between “crashed” and “match ended cleanly.” Here’s the pattern in Go, one of the officially maintained SDKs:
package main
import (
"log"
"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)
}
// Tell Agones this server is ready to be allocated
if err := s.Ready(); err != nil {
log.Fatalf("could not send ready message: %v", err)
}
// Keep sending health pings so Agones knows the process is alive
go func() {
tick := time.NewTicker(2 * time.Second)
for range tick.C {
if err := s.Health(); err != nil {
log.Printf("health ping failed: %v", err)
}
}
}()
// ... run match, then when the match ends:
if err := s.Shutdown(); err != nil {
log.Fatalf("could not shutdown gracefully: %v", err)
}
}
Calling Shutdown() instead of just exiting the process is what lets Agones recycle the Pod cleanly and report accurate Fleet metrics. A process that just crashes or gets OOM-killed still gets caught by the health check timeout, but that’s the slow path — always shut down gracefully when the match logic allows it.
The SDK sidecar communicates over a local gRPC connection by default, with a REST-over-HTTP gateway also available for languages or engines where a gRPC client is impractical to embed — this is the path most Unity and Unreal integrations use, since it avoids pulling a full gRPC stack into the game engine’s runtime. Whichever transport you pick, the sidecar itself is injected automatically into every Pod Agones creates, so there’s no extra manifest work beyond making sure your container image includes a client that can reach localhost on the sidecar’s port.
Step 7: Set Up a FleetAutoscaler
A static Fleet of 10 replicas is fine for a demo, but real player traffic swings by time of day and by launch events. The FleetAutoscaler resource watches the ratio of Ready to Allocated servers and resizes the Fleet automatically.
apiVersion: autoscaling.agones.dev/v1
kind: FleetAutoscaler
metadata:
name: match-fleet-autoscaler
spec:
fleetName: match-fleet
policy:
type: Buffer
buffer:
bufferSize: 5
minReplicas: 10
maxReplicas: 100
This policy keeps a constant buffer of 5 Ready servers on top of whatever is currently Allocated, scaling the Fleet between 10 and 100 replicas as demand shifts. For workloads with more complex scaling logic — say, you want to factor in queue depth from an external matchmaker — Agones also supports a Webhook policy type that calls out to your own scaling service instead of using the built-in buffer math.
| Policy Type | How It Decides | Best For |
|---|---|---|
| Buffer | Maintains a fixed count (or percentage) of Ready servers above current Allocated count | Most titles — simple, predictable, no external dependency |
| Webhook | Calls an external HTTP endpoint you control, which returns the desired replica count | Titles with custom matchmaking queue-depth signals or scheduled-event traffic spikes |
Start with Buffer. It’s simpler to reason about, ships with sensible defaults, and covers the vast majority of production traffic patterns without any code beyond the YAML shown above. Move to Webhook only once you have a concrete signal — like a matchmaker queue that’s growing faster than the Buffer policy reacts to — that a custom scaling function would actually improve on.
Step 8: Configure Node Autoscaling to Back the Fleet
FleetAutoscaler resizes the number of GameServer Pods, but those Pods still need nodes to land on. Pair it with your cluster’s node autoscaler, and be deliberate about scale-down behavior — you do not want the cluster autoscaler draining a node that’s hosting live matches.
gcloud container node-pools update game-server-pool \
--cluster=agones-tutorial \
--enable-autoscaling \
--min-nodes=3 \
--max-nodes=20
Agones registers a PreStop hook and pod disruption budget behavior that delays node drains until Allocated GameServers finish, but this safety net only works if the cluster autoscaler is configured to respect pod disruption budgets — verify that setting explicitly rather than assuming the default is safe for your cloud provider.
Step 9: Add Observability With the Grafana Helm Chart
Agones 1.57 shipped an upgraded Grafana Helm chart specifically for game server fleet dashboards, covering Ready/Allocated/Shutdown counts, allocation latency, and per-Fleet resource usage. Install it alongside Prometheus so you can see Fleet health at a glance instead of polling kubectl get fleet.
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring --create-namespace
helm upgrade agones --namespace agones-system \
--set agones.metrics.prometheusServiceDiscovery=true \
--reuse-values agones/agones
Import the Agones dashboard JSON from the project’s install directory into Grafana, and you’ll immediately get panels tracking Fleet size against Allocated count over time — the single most useful graph for catching a FleetAutoscaler misconfiguration before players notice queue times spike.
Step 10: Handle Multi-Region Deployment for Latency
A single-region Agones cluster works for a regional launch, but global titles need game servers close to players in every major market. Agones itself doesn’t do multi-cluster allocation out of the box — that’s a gap third-party platforms have built businesses around. Edgegap, for example, layers a usage-based edge network on top of orchestration concepts similar to Agones, with pricing published as of September 2026 at $0.00115 per dedicated vCPU-minute for on-demand Edge Cloud compute, billed at $0 when idle, plus $0.10 per GB of monthly network egress, spread across more than 615 edge locations.
If you’re staying self-managed with Agones, the standard pattern is running one Agones-managed cluster per region (GKE in us-central1, eu-west1, asia-southeast1, and so on) and putting a region-aware matchmaker in front of all of them, choosing a target cluster based on measured client latency before calling that region’s allocator endpoint.
Step 11: Lock Down the Allocator With mTLS
The allocator service is the one component of an Agones deployment that’s designed to be reachable from outside the cluster, which makes it the piece you need to secure hardest. Agones issues its own client certificates for allocator authentication by default.
kubectl get secret allocator-client.default \
--namespace agones-system -o jsonpath='{.data.tls\.crt}' | base64 -d > client.crt
kubectl get secret allocator-client.default \
--namespace agones-system -o jsonpath='{.data.tls\.key}' | base64 -d > client.key
Your matchmaking service loads this cert/key pair and presents it on every gRPC call to the allocator. Never expose the raw Kubernetes API server to your matchmaker as a shortcut — the allocator exists specifically so external services never need direct cluster-admin credentials just to claim a game server.
Step 12: Test Locally With Minikube Before Deploying to Production
Agones 1.60 specifically called out an improved Minikube development workflow as a headline feature, making local iteration far less painful than earlier releases. Use this loop before pushing any Fleet or FleetAutoscaler change to a shared cluster.
minikube start --kubernetes-version=1.36.0 --cpus=4 --memory=8192
helm install agones --namespace agones-system --create-namespace \
--set agones.controller.healthCheck.initialDelaySeconds=3 \
agones/agones
kubectl apply -f gameserver.yaml
kubectl get gameserver -w
Running the health check with a shorter initial delay locally speeds up your test cycle considerably, since Minikube’s single-node cluster doesn’t need the longer warm-up window a multi-node production cluster does.
Complete Working Project: Putting It All Together
Here’s the full manifest set for a small but functioning production setup: a Fleet with autoscaling, ready to accept allocations from a matchmaker. Save each block as its own file and apply in order.
# 01-fleet.yaml
apiVersion: agones.dev/v1
kind: Fleet
metadata:
name: production-fleet
namespace: default
spec:
replicas: 20
scheduling: Packed
template:
metadata:
labels:
game: my-multiplayer-title
spec:
health:
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
ports:
- name: default
portPolicy: Dynamic
containerPort: 7654
protocol: UDP
template:
spec:
containers:
- name: game-server
image: your-registry/your-game-server:1.0.0
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
---
# 02-autoscaler.yaml
apiVersion: autoscaling.agones.dev/v1
kind: FleetAutoscaler
metadata:
name: production-fleet-autoscaler
namespace: default
spec:
fleetName: production-fleet
policy:
type: Buffer
buffer:
bufferSize: 10
minReplicas: 20
maxReplicas: 200
Deploy with kubectl apply -f 01-fleet.yaml -f 02-autoscaler.yaml, confirm both resources report healthy, then point your matchmaking service’s allocator client at the cluster’s agones-allocator Service endpoint. That’s a complete, scalable dedicated game server backend running on standard Kubernetes tooling and APIs — which is precisely the capability the Agones project set out to give Kubernetes natively.
Verifying the Full Stack End to End
Before calling the setup done, run through a full allocation cycle manually. Create a GameServerAllocation against production-fleet, confirm the returned IP and port actually accept a connection from your game client, then let the match run to completion and confirm the server transitions back to a fresh Ready state (or gets recycled and replaced, depending on your Fleet’s replicas and scheduling strategy) within a few seconds. If that full loop works — allocation, connection, gameplay, clean shutdown, capacity backfill — the infrastructure layer is done and any remaining bugs belong to your game logic, not to Kubernetes or Agones.
Integrating a Real Matchmaker With Open Match
Everything up to this point assumes a matchmaker already exists and just needs to call the Agones allocator. If you don’t have one yet, Open Match is the companion open-source project most commonly paired with Agones, and the two are designed to interoperate — Open Match handles player pooling and match-formation logic, then hands off to Agones for the actual server allocation once a match is formed. This split matters because matchmaking logic (skill-based pairing, party grouping, region preference) changes constantly as a live game evolves, while server allocation logic barely changes at all once it’s working. Keeping them as separate services means you can iterate on matchmaking rules without touching the Kubernetes layer underneath.
A minimal integration looks like this: Open Match’s Director component runs a match-function to group waiting players into a proposed match, then calls the Agones allocator gRPC endpoint (using the same mTLS client certificate from Step 11) to claim a Ready GameServer for that match. The allocator response includes the IP and port, which the Director passes back to Open Match’s assignment service, which in turn notifies each matched player’s client where to connect. None of this requires touching the Fleet or FleetAutoscaler resources you already deployed — they keep managing capacity exactly as configured, oblivious to whichever matchmaking logic is calling the allocator on top.
If your title doesn’t need skill-based matchmaking — a co-op game with simple lobby codes, for instance — you can skip Open Match entirely and have your lobby service call the allocator directly, exactly as shown in Step 5. Open Match earns its complexity budget once match quality (not just match speed) becomes a design requirement.
Security Hardening Checklist Before Going Live
A handful of security defaults are easy to miss because Agones works out of the box without them, right up until an external penetration test or a real incident finds the gap. Run through this list before pointing real player traffic at a cluster.
Rotate the allocator’s default self-signed certificates. The certificates Helm generates on install are fine for getting started but should be replaced with certificates from your organization’s own certificate authority before launch, with a documented rotation schedule.
Restrict RBAC for anything that isn’t the Agones controller itself. CI/CD service accounts and human operators should get scoped Role bindings limited to the namespaces they actually need, not cluster-admin, since a compromised deploy pipeline with cluster-admin access can rewrite Fleet specs to point at a malicious image.
Network-policy the game-server node pool. Game server Pods generally only need to accept inbound UDP/TCP on their allocated port range and shouldn’t need arbitrary egress to the rest of your cluster’s internal services — a Kubernetes NetworkPolicy restricting east-west traffic limits blast radius if a game server process is ever compromised through a game-logic vulnerability.
Keep Agones itself patched. Because Agones ships new minor versions roughly every few weeks, treat it like any other piece of cluster infrastructure with a defined upgrade cadence rather than something installed once and forgotten.
Common Pitfalls When Running Agones in Production
1. Forgetting hostPort networking implications. Agones GameServers use hostPort, not ClusterIP Services, so each node can only host as many concurrent game servers as it has free ports in your configured range. Undersizing the port range on large nodes is a frequent cause of Pods stuck Pending.
2. Running control-plane and game-server workloads on the same node pool. This causes noisy-neighbor CPU contention and makes it much harder to reason about scale-down safety. Always taint the game-server pool separately, as shown in Step 1.
3. Skipping the SDK’s Health() ping. Without regular health pings, Agones can’t distinguish a hung process from a healthy one that’s just quiet, and it will eventually mark the server Unhealthy and recycle it mid-match.
4. Setting bufferSize too low on the FleetAutoscaler. A buffer of 1-2 servers looks efficient on a cost dashboard but means every burst of concurrent match starts creates a queue while new Pods schedule, which can take 10-30 seconds on cloud infrastructure.
5. Ignoring Kubernetes version compatibility. Agones ties each release to specific supported Kubernetes minor versions — running Agones 1.60 against Kubernetes 1.37 or newer is unsupported and can surface CRD validation errors that look unrelated to versioning.
6. Exposing the Kubernetes API directly to matchmaking services. Some early integrations skip the allocator and call the Kubernetes API server directly to create GameServerAllocation objects. This works in a demo but is a security anti-pattern in production — use the mTLS-secured allocator gRPC endpoint instead.
7. Not testing node drain behavior before a real deploy. Teams frequently discover during their first production rolling update that node drains don’t respect Allocated GameServers the way they expected, because a pod disruption budget setting was missing.
Troubleshooting: 8+ Common Agones Issues and Fixes
| Symptom | Likely Cause | Fix |
|---|---|---|
| GameServer stuck in Scheduled, never reaches Ready | SDK sidecar never received a Ready() call from your game binary | Check container logs for SDK connection errors; confirm your binary calls s.Ready() after startup |
| Pods Pending indefinitely | Node pool taint mismatch or exhausted host port range | Verify the toleration matches your taint key/value exactly; widen the containerPort range |
| Fleet shows fewer READY than DESIRED | Resource requests exceed available node capacity | Check kubectl describe node for CPU/memory pressure; scale the node pool |
| Allocator returns Unavailable errors | mTLS client cert expired or mismatched | Regenerate allocator-client secret and redistribute to the matchmaker service |
| GameServers marked Unhealthy under normal load | Health ping interval too aggressive for your game loop | Increase periodSeconds and failureThreshold in the health block |
| FleetAutoscaler not scaling up under load | maxReplicas ceiling reached, or webhook policy endpoint unreachable | Check FleetAutoscaler status conditions with kubectl describe; raise maxReplicas |
| Helm install hangs on CRD creation | Previous partial Agones install left orphaned CRDs | Run kubectl get crds | grep agones.dev and delete stale ones before reinstalling |
| Node drain kills an Allocated GameServer | Cluster autoscaler ignoring pod disruption budgets | Enable autoscaling with pod-disruption-budget-aware drain behavior on your cloud provider |
| High allocation latency (over 1s) | Buffer size too small relative to concurrent allocation rate | Increase FleetAutoscaler bufferSize and monitor the Grafana allocation-latency panel |
Agones vs Managed Alternatives: Cost and Control Tradeoffs
Agones is free and open source, but “free” only covers the software license — you still pay for the underlying Kubernetes cluster, nodes, and your own operational time. Managed edge orchestration platforms trade that operational overhead for a usage-based bill. Edgegap’s published Q3 2026 pricing illustrates the shape of that tradeoff clearly.
| Approach | Pricing Model | Example Cost | Operational Burden |
|---|---|---|---|
| Self-managed Agones on GKE/EKS/AKS | Pay for cluster nodes only | Standard cloud VM pricing (e.g., e2-standard-4 hourly rate) x node count | High — you own upgrades, scaling policy, monitoring |
| Edgegap Edge Cloud (on-demand) | Usage-based, per vCPU-minute | $0.00115/vCPU-minute, $0 when idle, plus $0.10/GB egress | Low — orchestration and edge routing managed for you |
| Edgegap Private Fleet (Performance host) | Monthly host rental | $280/month on a 12-month term, 16 vCPU / 32 GB RAM, 6 TB egress included | Medium — you manage the host, Edgegap manages allocation |
| Edgegap Private Fleet (month-to-month) | Monthly host rental, no commitment | $350/month, same Performance host spec | Medium |
The practical takeaway: self-managed Agones makes the most sense once you have the DevOps capacity to run Kubernetes well and want zero per-minute usage fees layered on top of your cloud bill. Usage-based edge platforms make sense when you need global point-of-presence coverage fast and don’t want to stand up and maintain a Kubernetes cluster in every region yourself.
Advanced Tips for Scaling Agones Beyond the Basics
Once the base Fleet and autoscaler are stable, a few advanced patterns pay off at real scale. First, use the Webhook FleetAutoscaler policy type instead of the Buffer policy once your matchmaker has its own queue-depth metrics — feeding that signal directly into scaling decisions reacts faster than the generic Ready/Allocated ratio.
Second, use GameServer Scheduling: Packed mode (the default) rather than Distributed when you’re optimizing for node-pool cost efficiency, since Packed mode concentrates Allocated servers on fewer nodes, letting the cluster autoscaler scale down idle nodes faster. Switch to Distributed only if you specifically need to spread load evenly for resilience reasons.
Packed vs Distributed Scheduling in Practice
The difference shows up most clearly during a partial outage. With Packed scheduling, a single node failure might take down several Allocated matches at once because they were all bin-packed onto the same node to maximize density. With Distributed scheduling, that same node failure spreads its blast radius across fewer matches per node, at the cost of keeping more nodes partially utilized (and therefore running) at any given time. Titles with strict uptime SLAs for ranked or competitive modes often run a Distributed-scheduled Fleet for ranked matches and a Packed-scheduled Fleet for casual modes, accepting the cost tradeoff only where match integrity actually justifies it.
Third, set explicit resource limits on every GameServer container. Agones 1.60’s enhanced CRD patching makes it easier to update these limits across a running Fleet without a full rolling replacement, so there’s no excuse for leaving requests and limits unset and letting the scheduler guess.
Fourth, if you’re supporting init logic — like downloading match assets before a server reports Ready — take advantage of the init sidecar container support Agones added in the 1.57 release rather than baking that logic into your main game server entrypoint. It keeps startup failures cleanly separated from game-logic failures in your logs.
Monitoring and Cost Control Once You’re Live
The Grafana dashboards from Step 9 give you visibility, but pair them with billing alerts on your cloud provider tied to the game-server node pool specifically, separate from the rest of your infrastructure spend. Because Fleet size scales automatically, a runaway FleetAutoscaler misconfiguration (say, a maxReplicas set several orders of magnitude too high) can produce a cloud bill spike overnight with nobody watching. Set a hard maxReplicas ceiling you’ve sanity-checked against your actual concurrent-player ceiling, not an arbitrary round number.
For teams also tracking cost across their broader Kubernetes footprint, it’s worth comparing how Kubernetes cost tools handle spend visibility, since game-server node pools tend to be the single largest line item on a multiplayer title’s infrastructure bill and benefit from the same granular cost attribution as any other workload.
Frequently Asked Questions
Is Agones free to use?
Yes. Agones is fully open source, maintained jointly with contributions from Google Cloud and Ubisoft. There’s no license fee; your only costs are the Kubernetes cluster and nodes you run it on.
What Kubernetes versions does Agones 1.60 support?
Per the official Agones documentation, version 1.60 supports Kubernetes 1.34, 1.35, and 1.36 across GKE, AKS, EKS, and Minikube.
Can I run Agones on a single-node cluster for testing?
Yes, using Minikube. Agones 1.60 specifically improved its Minikube development workflow, making local single-node testing considerably smoother than in earlier releases.
Does Agones handle matchmaking?
No. Agones handles hosting, allocation, and scaling of the dedicated game server processes themselves. Matchmaking logic — deciding which players go into which match — is left to your own service, which then calls the Agones allocator to claim a server once a match is formed.
What’s the difference between a GameServer and a Fleet?
A GameServer is a single managed instance. A Fleet manages a pool of identical GameServer replicas with a target size, letting you maintain warm Ready capacity instead of creating servers on demand one at a time.
How does Agones compare to using Edgegap or a similar managed platform?
Agones is self-managed software you run on your own Kubernetes cluster with no per-minute fees beyond your cloud infrastructure bill. Managed platforms like Edgegap charge usage-based rates (for example, $0.00115 per vCPU-minute as of September 2026) in exchange for handling orchestration, global edge placement, and scaling operations for you.
Which programming languages have official Agones SDK support?
The project maintains SDKs for Go, C++, C#, Node.js, Rust, and Python, with the Python SDK added as of the 1.58 release, plus integration helpers for Unity and Unreal Engine projects.
What happens if a GameServer crashes mid-match?
If the process stops sending Health() pings, Agones marks it Unhealthy after the configured failureThreshold is exceeded and recycles the Pod. This is a fallback path — a graceful Shutdown() call from your game logic is always preferable since it avoids the health-check timeout delay.
Related Coverage
- How to Autoscale Game Servers With Kubernetes HPA: 12 Steps [2026]
- Multiplayer Game Servers on Cloudflare Durable Objects: 14 Steps [2026]
- Deploy Agones on Kubernetes: 12 Steps, 90 Min [2026]
- Kubernetes Ingress Setup: 12 Steps After NGINX EOL [2026]
- Kubernetes 1.37 Upgrade Guide: Fix 3 Breaking Changes in 12 Steps [2026]


