Dedicated Game Server on Kubernetes: 13 Steps [2026]

Dedicated game servers keep competitive and social multiplayer titles fair: every player connects to the same authoritative simulation instead of trusting a peer’s machine. Running those servers by hand, one VM at a time, stopped scaling years ago. In 2026, the default answer is Kubernetes, and the tool that makes Kubernetes speak “game server” is Agones, the open-source project built by Google Cloud and Ubisoft. This tutorial walks through installing Agones 1.61 on a real cluster, deploying a dedicated game server, scaling it with a Fleet and FleetAutoscaler, securing it, and knowing when to hand operations off to a managed service like Amazon GameLift Servers.

By the end you will have a working dedicated game server running on Kubernetes, a Fleet that keeps warm capacity ready for players, an autoscaler that reacts to demand, and a migration path to GameLift for teams that would rather not run Kubernetes themselves. Expect to spend roughly 90 minutes end to end if you already have a cloud account and kubectl installed.

Google · Preferred Sources

Don't miss new tech stories on Google

Add Tech Insider once in the Google app and our stories appear in your news suggestions.

Add Now

Why Dedicated Game Servers Still Belong on Kubernetes in 2026

Peer-to-peer hosting is fine for casual co-op games, but anything with ranked matchmaking, anti-cheat requirements, or a persistent world needs a dedicated game server that the developer controls. The problem has always been operational: dedicated servers need fast pod replacement when a process crashes, session-aware routing so a player reconnects to the correct instance, and autoscaling that matches player counts instead of CPU averages. Generic Kubernetes deployments were not built for any of that, which is exactly the gap Agones closes.

Agones extends the Kubernetes controller model with custom resources purpose-built for game servers: GameServer, Fleet, and FleetAutoscaler. A GameServer wraps a single game server process and tracks its lifecycle through states like Scheduled, RequestReady, Ready, Allocated, and Shutdown. A Fleet manages a pool of GameServers the same way a Deployment manages stateless pods, except it understands that a “ready” game server is not interchangeable with a “ready” web server pod: allocated servers cannot simply be deleted mid-match. Agones 1.61.0 shipped on September 24, 2026 and runs on Kubernetes 1.34 through 1.36, which means it tracks the same Kubernetes release cadence most managed clusters are already on.

The other reason Kubernetes still wins for game server hosting is portability. Agones deploys identically on Amazon EKS, Google Kubernetes Engine, Azure Kubernetes Service, or a local Minikube cluster for testing, so a studio is not locked to one cloud simply because it picked a game server orchestrator. That portability matters more in 2026 than it did a few years ago, since GPU and compute pricing swings between AWS, Google Cloud, and Azure have made multi-cloud game infrastructure a real cost lever rather than a theoretical one.

The project also keeps shipping at a steady clip instead of stalling out the way some infrastructure tools do once their original backers move on. Agones 1.60 landed shortly before 1.61 and added Kubernetes 1.36 support, upgraded its internal Go toolchain to Go 1.26.5, stabilized the PortPolicyNone setting for teams that manage their own port allocation externally, and improved how the controller patches custom resource definitions during upgrades. None of that is flashy, but it is exactly the kind of maintenance work that keeps a dedicated game server platform safe to run in production years after the initial rollout, rather than something you quietly migrate away from once the original engineering champion leaves the team.

Prerequisites: Tools and Versions You Need Before You Start

This tutorial assumes basic comfort with the command line and a passing familiarity with Kubernetes pods and YAML. You do not need prior Agones experience. Install and verify the following before Step 1.

ToolMinimum VersionPurpose
Kubernetes cluster1.34, 1.35, or 1.36Runs Agones and your game server pods (EKS, GKE, AKS, or Minikube)
kubectl1.34 or newerApplies manifests and inspects GameServer status
Helm3.14 or newerInstalls the Agones controller and CRDs
Docker or PodmanRecent stable releaseBuilds the game server container image
Agones1.61.0The game server orchestration layer itself
Cloud CLI (aws, gcloud, or az)LatestProvisions the managed cluster if not using Minikube

You also need at least three worker nodes with a combined 4 vCPUs and 8 GB of memory free for this walkthrough, plus firewall or security group rules that allow inbound UDP traffic on the port range Agones assigns to game servers (7000 to 8000 by default). If you are testing locally, Minikube with the Minikube driver documentation covers the extra steps needed to expose host ports to a local cluster.

Testing Locally With Minikube Before You Touch Production

Skip straight to a managed cloud cluster and you will end up debugging Agones behavior and cloud networking quirks at the same time, which makes every problem harder to isolate. A local Minikube cluster removes the cloud variable entirely, so you can confirm the GameServer lifecycle, Fleet scaling, and allocation flow work before you spend money on cloud compute.

minikube start --kubernetes-version=v1.36.1 --cpus=4 --memory=8192
minikube addons enable ingress

helm repo add agones https://agones.dev/chart/stable
helm repo update
kubectl create namespace agones-system
helm install agones-release agones/agones -n agones-system --version 1.61.0 \
  --set agones.featureGates="NodeExternalDNS=false"

Minikube does not expose UDP host ports the same way a cloud load balancer does, so for local testing you will usually port-forward directly to a specific GameServer pod instead of relying on the dynamically assigned node port. That is a reasonable tradeoff for local iteration, but do not treat a working Minikube deployment as proof your firewall rules or security groups are correct on the real cluster, they are two entirely separate checks.

Step 1: Provision a Kubernetes Cluster for Game Servers

Agones needs a real Kubernetes cluster, not just a namespace inside a shared one, because it installs cluster-scoped custom resource definitions and a controller with elevated permissions. For production game server hosting, use a managed cluster on Amazon EKS, GKE, or AKS so node pool scaling and upgrades stay someone else’s problem. For this tutorial, any of the three works identically once the cluster is reachable through kubectl.

Create a dedicated node pool for game server workloads rather than mixing them with your general application pods. Game server pods hold UDP ports open for the life of a match and should not be evicted casually, so isolating them lets you apply different node affinity, taint, and autoscaling rules than the rest of your cluster.

eksctl create cluster \
  --name game-servers-cluster \
  --region us-east-1 \
  --nodegroup-name gameserver-pool \
  --node-type c6i.xlarge \
  --nodes 3 \
  --nodes-min 3 \
  --nodes-max 10 \
  --kubernetes-version 1.36

Once the cluster reports Active, point kubectl at it and confirm node readiness before moving on.

kubectl get nodes -o wide
NAME                          STATUS   ROLES    AGE   VERSION
ip-192-168-14-201.ec2.internal   Ready    <none>   2m    v1.36.1
ip-192-168-32-88.ec2.internal    Ready    <none>   2m    v1.36.1
ip-192-168-51-19.ec2.internal    Ready    <none>   2m    v1.36.1

Step 2: Install Agones 1.61 With Helm

Agones ships an official Helm chart that installs the controller, the custom resource definitions for GameServer, Fleet, and FleetAutoscaler, and a validating webhook that enforces schema rules on those resources. Add the repository, create a dedicated namespace, and install the chart pinned to the current release.

helm repo add agones https://agones.dev/chart/stable
helm repo update

kubectl create namespace agones-system

helm install agones-release agones/agones \
  --namespace agones-system \
  --version 1.61.0

The chart also labels one or more of your nodes for game server scheduling. By default Agones expects nodes labeled agones.dev/agones-system=true for the controller and lets game server pods land on any untainted node. For a dedicated node pool, label it explicitly so the scheduler places game servers only where you expect.

kubectl label nodes ip-192-168-14-201.ec2.internal agones.dev/agones-gameserver=true
kubectl label nodes ip-192-168-32-88.ec2.internal agones.dev/agones-gameserver=true
kubectl label nodes ip-192-168-51-19.ec2.internal agones.dev/agones-gameserver=true

Step 3: Verify the Agones Controller, CRDs, and Webhooks

Before deploying a dedicated game server, confirm every Agones component reports healthy. A common early mistake is applying a GameServer manifest before the webhook pods finish starting, which produces a cryptic admission error instead of a clear “not ready” message.

kubectl get pods -n agones-system

NAME                                      READY   STATUS    RESTARTS   AGE
agones-controller-7d8f6c9b45-k2xpl        1/1     Running   0          58s
agones-extensions-6c9d7f8b4-mq7rt         1/1     Running   0          58s
agones-ping-7f5b8c9d4-vw2kd               1/1     Running   0          58s
agones-allocator-5d7c8b9f6-jn4pz          1/1     Running   0          58s

Then confirm the CRDs registered correctly. You should see gameservers, fleets, gameserversets, and fleetautoscalers as available API resources.

kubectl api-resources | grep agones

fleetautoscalers      fas      agones.dev/v1   true   FleetAutoscaler
fleets                        agones.dev/v1   true   Fleet
gameserverallocations         allocation.agones.dev/v1   true   GameServerAllocation
gameservers            gs       agones.dev/v1   true   GameServer
gameserversets          gss      agones.dev/v1   true   GameServerSet

Step 4: Containerize a Dedicated Game Server Binary

Agones does not care what engine built your game server. It needs the binary to call the Agones SDK to signal Ready, Health, and Shutdown, and it needs the process packaged into a container image. Most engines expose an Agones SDK wrapper: Unreal, Unity, and Godot integrations all exist in the open-source project. The example below uses a generic Go-based dedicated server binary to keep the Dockerfile engine-agnostic.

FROM golang:1.26 AS build
WORKDIR /app
COPY . .
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux go build -o gameserver ./cmd/server

FROM gcr.io/distroless/static-debian12
COPY --from=build /app/gameserver /gameserver
EXPOSE 7654/udp
ENTRYPOINT ["/gameserver"]

Build and push the image to a registry your cluster can reach. Amazon ECR, Google Artifact Registry, and Azure Container Registry all work identically for this step, and this same registry step is what you reuse later if you migrate to GameLift, since GameLift Servers also pulls container images from a registry rather than uploading raw binaries.

docker build -t registry.example.com/game-servers/match-server:1.0.0 .
docker push registry.example.com/game-servers/match-server:1.0.0

Step 5: Write and Apply Your First GameServer Manifest

A GameServer manifest wraps a standard pod template with an Agones-specific health check and port configuration. The ports block tells Agones which container port to map to a dynamically assigned host port, which is how multiple game server pods can share a node without port collisions.

apiVersion: agones.dev/v1
kind: GameServer
metadata:
  generateName: match-server-
spec:
  ports:
  - name: default
    portPolicy: Dynamic
    containerPort: 7654
    protocol: UDP
  health:
    initialDelaySeconds: 5
    periodSeconds: 5
    failureThreshold: 3
  template:
    spec:
      containers:
      - name: match-server
        image: registry.example.com/game-servers/match-server:1.0.0
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"

Apply it and watch the GameServer move through its lifecycle states. A healthy dedicated game server reaches Ready within a few seconds once the SDK inside the binary calls sdk.Ready().

kubectl apply -f gameserver.yaml
kubectl get gameserver -w

NAME                  STATE       ADDRESS         PORT
match-server-7xk2m     Scheduled
match-server-7xk2m     RequestReady 203.0.113.14   7412
match-server-7xk2m     Ready        203.0.113.14   7412

Step 6: Allocate a GameServer and Confirm the Ready State

A Ready GameServer is idle capacity. Allocation is the moment Agones hands that capacity to a specific match or session, moving the resource to the Allocated state so Agones will not reclaim or scale it down mid-match. In production your matchmaker calls the Agones allocator service or the GameServerAllocation API. For testing, you can allocate directly with kubectl.

cat <<EOF | kubectl create -f -
apiVersion: allocation.agones.dev/v1
kind: GameServerAllocation
spec:
  selectors:
  - matchLabels:
      agones.dev/fleet: match-server-fleet
EOF

The response returns the address and port your matchmaking backend hands to the connecting client, along with the GameServer’s new Allocated status. This handoff is what makes a dedicated game server usable inside a real matchmaking flow instead of a static, always-on endpoint.

Step 7: Build a Fleet for Multiple Server Replicas

A single GameServer is a proof of concept, not a production setup. A Fleet manages a pool of identical GameServers, maintains a target number of Ready replicas, and replaces any that crash or fail health checks, the same self-healing behavior a Kubernetes Deployment gives web pods, applied to session-aware game server processes.

apiVersion: agones.dev/v1
kind: Fleet
metadata:
  name: match-server-fleet
spec:
  replicas: 10
  template:
    spec:
      ports:
      - name: default
        portPolicy: Dynamic
        containerPort: 7654
        protocol: UDP
      health:
        initialDelaySeconds: 5
        periodSeconds: 5
      template:
        spec:
          containers:
          - name: match-server
            image: registry.example.com/game-servers/match-server:1.0.0
            resources:
              requests:
                memory: "256Mi"
                cpu: "250m"
kubectl apply -f fleet.yaml
kubectl get fleet match-server-fleet

NAME                  SCHEDULING   DESIRED   CURRENT   ALLOCATED   READY   AGE
match-server-fleet     Packed       10        10        0           10      42s

Step 8: Attach a FleetAutoscaler for Player Demand

Player counts swing hard around prime-time hours and live events, so a fixed replica count either wastes spend overnight or runs out of capacity during a launch spike. The Agones buffer-based FleetAutoscaler keeps a fixed number of Ready servers on standby at all times and grows or shrinks the Fleet automatically as Allocated servers eat into that buffer.

apiVersion: autoscaling.agones.dev/v1
kind: FleetAutoscaler
metadata:
  name: match-server-autoscaler
spec:
  fleetName: match-server-fleet
  policy:
    type: Buffer
    buffer:
      bufferSize: 5
      minReplicas: 10
      maxReplicas: 100

With bufferSize set to 5, Agones always keeps five idle Ready servers available. As players get allocated servers, the autoscaler spins up new replicas to restore that buffer, and it scales the Fleet back down once demand drops, bounded by minReplicas and maxReplicas so a traffic spike cannot silently run up your cloud bill overnight.

Step 9: Connect a Game Client to an Allocated Server

Once allocation returns an address and port, that connection information flows to the client the same way it would for any dedicated server: through your matchmaking backend’s session response, a lobby service, or a direct connect string. The client never talks to Kubernetes or Agones directly, it only ever sees a plain IP and UDP port, which keeps your game networking code identical whether the server underneath is running on Agones today or migrates to a different host later.

On the server side, the Agones SDK inside your binary should call sdk.Allocate() acknowledgment handlers and continue sending health pings for the life of the match, then call sdk.Shutdown() when the match ends so Agones can recycle or terminate the pod cleanly instead of waiting for a timeout.

It helps to think of the allocation response as a contract between three systems that otherwise know nothing about each other: Kubernetes, which only tracks pod scheduling and health, your matchmaking service, which only tracks player pairing logic, and the game client, which only tracks a connection string. Agones is the layer that translates between all three without forcing any of them to understand the others’ internals, which is precisely why teams can swap matchmaking backends or client engines later without touching the Agones layer underneath.

Step 10: Test Pod Failure and Automatic Rescheduling

Cloud-native resilience only matters if it actually works under failure, so validate it before you trust it in production. Kill a Ready GameServer pod directly and confirm the Fleet controller replaces it to restore the desired replica count.

kubectl delete pod match-server-fleet-8h2fx-gk9pl

kubectl get gameserver -l agones.dev/fleet=match-server-fleet

NAME                       STATE   AGE
match-server-fleet-8h2fx-wr3qn   Ready   3s
match-server-fleet-vn2xk-mp8th   Ready   4m
match-server-fleet-vn2xk-th9zq   Ready   4m

Note that Agones deliberately will not delete an Allocated GameServer this way, even if you try to scale the Fleet down while a match is in progress. That protection exists specifically so a mid-match crash policy or autoscaler decision never drops active players, and it is one of the biggest operational differences between Agones and a plain Kubernetes Deployment.

Step 11: Secure the Fleet With RBAC and Network Policies

Dedicated game servers accept direct UDP connections from anonymous internet clients, which makes them a bigger attack surface than an internal microservice. Two controls matter most: restrict who inside the cluster can call the Agones allocator API, and restrict which network paths reach the game server pods themselves.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: matchmaker-allocator
rules:
- apiGroups: ["allocation.agones.dev"]
  resources: ["gameserverallocations"]
  verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: matchmaker-allocator-binding
  namespace: default
subjects:
- kind: ServiceAccount
  name: matchmaker
  namespace: matchmaking
roleRef:
  kind: Role
  name: matchmaker-allocator
  apiGroup: rbac.authorization.k8s.io

Scope that Role narrowly to the matchmaking service account only. Do not grant broad cluster-admin access to anything that touches game server allocation, since a compromised matchmaker with wide permissions could allocate or drain your entire Fleet. Pair that with a NetworkPolicy that only allows the game server pods to accept UDP traffic on the Agones-assigned port range and blocks lateral movement toward other namespaces.

Step 12: Monitor Fleets With Metrics, Logs, and Alerts

Agones exposes Prometheus-compatible metrics out of the box, covering GameServer counts by state, Fleet replica counts, and allocation latency. Point your existing Prometheus scrape config at the agones-controller service, then build dashboards on top of the standard Kubernetes and Agones metric set rather than instrumenting your own.

  • Track gameservers_count broken down by state (Ready, Allocated, Error) to catch capacity problems before players notice queue times climbing.
  • Alert if Ready count drops below the FleetAutoscaler buffer for more than a minute, since that usually means nodes are out of capacity, not that Agones is broken.
  • Watch pod restart counts on the game server node pool separately from the rest of the cluster, because a crash-looping game server binary looks very different from a crash-looping web service.
  • Export Agones controller logs alongside your game server application logs so an allocation failure and a gameplay crash show up in the same timeline during an incident.

Step 13: Know When to Migrate to Amazon GameLift Servers

Running Agones yourself means you own cluster upgrades, node pool scaling, and every edge case above. That tradeoff makes sense for studios with existing Kubernetes expertise, multi-cloud requirements, or unusual networking needs. For teams that would rather not operate Kubernetes at all, Amazon GameLift Servers offers a fully managed path to the same dedicated-server model, with AWS handling fleet management, scaling, and matchmaking through FlexMatch.

The migration keeps most of your work: the same container image you built in Step 4 becomes the input to a GameLift container-group definition. Push it to Amazon Elastic Container Registry, then create the container fleet from that image instead of pointing a Kubernetes Fleet at it.

aws gamelift create-container-group-definition \
  --name match-server-group \
  --container-group-type GAME_SERVER \
  --total-memory-limit-mebibytes 1024 \
  --total-cpu-limit 512 \
  --game-server-container-definition '{
    "ContainerName": "match-server",
    "ImageUri": "123456789012.dkr.ecr.us-east-1.amazonaws.com/match-server:1.0.0",
    "PortConfiguration": {
      "ContainerPortRanges": [{"FromPort": 7654, "ToPort": 7654, "Protocol": "UDP"}]
    }
  }'

Two code changes matter most in this migration. First, swap Agones SDK calls for the GameLift Server SDK, since the Ready, Health, and Shutdown signaling pattern is conceptually the same but uses a different client library. Second, replace calls to the Agones allocator API with GameLift’s game-session queue, and optionally layer FlexMatch on top if you want AWS’s managed matchmaking instead of rolling your own. Your backend also needs to fetch connection information through GameLift APIs instead of the Agones allocator response.

GameLift added a useful safety net in August 2026: managed fleets now expire automatically one year after creation, transitioning to an EXPIRED state, emitting a fleet-expired event, and scaling to zero instances. That prevents forgotten test fleets from quietly billing for months. The same August update also added support for the C8a, C8i, C9g, M8a, M8i, and M9g EC2 instance families across managed EC2 and container fleets, giving teams newer compute options for CPU-bound simulation workloads than were available a year earlier.

Common Pitfalls When Deploying Game Servers on Kubernetes

Most Agones problems trace back to a handful of repeated mistakes, and nearly all of them show up during a launch weekend or a live event rather than during quiet testing, because that is when replica counts, connection volume, and match churn all spike at once. Watch for these before they cost you a production incident.

  • Forgetting to call sdk.Ready() in the binary. A GameServer will sit in RequestReady forever if the process never signals readiness through the SDK, and it looks identical to a networking problem until you check the application logs.
  • Using Static instead of Dynamic port policy at scale. Static ports work fine for a single test server but cause port collisions the moment you run more than one replica per node inside a Fleet.
  • Setting health check thresholds too aggressively. A failureThreshold of 1 with a 5-second period will kill and replace game servers during brief GC pauses or matchmaking spikes, churning capacity for no reason.
  • Skipping dedicated node pools. Mixing game server pods with regular application workloads means Kubernetes’ default scheduler and eviction behavior can disrupt live matches during unrelated cluster maintenance.
  • Granting matchmaking services cluster-admin. The allocator RBAC role only needs create access on GameServerAllocation resources; anything broader turns a compromised matchmaker into a cluster-wide risk.
  • Ignoring the FleetAutoscaler buffer size under bursty load. A buffer that is too small for your launch-day traffic pattern means new players wait on cold-start pods instead of connecting to already-warm ones.
  • Not testing the shutdown path. Teams frequently test Ready and Allocated flows but skip verifying that sdk.Shutdown() actually recycles the pod cleanly, which surfaces as slowly leaking capacity days after launch.

Troubleshooting Agones and Kubernetes Game Server Issues

These are the issues that come up most often once a Fleet is running under real player traffic. Most of them are diagnosable in under five minutes once you know which kubectl command to reach for, but they are confusing the first time because the failure often surfaces far from its actual cause, for example a networking misconfiguration that looks like a broken game server binary.

SymptomLikely CauseFix
GameServer stuck in ScheduledNo node matches the pod’s resource requests or node selectorCheck node capacity with kubectl describe node and confirm labels match the Fleet template
GameServer stuck in RequestReadyBinary never calls sdk.Ready()Check container logs for SDK connection errors and confirm the sidecar is running
Allocation requests time outNo Ready servers available in the FleetIncrease FleetAutoscaler bufferSize or minReplicas
Players cannot connect after allocationSecurity group or firewall blocks the Agones UDP port rangeOpen inbound UDP 7000-8000 (or your configured range) on worker nodes
Fleet will not scale downGameServers remain Allocated after the match actually endedVerify sdk.Shutdown() is called and check the shutdown replica policy
Webhook admission errors on applyAgones controller or webhook pods not fully ready yetWait for all agones-system pods to report Running before applying manifests
Helm install hangsCluster RBAC blocks CRD creationConfirm your kubectl context has cluster-admin rights for the install
High allocation latencyBuffer too small or allocator pod under-resourcedRaise bufferSize and check agones-allocator pod CPU/memory limits
Pods evicted mid-matchGame server pods sharing nodes with unrelated workloads under memory pressureMove game servers to a dedicated, tainted node pool

Agones vs Amazon GameLift Servers: Choosing the Right Path

Neither option is universally better, the right choice depends on how much Kubernetes operations work your team wants to own.

FactorAgones on KubernetesAmazon GameLift Servers
Operational ownershipYou manage cluster upgrades, node pools, and scaling policyAWS manages fleet infrastructure and scaling
Cloud portabilityRuns on EKS, GKE, AKS, or on-prem clusters identicallyAWS only
MatchmakingBring your own or integrate Open Match separatelyBuilt-in FlexMatch available
Latest releaseAgones 1.61.0 (September 24, 2026)August 2026 update added new EC2 instance families and managed-fleet expiration
Best fitTeams with existing Kubernetes skills or multi-cloud needsTeams that want managed infrastructure without running Kubernetes

A growing number of studios run both: Agones for internal testing and staging environments where engineering wants direct cluster access, and GameLift for production live-service traffic where operational overhead needs to stay low. The migration path in Step 13 exists precisely because that hybrid pattern has become common enough that AWS documents an official Agones-to-GameLift migration workflow rather than treating it as an edge case.

Cost Considerations for Kubernetes Game Server Hosting

Running Agones yourself does not mean it is free, it means the cost shifts from a managed-service bill to raw compute plus engineering time. Three line items drive most of the spend: the node pool backing your game server Fleet, the always-on buffer capacity your FleetAutoscaler maintains even when nobody is playing, and the engineering hours spent operating Kubernetes itself, including version upgrades, node image patching, and incident response.

The buffer setting from Step 8 is the single biggest lever most teams overlook. A bufferSize of 20 on a Fleet running c6i.xlarge nodes at roughly a few hundred dollars a month per node, multiplied across a multi-region deployment, adds up fast if you set it once at launch and never revisit it. Review buffer sizes against real matchmaking wait-time data on a recurring basis rather than picking a number during initial setup and leaving it untouched for a year. Pair FleetAutoscaler buffer tuning with cluster-level node autoscaling so idle capacity gets released at the infrastructure layer too, not just at the GameServer replica count.

Against that, Amazon GameLift Servers folds infrastructure management into its pricing, which trades a per-instance-hour premium for zero Kubernetes operations overhead. For a small team without dedicated infrastructure engineers, that premium is often cheaper than the fully-loaded cost of a person who understands Kubernetes networking well enough to debug a stuck GameServer at 2 a.m. during a launch weekend. Weigh the tradeoff against your team’s existing skills rather than compute price alone.

Advanced Tips: Multi-Cluster Allocation and Scaling Beyond One Region

A single-cluster Fleet works for regional launches, but global titles need capacity spread across multiple clusters in different geographic regions to keep latency low for every player. Agones supports multi-cluster allocation through the allocator service, which can route allocation requests across clusters based on capacity and, if you configure it, player proximity.

Set this up by deploying Agones independently in each regional cluster, then configuring your matchmaking backend to query multiple allocator endpoints and pick the cluster with available Ready capacity closest to the player. AWS publishes a reference multi-cluster allocation pattern for running Agones across EKS clusters that is worth studying before building a custom router, since getting allocator failover wrong under load is a common source of dropped matches during regional traffic spikes.

For cost efficiency at that scale, combine node pool autoscaling with the FleetAutoscaler so idle regional clusters scale their underlying compute down, not just the GameServer replica count. Leaving three full nodes running for a five-server buffer wastes far more than the game server pods themselves cost.

Complete Working Project: Full Manifest Reference

Bringing every piece from this tutorial together, a production-ready dedicated game server deployment on Kubernetes consists of five files applied in this order: the Agones Helm release, the Fleet manifest, the FleetAutoscaler, the RBAC role for your matchmaker, and a NetworkPolicy restricting inbound traffic.

# 1. Install Agones
helm install agones-release agones/agones -n agones-system --version 1.61.0

# 2. Deploy the Fleet
kubectl apply -f fleet.yaml

# 3. Attach the autoscaler
kubectl apply -f fleet-autoscaler.yaml

# 4. Apply matchmaker RBAC
kubectl apply -f matchmaker-rbac.yaml

# 5. Lock down network access
kubectl apply -f gameserver-networkpolicy.yaml

# 6. Confirm everything is healthy
kubectl get fleet,fleetautoscaler,gameserver -o wide

From here, your matchmaking backend calls the Agones allocator whenever it needs a server for a new match, your Fleet keeps a warm buffer of Ready capacity through the FleetAutoscaler, and your RBAC and NetworkPolicy configuration keeps that capacity from becoming an open attack surface. That is a genuinely production-capable dedicated game server platform, the same architectural pattern studios use for competitive shooters, battle royales, and persistent-world MMOs today, and it scales from a ten-server Fleet in staging to hundreds of servers spread across multiple regional clusters without changing the underlying manifests, only the replica counts and buffer sizes.

Frequently Asked Questions

What is the difference between Agones and a regular Kubernetes Deployment?
A Deployment assumes every pod is interchangeable and safe to delete at any time. Agones adds a GameServer lifecycle (Ready, Allocated, Shutdown) so Kubernetes understands that an Allocated server is hosting an active match and should not be reclaimed until it explicitly signals it is done.

Do I need Google Cloud to run Agones?
No. Agones is open source and runs identically on Amazon EKS, Google Kubernetes Engine, Azure Kubernetes Service, or a self-managed cluster. Google Cloud and Ubisoft created the project, but it is cloud-neutral by design.

Which Kubernetes versions does Agones 1.61 support?
Agones 1.61.0, released September 24, 2026, supports Kubernetes 1.34, 1.35, and 1.36. Always match your cluster version to a currently supported Agones release before upgrading either component.

How does a dedicated game server on Kubernetes handle sudden traffic spikes?
The FleetAutoscaler’s Buffer policy keeps a fixed number of Ready servers on standby and grows the Fleet automatically as that buffer gets consumed by new allocations, bounded by the minReplicas and maxReplicas you configure.

Can I migrate from Agones to Amazon GameLift Servers later without a full rewrite?
Mostly yes. Your containerized game server image carries over directly. You do need to swap the Agones SDK calls for the GameLift Server SDK and replace allocator API calls with GameLift’s game-session queue, but the core game server binary and container build process stay the same.

Why did my GameServer stay in the Scheduled state and never reach Ready?
This almost always means the pod could not be scheduled onto any node, usually due to insufficient CPU or memory, or the binary inside the container never called sdk.Ready(). Check kubectl describe gameserver first, then check container logs.

Is Agones suitable for a small indie team, or is it overkill?
For a single-server or single-region indie launch, running full Kubernetes and Agones is often more operational overhead than the game needs. It starts paying off once you need autoscaling, multi-region capacity, or more than a handful of concurrent server instances.

What UDP port range should I open for Agones game servers?
By default Agones assigns dynamic ports from 7000 to 8000, though this range is configurable in the Helm chart values. Whatever range you set, make sure your cloud security groups or firewall rules allow inbound UDP traffic across the full range on your game server node pool.

Can Agones run stateful game modes like persistent-world servers, or only session-based matches?
Agones itself is agnostic to game mode. Session-based shooters and battle royales are the most common use case because their GameServer lifecycle maps cleanly onto Ready, Allocated, and Shutdown, but persistent-world servers work too, they simply stay Allocated for much longer and typically use a custom health check tuned for long-running processes instead of a fast per-match cycle.

How is a Fleet different from a GameServerSet?
A GameServerSet is the lower-level resource that actually manages a set of GameServers with the same configuration, similar to how a ReplicaSet backs a Deployment in plain Kubernetes. Fleet is the resource you interact with directly, and it creates and manages GameServerSets underneath during rolling updates, so you rarely need to touch a GameServerSet by hand.

Elias Virtanen

Elias Virtanen

Cybersecurity Analyst

Elias Virtanen is the Cybersecurity Analyst at Tech Insider, bringing hands-on expertise from his background in penetration testing and security consulting. He previously worked as a security researcher at F-Secure in Helsinki, where he focused on threat intelligence and vulnerability disclosure. Elias covers ransomware trends, zero-trust architecture, and the evolving regulatory landscape including NIS2 and the EU Cyber Resilience Act. He holds a CISSP certification and an MSc in Information Security from Aalto University.

View all articles