From 3d86b7522a7c313ba49d49be23b9f11b51a96d96 Mon Sep 17 00:00:00 2001 From: Federico Paolinelli Date: Tue, 4 Aug 2026 10:43:30 -0400 Subject: [PATCH] frr-k8s: use Recreate strategy for statuscleaner deployment The statuscleaner deployment uses hostNetwork with a fixed port (9123). With the default RollingUpdate strategy, upgrades on SNO clusters get stuck because the new pod cannot bind the host port already held by the old pod. Switching to Recreate ensures the old pod is terminated before the new one starts. Signed-off-by: Federico Paolinelli Co-Authored-By: Claude Sonnet 4.6 (1M context) --- .../network/frr-k8s/node-status-cleaner.yaml | 4 +++ pkg/network/render.go | 1 + pkg/network/render_test.go | 31 +++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/bindata/network/frr-k8s/node-status-cleaner.yaml b/bindata/network/frr-k8s/node-status-cleaner.yaml index 7c28bceffe..c14786c1f8 100644 --- a/bindata/network/frr-k8s/node-status-cleaner.yaml +++ b/bindata/network/frr-k8s/node-status-cleaner.yaml @@ -9,6 +9,10 @@ metadata: annotations: release.openshift.io/version: "{{.ReleaseVersion}}" spec: +{{- if .IsSNO }} + strategy: + type: Recreate +{{- end }} selector: matchLabels: component: frr-k8s-statuscleaner diff --git a/pkg/network/render.go b/pkg/network/render.go index 626ffd5a21..205de88336 100644 --- a/pkg/network/render.go +++ b/pkg/network/render.go @@ -870,6 +870,7 @@ func renderAdditionalRoutingCapabilities(conf *operv1.NetworkSpec, bootstrapResu data.Data["ReleaseVersion"] = os.Getenv("RELEASE_VERSION") data.Data["NoOverlayManagedEnabled"] = conf.DefaultNetwork.OVNKubernetesConfig != nil && conf.DefaultNetwork.OVNKubernetesConfig.BGPManagedConfig.BGPTopology != "" + data.Data["IsSNO"] = bootstrapResult.OVN.ControlPlaneReplicaCount == 1 objs, err := render.RenderDir(filepath.Join(manifestDir, "network/frr-k8s"), &data) if err != nil { return nil, fmt.Errorf("failed to render frr-k8s manifests: %w", err) diff --git a/pkg/network/render_test.go b/pkg/network/render_test.go index 8cabe366aa..a47a661be8 100644 --- a/pkg/network/render_test.go +++ b/pkg/network/render_test.go @@ -680,6 +680,37 @@ func Test_renderFRRRoutingCapabilities(t *testing.T) { }) } +func Test_renderFRRStatusCleanerStrategy(t *testing.T) { + frrConf := &operv1.NetworkSpec{ + AdditionalRoutingCapabilities: &operv1.AdditionalRoutingCapabilities{ + Providers: []operv1.RoutingCapabilitiesProvider{ + operv1.RoutingCapabilitiesProviderFRR, + }, + }, + } + + render := func(replicaCount int) *appsv1.Deployment { + g := NewWithT(t) + br := fakeBootstrapResult() + br.OVN.ControlPlaneReplicaCount = replicaCount + objs, err := renderAdditionalRoutingCapabilities(frrConf, br, manifestDir) + g.Expect(err).NotTo(HaveOccurred()) + return mustFindRenderedObj[*appsv1.Deployment](t, objs, "Deployment", "frr-k8s-statuscleaner") + } + + t.Run("SNO: strategy is Recreate", func(t *testing.T) { + g := NewWithT(t) + d := render(1) + g.Expect(d.Spec.Strategy.Type).To(Equal(appsv1.RecreateDeploymentStrategyType)) + }) + + t.Run("HA: no strategy override", func(t *testing.T) { + g := NewWithT(t) + d := render(3) + g.Expect(d.Spec.Strategy.Type).To(BeEmpty()) + }) +} + func Test_renderNetworkingConsolePlugin(t *testing.T) { renderAndFindNginxConfig := func(t *testing.T, tlsProfile bootstrap.TLSProfile) string { g := NewWithT(t)