feat(netpol): 锁定游戏服出站并为 registry 加入站围栏

This commit is contained in:
Lemon-miaow committed 2026-09-24 14:25:17 +08:00
1 parent 3424852a39
commit 7819e5de50
13 files changed
+620 -37

No files matched your search

+13 -1
View File
@@ -73,6 +73,18 @@ func labelsFor(server *v1alpha1.MinecraftServer) map[string]string {
}
}
// podLabelsFor is labelsFor plus the setup-owned system-role label, copied onto
// the pod so the platform's NetworkPolicies can tell the login gate apart from a
// user server (internal/platform loginToInternalAPI). Only the template carries it:
// the StatefulSet selector is immutable and stays selectorFor.
func podLabelsFor(server *v1alpha1.MinecraftServer) map[string]string {
l := labelsFor(server)
if role := server.Labels[v1alpha1.LabelSystemRole]; role != "" {
l[v1alpha1.LabelSystemRole] = role
}
return l
}
func headlessServiceName(name string) string { return name + "-hl" }
// rconPort resolves the RCON port, defaulting to the conventional DefaultRconPort.
@@ -274,7 +286,7 @@ func buildStatefulSet(server *v1alpha1.MinecraftServer, replicas int32, felisIma
ServiceName: headlessServiceName(server.Name),
Selector: &metav1.LabelSelector{MatchLabels: selectorFor(server)},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{Labels: labelsFor(server)},
ObjectMeta: metav1.ObjectMeta{Labels: podLabelsFor(server)},
Spec: corev1.PodSpec{
TerminationGracePeriodSeconds: &grace,
InitContainers: initContainers,
@@ -119,6 +119,40 @@ func TestBuildStatefulSetForwardingInitContainer(t *testing.T) {
}
}
// The system-role label travels onto the pod: the platform's NetworkPolicies select
// on it (felis-login-to-internal-api opens 8081 only to name=login AND
// system-role=login), and a pod without it would be fenced off the one service it
// exists to call. The selector stays the immutable labelsFor subset, so existing
// StatefulSets roll instead of failing to update.
func TestBuildStatefulSetCopiesSystemRoleOntoPods(t *testing.T) {
login := &v1alpha1.MinecraftServer{}
login.Name = naming.SystemLoginServer
login.Labels = map[string]string{v1alpha1.LabelSystemRole: naming.SystemLoginServer}
sts, err := buildStatefulSet(login, 1, "felis:demo")
if err != nil {
t.Fatalf("buildStatefulSet: %v", err)
}
pod := sts.Spec.Template.Labels
if pod[v1alpha1.LabelSystemRole] != naming.SystemLoginServer {
t.Errorf("pod labels = %v, want %s=%s", pod, v1alpha1.LabelSystemRole, naming.SystemLoginServer)
}
for k, v := range sts.Spec.Selector.MatchLabels {
if pod[k] != v {
t.Errorf("selector %s=%s does not match the pod template", k, v)
}
}
if _, ok := sts.Spec.Selector.MatchLabels[v1alpha1.LabelSystemRole]; ok {
t.Error("the system role must stay out of the (immutable) selector")
}
user := &v1alpha1.MinecraftServer{}
user.Name = "survival"
userSts, _ := buildStatefulSet(user, 1, "felis:demo")
if _, ok := userSts.Spec.Template.Labels[v1alpha1.LabelSystemRole]; ok {
t.Errorf("a user server pod must carry no system role, got %v", userSts.Spec.Template.Labels)
}
}
// A server with a health port also exposes it as a named container port so the
// kubelet can reach it.
func TestBuildStatefulSetAddsHealthPort(t *testing.T) {