feat(api): HTTP readiness knob on MinecraftServer and login-gate fallback default

StartupSpec.HealthHTTPPort/Path switch pod readiness from plain-TCP to an HTTP GET for RCON-less loaders (LOOHP/Limbo) that report 'started' only after the first tick. User servers now default FallbackServer to the login gate, never the lobby, so a stopped/starting backend keeps authentication in front of a fresh connection.
This commit is contained in:
flyemoji committed 2026-07-02 19:38:37 +09:00
1 parent 9ef817f2b3
commit 159107b4e3
3 files changed
+32

No files matched your search

@@ -243,6 +243,18 @@ spec:
description: Startup bounds how long Starting may last before Failed
(spec §5).
properties:
healthHTTPPath:
description: HealthHTTPPath is the path for the HTTP readiness
probe (default "/healthz" when HealthHTTPPort is set).
type: string
healthHTTPPort:
description: HealthHTTPPort, when > 0, switches the pod readiness
probe from the default plain-TCP check on the game port to an
HTTP GET on this container port. It exists for RCON-less loaders
(notably LOOHP/Limbo) where the felis-limbo plugin reports true
readiness only after the first server tick.
format: int32
type: integer
readinessTimeoutSeconds:
description: ReadinessTimeoutSeconds is the budget for the first
successful RCON probe.
+8
View File
@@ -4,6 +4,7 @@ import (
"context"
"felis.lolicon.best/internal/apis/felis/v1alpha1"
"felis.lolicon.best/internal/naming"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -68,6 +69,12 @@ func (k *K8sCluster) ListServers(ctx context.Context) ([]ServerInfo, error) {
// guaranteed the §22 memory ceiling lives in in.Resources, so the operator
// never has to derive a cgroup limit from JavaMemory. An existing name maps to
// ErrConflict so the handler returns 409.
//
// Every user server falls back to the login gate while it is stopped or starting
// — never to the lobby. Routing a fresh connection to the lobby would drop the
// player past authentication; falling back to login keeps the gate in front of
// them (and if login itself is down the proxy refuses, which is the intended
// "rather unreachable than unauthenticated" trade-off).
func (k *K8sCluster) CreateServer(ctx context.Context, in CreateServerInput) error {
ms := &v1alpha1.MinecraftServer{
ObjectMeta: metav1.ObjectMeta{
@@ -81,6 +88,7 @@ func (k *K8sCluster) CreateServer(ctx context.Context, in CreateServerInput) err
JavaMemory: in.JavaMemory,
DesiredState: v1alpha1.DesiredStopped,
AutostartPolicy: in.AutostartPolicy,
FallbackServer: naming.SystemLoginServer,
Storage: v1alpha1.StorageSpec{Size: in.StorageSize},
Resources: in.Resources,
},
@@ -208,6 +208,18 @@ type StartupSpec struct {
TimeoutSeconds int32 `json:"timeoutSeconds,omitempty"`
// ReadinessTimeoutSeconds is the budget for the first successful RCON probe.
ReadinessTimeoutSeconds int32 `json:"readinessTimeoutSeconds,omitempty"`
// HealthHTTPPort, when > 0, switches the pod readiness probe from the default
// plain-TCP check on the game port to an HTTP GET on this container port. It
// exists for RCON-less loaders (notably LOOHP/Limbo) where "the socket is
// bound" is a weaker signal than the server itself reporting it has finished
// starting: the felis-limbo plugin serves such an endpoint and flips it to 200
// only after the first server tick. The operator's readiness path is otherwise
// unchanged — with rcon disabled, passing this probe (readyReplicas >= 1) is
// what marks the server Ready.
HealthHTTPPort int32 `json:"healthHTTPPort,omitempty"`
// HealthHTTPPath is the path for the HTTP readiness probe (default "/healthz"
// when HealthHTTPPort is set).
HealthHTTPPath string `json:"healthHTTPPath,omitempty"`
}
// IdleSpec configures empty-server auto-stop (spec §8).