mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
d40344a2c0
The Kubernetes base deployed a control-plane image the Dockerfile never built -- cmd/control-plane was absent from the Go build stage and no target existed -- while the Dockerfile built a matcher image no manifest ever deployed. Applying the checked-in base therefore could not produce the advertised topology: one required workload had no repository-defined artifact, and nothing consumed queued tickets. Tickets could be created but never became proposals. Add the production control-plane build and image target, explicitly not the testkit-api target, which injects a fake login accepting any ticket. Add casual and ranked matcher Deployments as separate workloads: they have different match sizes, and separating them keeps a ranked backlog from delaying casual formation. One replica each -- CreateProposal's SKIP LOCKED fences make more replicas safe, but they would halve the candidate pool each worker sees per poll and worsen formation for no throughput gain at this scale. Their PDB uses maxUnavailable, since minAvailable against a single replica blocks node drains outright. Also fix both blocked traffic directions. No ingress policy admitted UDP/7777 to game-server pods, so an allocated server was unreachable from the internet under the namespace-wide default deny. And control-plane ingress admitted only edge-gateway pods, so roster fetch, registration, connection receipts, shutdown and result submission from game servers were dropped even inside the cluster, despite their egress being permitted. The default deny stays. Manifest tests now assert every required role is deployed, both playlists are scheduled, every referenced image maps to a real Dockerfile target, and both traffic directions are permitted. Each was verified to fail against the defect it covers. The control-plane image was built and run to confirm the target works.
148 lines
4.6 KiB
YAML
148 lines
4.6 KiB
YAML
# cmd/matcher is a standalone poll loop that turns queued tickets into
|
|
# proposals. It was built as an image but had no Deployment anywhere in this
|
|
# base, so applying the checked-in manifests produced a cluster where tickets
|
|
# could be created but nothing ever consumed them.
|
|
#
|
|
# Casual and ranked run as separate Deployments rather than one process with
|
|
# two loops: they have different match sizes, and separating them means a
|
|
# ranked backlog cannot delay casual formation (and vice versa). Each worker
|
|
# reads its own playlist-scoped Redis namespace.
|
|
#
|
|
# Exactly one replica each. The matcher claims tickets through CreateProposal's
|
|
# SKIP LOCKED fences so a second replica would be safe, but it would also halve
|
|
# the candidate pool each worker sees per poll and make formation quality worse
|
|
# for no throughput gain at this scale.
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: matcher-casual
|
|
namespace: cosmic-clash
|
|
labels:
|
|
app.kubernetes.io/name: matcher
|
|
app.kubernetes.io/component: matcher
|
|
cosmic-clash.io/playlist: casual
|
|
spec:
|
|
replicas: 1
|
|
strategy:
|
|
type: Recreate
|
|
selector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: matcher
|
|
cosmic-clash.io/playlist: casual
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: matcher
|
|
app.kubernetes.io/component: matcher
|
|
cosmic-clash.io/playlist: casual
|
|
spec:
|
|
terminationGracePeriodSeconds: 10
|
|
serviceAccountName: matcher
|
|
automountServiceAccountToken: false
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 10001
|
|
runAsGroup: 10001
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
containers:
|
|
- name: matcher
|
|
image: ghcr.io/cosmic-clash/matcher@sha256:0000000000000000000000000000000000000000000000000000000000000000
|
|
args:
|
|
- --dsn=$(COSMIC_CLASH_POSTGRES_DSN)
|
|
- --playlist=casual
|
|
- --size=4
|
|
- --interval=1s
|
|
- --redis-addr=$(COSMIC_CLASH_REDIS_ADDR)
|
|
securityContext:
|
|
allowPrivilegeEscalation: false
|
|
readOnlyRootFilesystem: true
|
|
capabilities:
|
|
drop: [ALL]
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 128Mi
|
|
limits:
|
|
cpu: 1
|
|
memory: 512Mi
|
|
env:
|
|
- name: COSMIC_CLASH_POSTGRES_DSN
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cosmic-clash-database
|
|
key: dsn
|
|
- name: COSMIC_CLASH_REDIS_ADDR
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cosmic-clash-redis
|
|
key: addr
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: matcher-ranked
|
|
namespace: cosmic-clash
|
|
labels:
|
|
app.kubernetes.io/name: matcher
|
|
app.kubernetes.io/component: matcher
|
|
cosmic-clash.io/playlist: ranked
|
|
spec:
|
|
replicas: 1
|
|
strategy:
|
|
type: Recreate
|
|
selector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: matcher
|
|
cosmic-clash.io/playlist: ranked
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: matcher
|
|
app.kubernetes.io/component: matcher
|
|
cosmic-clash.io/playlist: ranked
|
|
spec:
|
|
terminationGracePeriodSeconds: 10
|
|
serviceAccountName: matcher
|
|
automountServiceAccountToken: false
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 10001
|
|
runAsGroup: 10001
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
containers:
|
|
- name: matcher
|
|
image: ghcr.io/cosmic-clash/matcher@sha256:0000000000000000000000000000000000000000000000000000000000000000
|
|
args:
|
|
- --dsn=$(COSMIC_CLASH_POSTGRES_DSN)
|
|
# Ranked is strictly 3v3; domain.AllocateAcceptedProposal rejects a
|
|
# ranked proposal that is not exactly six players.
|
|
- --playlist=ranked
|
|
- --size=6
|
|
- --interval=1s
|
|
- --redis-addr=$(COSMIC_CLASH_REDIS_ADDR)
|
|
securityContext:
|
|
allowPrivilegeEscalation: false
|
|
readOnlyRootFilesystem: true
|
|
capabilities:
|
|
drop: [ALL]
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 128Mi
|
|
limits:
|
|
cpu: 1
|
|
memory: 512Mi
|
|
env:
|
|
- name: COSMIC_CLASH_POSTGRES_DSN
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cosmic-clash-database
|
|
key: dsn
|
|
- name: COSMIC_CLASH_REDIS_ADDR
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cosmic-clash-redis
|
|
key: addr
|