mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-16 09:32:02 +00:00
feat: add fleet autoscaling baseline
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
apiVersion: autoscaling.agones.dev/v1
|
||||||
|
kind: FleetAutoscaler
|
||||||
|
metadata:
|
||||||
|
name: cosmic-clash-game
|
||||||
|
namespace: cosmic-clash
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: game-fleet-autoscaler
|
||||||
|
spec:
|
||||||
|
fleetName: cosmic-clash-game
|
||||||
|
policy:
|
||||||
|
type: Buffer
|
||||||
|
buffer:
|
||||||
|
# Ready floor is deliberately independent of Allocated capacity. Agones
|
||||||
|
# scales Allocated servers down to zero while preserving this buffer.
|
||||||
|
minReady: 2
|
||||||
|
maxReady: 6
|
||||||
|
bufferSize: 2
|
||||||
@@ -7,3 +7,4 @@ resources:
|
|||||||
- network-policies.yaml
|
- network-policies.yaml
|
||||||
- control-plane-deployment.yaml
|
- control-plane-deployment.yaml
|
||||||
- fleet.yaml
|
- fleet.yaml
|
||||||
|
- fleet-autoscaler.yaml
|
||||||
|
|||||||
+5
-2
@@ -127,8 +127,11 @@ product policy are in [`docs/MATCHMAKING.md`](docs/MATCHMAKING.md).
|
|||||||
Agones integration remains.
|
Agones integration remains.
|
||||||
- [ ] Deliver/verify the signed roster after allocation and expose client
|
- [ ] Deliver/verify the signed roster after allocation and expose client
|
||||||
tickets only after backend `assignment_ready`.
|
tickets only after backend `assignment_ready`.
|
||||||
- [ ] Keep >=2 Ready processes across >=2 on-demand nodes/failure domains per
|
- [ ] **IN PROGRESS:** Keep >=2 Ready processes across >=2 on-demand
|
||||||
queue-enabled region; only Allocated count may fall to zero.
|
nodes/failure domains per queue-enabled region; only Allocated count may
|
||||||
|
fall to zero. A provider-neutral Agones FleetAutoscaler now encodes a
|
||||||
|
two-process Ready buffer and six-process warm cap; regional node pools,
|
||||||
|
pre-pull rollout and measured N+1 capacity remain.
|
||||||
- [ ] Spread on-demand capacity across zones with N+1 headroom; do not place
|
- [ ] Spread on-demand capacity across zones with N+1 headroom; do not place
|
||||||
live matches on interruptible nodes.
|
live matches on interruptible nodes.
|
||||||
- [ ] Benchmark native x86_64 boot, p99 CPU/RSS/network and tick health; set
|
- [ ] Benchmark native x86_64 boot, p99 CPU/RSS/network and tick health; set
|
||||||
|
|||||||
+1
-1
@@ -1214,7 +1214,7 @@ the local/CI/community transport, not a silent production fallback.
|
|||||||
| 8.29 `[D:8.26,8.27]` | **IN PROGRESS.** Supervisor discovers and validates the Agones endpoint, propagates the actual dynamic `--port`, and exports `SDR_LISTEN_PORT`/`SDR_IP` only for Hosted-SDR while preserving an isolated ENet path | `server/supervisor/` tests cover invalid address/port rejection, dynamic port argument/env propagation and SDR-vs-ENet separation; real Agones dynamic/passthrough mapping, POP/cert/firewall/NAT and multi-match fixture remain |
|
| 8.29 `[D:8.26,8.27]` | **IN PROGRESS.** Supervisor discovers and validates the Agones endpoint, propagates the actual dynamic `--port`, and exports `SDR_LISTEN_PORT`/`SDR_IP` only for Hosted-SDR while preserving an isolated ENet path | `server/supervisor/` tests cover invalid address/port rejection, dynamic port argument/env propagation and SDR-vs-ENet separation; real Agones dynamic/passthrough mapping, POP/cert/firewall/NAT and multi-match fixture remain |
|
||||||
| 8.30 `[D:8.18,8.26,8.28,8.29]` | **IN PROGRESS.** Pure Go allocator filters Ready servers by region/build/protocol/transport, atomically claims one with idempotent allocation replay, and now owns the assignment-publication boundary | `server/domain/allocator.go` covers deterministic compatible selection, exhaustion, conflicting/identical allocation replay, unknown allocations, and assignment replay/conflict; Agones `GameServerAllocation`, signed roster metadata, bounded cross-replica retry and live integration remain |
|
| 8.30 `[D:8.18,8.26,8.28,8.29]` | **IN PROGRESS.** Pure Go allocator filters Ready servers by region/build/protocol/transport, atomically claims one with idempotent allocation replay, and now owns the assignment-publication boundary | `server/domain/allocator.go` covers deterministic compatible selection, exhaustion, conflicting/identical allocation replay, unknown allocations, and assignment replay/conflict; Agones `GameServerAllocation`, signed roster metadata, bounded cross-replica retry and live integration remain |
|
||||||
| 8.31 `[D:8.9,8.30]` | **IN PROGRESS.** Pure Go assignment gate requires Allocated state, exact allocation ID/match/server/region/build/protocol/transport compatibility, non-empty hosted endpoint and verified manifest signature before exposure; allocator publication cannot expose Ready state | `server/domain/assignment.go` and `allocator.go` plus adversarial fixtures cover early-connect, tampered signature/manifest, wrong compatibility, empty endpoint, unknown allocation and post-publication mutation rejection; Agones metadata watch, hosted-address registration, production signer and client-ticket publication remain |
|
| 8.31 `[D:8.9,8.30]` | **IN PROGRESS.** Pure Go assignment gate requires Allocated state, exact allocation ID/match/server/region/build/protocol/transport compatibility, non-empty hosted endpoint and verified manifest signature before exposure; allocator publication cannot expose Ready state | `server/domain/assignment.go` and `allocator.go` plus adversarial fixtures cover early-connect, tampered signature/manifest, wrong compatibility, empty endpoint, unknown allocation and post-publication mutation rejection; Agones metadata watch, hosted-address registration, production signer and client-ticket publication remain |
|
||||||
| 8.32 `[D:8.2,8.26,8.30]` | FleetAutoscaler with >=2 Ready processes across >=2 on-demand nodes/failure domains per queue-enabled region; pre-pull current/rollback; scale **Allocated** count to zero, never the Ready floor | Warm allocation meets p95 5 s/p99 10 s; disabled regions alone scale fully to zero; one-node loss retains certified Ready/headroom |
|
| 8.32 `[D:8.2,8.26,8.30]` | **IN PROGRESS.** Provider-neutral FleetAutoscaler baseline preserves a two-process Ready buffer, caps warm capacity, and leaves Allocated scale-down independent of the Ready floor; Fleet image references remain digest-pinned for current/rollback pre-pull | `deploy/k8s/base/fleet-autoscaler.yaml` and manifest tests cover Fleet ownership, Buffer policy and floor/cap invariants; regional on-demand node pools/failure domains, pre-pull rollout, warm-allocation p95/p99 and N+1 certification remain |
|
||||||
| 8.33 `[D:8.26,8.32]` | On-demand-only live capacity and measured N+1: loss of largest node leaves two Ready slots plus headroom for surviving Allocated matches | Interruptible nodes cannot receive live matches; forced node loss neither overloads survivors nor prevents the next allocation |
|
| 8.33 `[D:8.26,8.32]` | On-demand-only live capacity and measured N+1: loss of largest node leaves two Ready slots plus headroom for surviving Allocated matches | Interruptible nodes cannot receive live matches; forced node loss neither overloads survivors nor prevents the next allocation |
|
||||||
| 8.34 `[D:8.28,8.29]` | Native x86_64 benchmark of boot-to-process-ready and assignment-ready, p99 CPU/RSS/network and 60 Hz ticks; limits/node cap with 30% headroom | Measurements replace old estimates and certify density with no tick backlog |
|
| 8.34 `[D:8.28,8.29]` | Native x86_64 benchmark of boot-to-process-ready and assignment-ready, p99 CPU/RSS/network and 60 Hz ticks; limits/node cap with 30% headroom | Measurements replace old estimates and certify density with no tick backlog |
|
||||||
| 8.35 `[D:8.17,8.19,8.20,8.30,8.31]` | **IN PROGRESS.** Pure Go initial-connect policy decides ranked 30 s no-show cancellation with abandon ladder and casual 60 s bot start only when each team has a human; empty-team casual allocations cancel | `server/domain/noshow.go` covers wait/deadline boundaries, deterministic no-show/innocent ordering, ranked cooldown history and no pre-live rating action; persistent ticket restoration, allocation shutdown, bot spawn and live integration remain |
|
| 8.35 `[D:8.17,8.19,8.20,8.30,8.31]` | **IN PROGRESS.** Pure Go initial-connect policy decides ranked 30 s no-show cancellation with abandon ladder and casual 60 s bot start only when each team has a human; empty-team casual allocations cancel | `server/domain/noshow.go` covers wait/deadline boundaries, deterministic no-show/innocent ordering, ranked cooldown history and no pre-live rating action; persistent ticket restoration, allocation shutdown, bot spawn and live integration remain |
|
||||||
|
|||||||
@@ -20,6 +20,15 @@ class FleetManifestTest(unittest.TestCase):
|
|||||||
for hardening in ("runAsNonRoot: true", "automountServiceAccountToken: false", "readOnlyRootFilesystem: true", "allowPrivilegeEscalation: false"):
|
for hardening in ("runAsNonRoot: true", "automountServiceAccountToken: false", "readOnlyRootFilesystem: true", "allowPrivilegeEscalation: false"):
|
||||||
self.assertIn(hardening, fleet)
|
self.assertIn(hardening, fleet)
|
||||||
|
|
||||||
|
def test_autoscaler_preserves_ready_floor_and_owns_fleet(self):
|
||||||
|
autoscaler = self.read("base/fleet-autoscaler.yaml")
|
||||||
|
for field in (
|
||||||
|
"kind: FleetAutoscaler", "namespace: cosmic-clash",
|
||||||
|
"fleetName: cosmic-clash-game", "type: Buffer",
|
||||||
|
"minReady: 2", "maxReady: 6", "bufferSize: 2",
|
||||||
|
):
|
||||||
|
self.assertIn(field, autoscaler)
|
||||||
|
|
||||||
def test_eu_and_na_overlays_are_distinct_and_namespaced(self):
|
def test_eu_and_na_overlays_are_distinct_and_namespaced(self):
|
||||||
eu = self.read("overlays/eu/region.yaml")
|
eu = self.read("overlays/eu/region.yaml")
|
||||||
na = self.read("overlays/na/region.yaml")
|
na = self.read("overlays/na/region.yaml")
|
||||||
|
|||||||
Reference in New Issue
Block a user