Using Agones Autopilot
Applying Agones manifests with no cluster: what is supported and refused, how servers are sized, allocation, sleep, and the Agones SDK.
projects/{project}/locations/{location}/fleets/{fleet}projects/{project}/locations/{location}/fleetAutoscalers/{autoscaler}projects/{project}/locations/{location}/gameServers/{game_server}Applying manifests
apply takes what kubectl apply -f would: one or more YAML documents — Fleet,
GameServer and FleetAutoscaler — in any order, across any number of files.
Agones Autopilot → Apply manifests → paste your manifests → Check → ApplyA manifest like Agones' own example runs unchanged:
apiVersion: agones.dev/v1kind: Fleetmetadata: name: lobbyspec: replicas: 2 template: spec: ports: - name: default containerPort: 7654 template: spec: containers: - name: lobby image: .plany.cr//lobby:v1 resources: requests: memory: 512Mi cpu: 500m---apiVersion: autoscaling.agones.dev/v1kind: FleetAutoscalermetadata: name: lobby-autoscalerspec: fleetName: lobby policy: type: Buffer buffer: bufferSize: 2 minReplicas: 2 maxReplicas: 20What an apply does:
- It is all or nothing. Every document is checked before anything changes, so a file whose third document is refused changes nothing.
- Applying the same manifest twice changes nothing. Each object comes back as created, updated or unchanged, with its warnings.
- Changing a fleet's template rolls its servers the way Agones does, within
strategy.rollingUpdate'smaxSurgeandmaxUnavailable(25% each unless you say otherwise), or all at once withtype: Recreate. An Allocated server is never replaced mid-match; it is replaced once it shuts down. - A
GameServerwithgenerateNameis a new server every time it is applied, as withkubectl create. --dry-run(Check, in the console;validate_onlyon the API) reports what would change and changes nothing. Terraform runs this check duringplan, so a refusal fails the plan rather than half-way through an apply.
In Terraform, an object you remove from the manifest is deleted on the next apply,
as kubectl apply --prune would — so renaming a fleet is a new fleet and the old
one's deletion.
Names are lower-case letters, digits and hyphens, up to 40 characters, and unique
per kind within a project and region. metadata.namespace is kept as a label and
returned to the SDK, but nothing is scoped by it.
Choosing a network
New fleets and game servers join the project's default private
network unless you pass --vpc (vpc in
Terraform and on ApplyManifests). A fleet keeps the network it was created on:
applying it again with a different --vpc is refused rather than moving servers
players are on. To move one, delete it and apply it again.
What is supported
Anything Autopilot cannot run the way a cluster would is refused by name at
apply — Fleet "lobby": spec.template.spec.template.spec.containers[1]: one container per game server is supported — never quietly dropped. A field
Autopilot does not recognise is refused too. Fields that mean nothing without a
cluster are accepted and listed as warnings.
| Supported | Refused |
|---|---|
One container per game server, from .plany.cr or any public registry | More than one container, init containers, sidecars, volumes |
One port: Dynamic policy, protocol UDP, TCP or TCPUDP | Static and Passthrough ports, hostPort, more than one port, a port range other than the default |
command, args, workingDir, literal env, resources | env[].valueFrom, envFrom, privileged, added capabilities |
Labels, annotations, health, strategy, eviction | hostNetwork, hostPID, hostIPC, serviceAccountName |
Buffer autoscaling, as a count or a percentage | Webhook, Counter and List policies |
SDK: Ready, Allocate, Reserve, Shutdown, Health, labels, annotations, GetGameServer, WatchGameServer | SDK counters, lists and player tracking; allocationOverflow and priorities |
affinity, tolerations, nodeSelector, priorityClassName |
Accepted and ignored, with a warning: a fleet's own scheduling (there are no
nodes to pack), terminationGracePeriodSeconds (a server is given sixty seconds to
stop), restartPolicy (a fleet replaces a server that exits), a container's
imagePullPolicy (the image is pinned to a digest when it is applied), its
ports, livenessProbe, readinessProbe and startupProbe (use Agones health
through the SDK), imagePullSecrets, and the pod's securityContext.
The SDK is always on its standard ports, 9357 and 9358; an sdkServer naming any
other port is refused.
A FleetAutoscaler with minReplicas equal to maxReplicas is a fixed-size fleet,
and is accepted. A percentage buffer needs minReplicas of at least 1. Deleting an
autoscaler leaves its fleet at the size it had; the fleet returns to
spec.replicas on its next apply.
Sizing
There are no nodes, so each game server gets a machine of its own, sized from its
container's resources:
- CPU is the limit, or the request where there is no limit, rounded up to whole vCPUs. A server with neither gets one vCPU.
- Memory is the limit, or the request, plus 256 MiB for the server's own system, and at least 512 MiB.
The server then runs at the smallest machine type that
holds both — so a container asking for 2500m and 3Gi runs on a 4 vCPU, 8 GiB
machine. A container no machine type can hold is refused at apply, naming the
largest there is.
Allocation
A matchmaker allocates a server the way it does on a cluster. Three ways to do it:
Agones' own allocator. allocation.AllocationService/Allocate, from Agones'
allocation.proto, over gRPC at api.plany.cloud:443. A matchmaker built on it
changes two things and nothing else:
- The credential. A Plany API key as a bearer token
(
authorization: Bearer …), instead of a client certificate. Its principal needsagones.allocations.createon the project — a permission that lets a matchmaker's key allocate and do nothing else. - The project. A cluster's allocator knows its namespace; this one needs a
project. Set the allocation's
namespaceto your project id (), or send anx-plany-projectheader.
Multi-cluster allocation, and counter and list selectors, are refused.
The Plany API, or the CLI and console:
Agones Autopilot → lobby → Allocate a serverSelectors are tried in order. Each matches labels — Kubernetes-style
match_expressions with In, NotIn, Exists and DoesNotExist work too — and
may ask for Allocated servers rather than Ready ones, to put more players into a
lobby that has room. Packed (the default) prefers a fleet's oldest servers;
Distributed spreads. Labels and annotations on the request are written onto the
allocated server, where the game reads them through the SDK.
Two servers can never be allocated to one request, and two requests can never take
one server. Nothing matching is RESOURCE_EXHAUSTED, as Agones' allocator answers.
The address and port in the answer are where players connect. They stay the same across a sleep and a wake. Only servers Autopilot runs are ever allocated — never an ordinary Playpute server that happens to carry the same labels.
A buffer of Ready servers is how a lobby stays open: with bufferSize: 2, two
servers are always accepting players however many are Allocated to matches. A
server can also allocate itself by calling SDK.Allocate() when its match starts,
which takes it out of the buffer and makes the fleet start another.
Pay when played
A Ready server nobody has connected to for ten minutes goes to sleep. While asleep it is not charged for CPU or memory, stays Ready, and can still be allocated. Allocating it — or a player connecting to its address — wakes it, and the first connection waits a few seconds while it resumes exactly where it was, with whatever it held in memory.
An allocation answers straight away even when it wakes a server; the response says
it did (woken), and players connecting at once simply wait the few seconds.
An Allocated or Reserved server never sleeps, and neither does one Plany cannot tell is empty. A server that wakes is not marked unhealthy for the time it slept.
Change the idle time with an annotation on the Fleet (or standalone GameServer)
itself — a duration of at least a minute, or "0" to keep servers awake:
apiVersion: agones.dev/v1kind: Fleetmetadata: name: lobby annotations: autopilot.plany.cloud/sleep-after-idle: "30m"spec: # ...A manifest that does not mention it gets the ten-minute default, so nothing needs changing to get sleep.
The Agones SDK
Your game server's SDK client works unchanged. The SDK is served on localhost,
gRPC on port 9357 and HTTP on 9358, and AGONES_SDK_GRPC_PORT and
AGONES_SDK_HTTP_PORT are set in the container's environment, as on a cluster.
| Call | What happens |
|---|---|
Ready() | The server becomes Ready: in the buffer, and allocatable. |
Allocate() | Ready → Allocated, as a self-allocation. |
Reserve(seconds) | Reserved until the time runs out, then back to Ready. |
Shutdown() | A fleet's server is deleted and replaced; a standalone server is deleted. |
Health() | Missing it for longer than health.failureThreshold × health.periodSeconds marks the server Unhealthy. |
SetLabel, SetAnnotation | Stored under agones.dev/sdk-, as Agones does. |
GetGameServer, WatchGameServer | The Agones GameServer, including the address players connect to and the labels an allocation wrote. |
WatchGameServer sees an allocation as soon as it is made, so a server waiting to
be told its match starts does not wait for a poll. Counters, lists and player
tracking return an error naming the feature.
Two things differ from a cluster:
- There is no Kubernetes API inside the game server. Anything that reads or writes Kubernetes objects directly, rather than through the SDK, has nothing to talk to.
- The game sees connections arriving from Plany's address, not the player's. A game that bans by IP address or passes client addresses to anti-cheat will see the same address for everyone.
Reading what is running
Agones Autopilot → a fleet → its servers, autoscaler, ignored fields and manifestA fleet reports how many servers it has, how many are Ready (awake or asleep),
Allocated and asleep, and how many are still on an earlier template while a rollout
replaces them. A game server reports its Agones state — Ready, Allocated,
Reserved, Unhealthy and the rest — whether it is asleep, and its address.
Deleting
Agones Autopilot → a fleet → DeleteDeleting a fleet deletes its servers; an Allocated one is left to finish its match first, as Agones does. Deleting one of a fleet's servers makes the fleet replace it.