mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-15 01:22:13 +00:00
feat: add regional Agones fleet overlays
This commit is contained in:
@@ -2,6 +2,7 @@ apiVersion: apps/v1
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: control-plane
|
name: control-plane
|
||||||
|
namespace: cosmic-clash
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/name: control-plane
|
app.kubernetes.io/name: control-plane
|
||||||
spec:
|
spec:
|
||||||
@@ -56,4 +57,3 @@ spec:
|
|||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: cosmic-clash-steam
|
name: cosmic-clash-steam
|
||||||
key: publisher-key
|
key: publisher-key
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
apiVersion: agones.dev/v1
|
||||||
|
kind: Fleet
|
||||||
|
metadata:
|
||||||
|
name: cosmic-clash-game
|
||||||
|
namespace: cosmic-clash
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: game-fleet
|
||||||
|
spec:
|
||||||
|
replicas: 2
|
||||||
|
strategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: game-server
|
||||||
|
cosmic-clash.io/region: EU
|
||||||
|
cosmic-clash.io/build: build-1
|
||||||
|
cosmic-clash.io/protocol: "1"
|
||||||
|
cosmic-clash.io/transport: enet
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: game
|
||||||
|
containerPort: 7777
|
||||||
|
protocol: UDP
|
||||||
|
health:
|
||||||
|
disabled: false
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
serviceAccountName: match-server
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 10001
|
||||||
|
runAsGroup: 10001
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
containers:
|
||||||
|
- name: game-server
|
||||||
|
image: ghcr.io/cosmic-clash/game-server@sha256:0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
args: ["--port=7777"]
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
capabilities:
|
||||||
|
drop: [ALL]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1
|
||||||
|
memory: 512Mi
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
namespace: cosmic-clash
|
|
||||||
resources:
|
resources:
|
||||||
- namespace.yaml
|
- namespace.yaml
|
||||||
- service-accounts.yaml
|
- service-accounts.yaml
|
||||||
- rbac.yaml
|
- rbac.yaml
|
||||||
- network-policies.yaml
|
- network-policies.yaml
|
||||||
- control-plane-deployment.yaml
|
- control-plane-deployment.yaml
|
||||||
|
- fleet.yaml
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ apiVersion: networking.k8s.io/v1
|
|||||||
kind: NetworkPolicy
|
kind: NetworkPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: default-deny-ingress-egress
|
name: default-deny-ingress-egress
|
||||||
|
namespace: cosmic-clash
|
||||||
spec:
|
spec:
|
||||||
podSelector: {}
|
podSelector: {}
|
||||||
policyTypes: [Ingress, Egress]
|
policyTypes: [Ingress, Egress]
|
||||||
@@ -10,6 +11,7 @@ apiVersion: networking.k8s.io/v1
|
|||||||
kind: NetworkPolicy
|
kind: NetworkPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: control-plane-allowed-flows
|
name: control-plane-allowed-flows
|
||||||
|
namespace: cosmic-clash
|
||||||
spec:
|
spec:
|
||||||
podSelector:
|
podSelector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
@@ -64,4 +66,3 @@ spec:
|
|||||||
podSelector:
|
podSelector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
k8s-app: kube-dns
|
k8s-app: kube-dns
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- ../../base
|
||||||
|
patches:
|
||||||
|
- path: region.yaml
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: agones.dev/v1
|
||||||
|
kind: Fleet
|
||||||
|
metadata:
|
||||||
|
name: cosmic-clash-game
|
||||||
|
namespace: cosmic-clash
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
cosmic-clash.io/region: EU
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
resources:
|
||||||
|
- ../../base
|
||||||
|
patches:
|
||||||
|
- path: region.yaml
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: agones.dev/v1
|
||||||
|
kind: Fleet
|
||||||
|
metadata:
|
||||||
|
name: cosmic-clash-game
|
||||||
|
namespace: cosmic-clash
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
cosmic-clash.io/region: NA
|
||||||
+5
-2
@@ -111,8 +111,11 @@ product policy are in [`docs/MATCHMAKING.md`](docs/MATCHMAKING.md).
|
|||||||
|
|
||||||
## Phase 8 — Agones and regional server capacity
|
## Phase 8 — Agones and regional server capacity
|
||||||
|
|
||||||
- [ ] Add portable EU/NA Agones Fleets with provider edge/network/secret and
|
- [ ] **IN PROGRESS:** Add portable EU/NA Agones Fleets with provider
|
||||||
Valve-approved SDR POP/certificate/public-UDP overlays.
|
edge/network/secret and Valve-approved SDR POP/certificate/public-UDP
|
||||||
|
overlays. A restricted provider-neutral Fleet base and distinct EU/NA
|
||||||
|
Kustomize overlays now exist; live rendering and provider/Valve overlays
|
||||||
|
remain.
|
||||||
- [ ] Add the local-safe Agones adapter and separate process-ready (listen then
|
- [ ] Add the local-safe Agones adapter and separate process-ready (listen then
|
||||||
Ready) from assignment-ready (Allocated manifest verified and registered).
|
Ready) from assignment-ready (Allocated manifest verified and registered).
|
||||||
The Go supervisor now validates dynamic address/port data and gates Ready on
|
The Go supervisor now validates dynamic address/port data and gates Ready on
|
||||||
|
|||||||
+1
-1
@@ -1208,7 +1208,7 @@ the local/CI/community transport, not a silent production fallback.
|
|||||||
|
|
||||||
| # | Task | Acceptance |
|
| # | Task | Acceptance |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 8.26 `[D:8.1,8.6,8.12]` | Portable Helm/Kustomize Fleets per build/EU/NA region; isolate provider edge/network/DNS/secret and SDR POP/cert/public-UDP overlays | Two provider fixtures render; labels select region/build/protocol/transport; each fixture documents Valve approval and externally reachable UDP mapping |
|
| 8.26 `[D:8.1,8.6,8.12]` | **IN PROGRESS.** Provider-neutral Kustomize base now defines a restricted Agones Fleet with region/build/protocol/transport labels and UDP game port, plus distinct EU/NA overlays; the base avoids rewriting cross-namespace Agones RBAC | `deploy/k8s/base/fleet.yaml`, `overlays/eu`, `overlays/na` and `server/security/test_fleet_manifests.py` cover labels, replica floor, UDP declaration, pod hardening, overlay distinction and RBAC namespace safety; live Kustomize/Agones rendering, second-provider fixtures, edge/network/DNS/secret and SDR POP/cert/public-UDP overlays remain |
|
||||||
| 8.27 `[D:8.26]` | **IN PROGRESS.** Go supervisor package provides local-safe Agones REST discovery, validates assigned address/port data, injects dynamic `SDR_LISTEN_PORT`/`SDR_IP`, performs explicit process-ready probing and Ready transition; direct mode bypasses Agones | `server/supervisor/` covers allocated/direct startup, invalid endpoint rejection, dynamic endpoint/Ready ordering and authenticated drain; Godot Agones adapter, metadata watch, Health/annotation/Shutdown and emulator integration remain |
|
| 8.27 `[D:8.26]` | **IN PROGRESS.** Go supervisor package provides local-safe Agones REST discovery, validates assigned address/port data, injects dynamic `SDR_LISTEN_PORT`/`SDR_IP`, performs explicit process-ready probing and Ready transition; direct mode bypasses Agones | `server/supervisor/` covers allocated/direct startup, invalid endpoint rejection, dynamic endpoint/Ready ordering and authenticated drain; Godot Agones adapter, metadata watch, Health/annotation/Shutdown and emulator integration remain |
|
||||||
| 8.28 `[D:8.6,8.27]` | **IN PROGRESS.** Supervisor separates explicit process-ready from Agones Ready and never scrapes stdout; allocated mode refuses to mark Ready without a configured readiness probe | `server/supervisor/` tests prove Ready follows the probe and direct mode remains functional; Godot readiness endpoint, detached-container and Health-reclaim integration remain |
|
| 8.28 `[D:8.6,8.27]` | **IN PROGRESS.** Supervisor separates explicit process-ready from Agones Ready and never scrapes stdout; allocated mode refuses to mark Ready without a configured readiness probe | `server/supervisor/` tests prove Ready follows the probe and direct mode remains functional; Godot readiness endpoint, detached-container and Health-reclaim integration 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.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 |
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
BASE = Path(__file__).parents[2] / "deploy" / "k8s"
|
||||||
|
|
||||||
|
|
||||||
|
class FleetManifestTest(unittest.TestCase):
|
||||||
|
def read(self, path):
|
||||||
|
return (BASE / path).read_text()
|
||||||
|
|
||||||
|
def test_base_fleet_selects_compatible_game_servers(self):
|
||||||
|
fleet = self.read("base/fleet.yaml")
|
||||||
|
for label in (
|
||||||
|
"cosmic-clash.io/region: EU", "cosmic-clash.io/build: build-1",
|
||||||
|
'cosmic-clash.io/protocol: "1"', "cosmic-clash.io/transport: enet",
|
||||||
|
"protocol: UDP", "containerPort: 7777", "replicas: 2",
|
||||||
|
):
|
||||||
|
self.assertIn(label, fleet)
|
||||||
|
for hardening in ("runAsNonRoot: true", "automountServiceAccountToken: false", "readOnlyRootFilesystem: true", "allowPrivilegeEscalation: false"):
|
||||||
|
self.assertIn(hardening, fleet)
|
||||||
|
|
||||||
|
def test_eu_and_na_overlays_are_distinct_and_namespaced(self):
|
||||||
|
eu = self.read("overlays/eu/region.yaml")
|
||||||
|
na = self.read("overlays/na/region.yaml")
|
||||||
|
self.assertIn("cosmic-clash.io/region: EU", eu)
|
||||||
|
self.assertIn("cosmic-clash.io/region: NA", na)
|
||||||
|
self.assertNotEqual(eu, na)
|
||||||
|
for document in (eu, na):
|
||||||
|
self.assertIn("namespace: cosmic-clash", document)
|
||||||
|
|
||||||
|
def test_kustomization_does_not_rewrite_cross_namespace_agones_rbac(self):
|
||||||
|
base = self.read("base/kustomization.yaml")
|
||||||
|
rbac = self.read("base/rbac.yaml")
|
||||||
|
self.assertNotIn("namespace: cosmic-clash", base)
|
||||||
|
self.assertIn("namespace: agones-system", rbac)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Reference in New Issue
Block a user