fix(images): 服务器镜像在创建时固定到仓库 digest,更换镜像需确认备份,安装器重建前先固定旧服并推送不可变版本标签

This commit is contained in:
Lemon-miaow committed 2026-09-24 16:57:38 +08:00
1 parent 857b6da886
commit 215bfd78d7
29 files changed
+1149 -29

No files matched your search

+22 -9
View File
@@ -234,11 +234,13 @@ func loginToInternalAPI(p Params) *networkingv1.NetworkPolicy {
}
}
// RegistryIngressPolicy fences the registry pod: only build pods reach its port.
// Everything else that uses the registry runs on the node — containerd's pulls and
// the installer's pushes both arrive through the loopback hostPort — and Kubernetes
// never blocks resident-node traffic. Write authorization is the gate's job; this
// policy keeps every other pod from even trying.
// RegistryIngressPolicy fences the registry pod: only build pods and felis-api
// reach its port. Build pods push what they build; felis-api reads a manifest
// digest to pin a new server's image (internal/imagepin). Everything else that
// uses the registry runs on the node — containerd's pulls and the installer's
// pushes both arrive through the loopback hostPort — and Kubernetes never blocks
// resident-node traffic. Write authorization is the gate's job (felis-api holds no
// registry credential); this policy keeps every other pod from even trying.
func RegistryIngressPolicy(p Params) *networkingv1.NetworkPolicy {
p = p.withDefaults()
tcp := corev1.ProtocolTCP
@@ -246,11 +248,22 @@ func RegistryIngressPolicy(p Params) *networkingv1.NetworkPolicy {
np := netpol("felis-registry-ingress", p.RegistryNamespace,
metav1.LabelSelector{MatchLabels: registryLabels()},
[]networkingv1.NetworkPolicyIngressRule{{
From: []networkingv1.NetworkPolicyPeer{{
NamespaceSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{"kubernetes.io/metadata.name": p.BuildNamespace},
From: []networkingv1.NetworkPolicyPeer{
{
NamespaceSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{"kubernetes.io/metadata.name": p.BuildNamespace},
},
},
}},
{
NamespaceSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{"kubernetes.io/metadata.name": p.ControlNamespace},
},
PodSelector: &metav1.LabelSelector{MatchLabels: map[string]string{
LabelPartOf: controlPlanePartOf,
LabelComponent: ComponentAPI,
}},
},
},
Ports: []networkingv1.NetworkPolicyPort{{Protocol: &tcp, Port: &port}},
}},
)
+16 -3
View File
@@ -307,7 +307,7 @@ func TestLoginToInternalAPI_SelectsOnlyTheSystemLoginPod(t *testing.T) {
// TestRegistryIngress_BuildNamespaceOnly pins who may dial the registry pod: build
// pods, on the registry port. Game servers and the control plane never pull
// through the Service — containerd pulls over the node's loopback hostPort.
func TestRegistryIngress_BuildNamespaceOnly(t *testing.T) {
func TestRegistryIngress_BuildNamespaceAndAPI(t *testing.T) {
p := testParams().withDefaults()
np := RegistryIngressPolicy(p)
if np.Namespace != p.RegistryNamespace {
@@ -319,14 +319,27 @@ func TestRegistryIngress_BuildNamespaceOnly(t *testing.T) {
if mapSelectorMatches(np.Spec.PodSelector.MatchLabels, APIDeployment(p).Spec.Template.Labels) {
t.Error("registry ingress must not also fence the api pod")
}
if len(np.Spec.Ingress) != 1 || len(np.Spec.Ingress[0].From) != 1 {
t.Fatalf("registry ingress shape = %+v, want one rule, one peer", np.Spec.Ingress)
if len(np.Spec.Ingress) != 1 || len(np.Spec.Ingress[0].From) != 2 {
t.Fatalf("registry ingress shape = %+v, want one rule, two peers", np.Spec.Ingress)
}
peer := np.Spec.Ingress[0].From[0]
if peer.PodSelector != nil || peer.IPBlock != nil || peer.NamespaceSelector == nil ||
peer.NamespaceSelector.MatchLabels["kubernetes.io/metadata.name"] != p.BuildNamespace {
t.Errorf("registry ingress peer = %+v, want the whole %s namespace", peer, p.BuildNamespace)
}
// The second peer is felis-api alone: it selects the api pod and not the
// operator's, both of which live in the control namespace.
api := np.Spec.Ingress[0].From[1]
if api.IPBlock != nil || api.NamespaceSelector == nil || api.PodSelector == nil ||
api.NamespaceSelector.MatchLabels["kubernetes.io/metadata.name"] != p.ControlNamespace {
t.Fatalf("registry ingress api peer = %+v, want pods in %s", api, p.ControlNamespace)
}
if !mapSelectorMatches(api.PodSelector.MatchLabels, APIDeployment(p).Spec.Template.Labels) {
t.Errorf("registry ingress api peer %v does not select the api pod", api.PodSelector)
}
if mapSelectorMatches(api.PodSelector.MatchLabels, OperatorDeployment(p).Spec.Template.Labels) {
t.Errorf("registry ingress api peer %v also selects the operator pod", api.PodSelector)
}
assertSinglePort(t, np.Spec.Ingress[0].Ports, int(p.RegistryPort))
}