diff --git a/apps/gitea.yaml b/apps/gitea.yaml index a562e4d..affe41c 100644 --- a/apps/gitea.yaml +++ b/apps/gitea.yaml @@ -61,6 +61,8 @@ metadata: app.kubernetes.io/name: gitea spec: replicas: 1 + strategy: + type: Recreate selector: matchLabels: app.kubernetes.io/name: gitea diff --git a/apps/jackett.yaml b/apps/jackett.yaml index 99c557b..df03587 100644 --- a/apps/jackett.yaml +++ b/apps/jackett.yaml @@ -61,6 +61,8 @@ metadata: app.kubernetes.io/name: jackett spec: replicas: 1 + strategy: + type: Recreate selector: matchLabels: app.kubernetes.io/name: jackett @@ -123,7 +125,7 @@ spec: - port: '9117' protocol: TCP --- -# CiliumNetworkPolicy internet/world egress (vpn class, R-NET-05): jackett-allow-internet-egress +# CiliumNetworkPolicy world egress allow (egress class governs the path; R-NET-05): jackett-allow-internet-egress apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: diff --git a/apps/pihole.yaml b/apps/pihole.yaml index 9bdd907..34641b9 100644 --- a/apps/pihole.yaml +++ b/apps/pihole.yaml @@ -61,6 +61,8 @@ metadata: app.kubernetes.io/name: pihole spec: replicas: 1 + strategy: + type: Recreate selector: matchLabels: app.kubernetes.io/name: pihole @@ -123,7 +125,7 @@ spec: - port: '80' protocol: TCP --- -# CiliumNetworkPolicy internet/world egress (internet class, R-NET-05): pihole-allow-internet-egress +# CiliumNetworkPolicy world egress allow (egress class governs the path; R-NET-05): pihole-allow-internet-egress apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: diff --git a/apps/plex.yaml b/apps/plex.yaml index 607deab..e1d4517 100644 --- a/apps/plex.yaml +++ b/apps/plex.yaml @@ -61,6 +61,8 @@ metadata: app.kubernetes.io/name: plex spec: replicas: 1 + strategy: + type: Recreate selector: matchLabels: app.kubernetes.io/name: plex @@ -120,7 +122,7 @@ spec: - port: '32400' protocol: TCP --- -# CiliumNetworkPolicy internet/world egress (internet class, R-NET-05): plex-allow-internet-egress +# CiliumNetworkPolicy world egress allow (egress class governs the path; R-NET-05): plex-allow-internet-egress apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: diff --git a/apps/qbittorrent.yaml b/apps/qbittorrent.yaml index 8251127..f7569e0 100644 --- a/apps/qbittorrent.yaml +++ b/apps/qbittorrent.yaml @@ -61,6 +61,8 @@ metadata: app.kubernetes.io/name: qbittorrent spec: replicas: 1 + strategy: + type: Recreate selector: matchLabels: app.kubernetes.io/name: qbittorrent @@ -123,7 +125,7 @@ spec: - port: '8080' protocol: TCP --- -# CiliumNetworkPolicy internet/world egress (vpn class, R-NET-05): qbittorrent-allow-internet-egress +# CiliumNetworkPolicy world egress allow (egress class governs the path; R-NET-05): qbittorrent-allow-internet-egress apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: diff --git a/apps/radarr.yaml b/apps/radarr.yaml index f36f9db..6525a54 100644 --- a/apps/radarr.yaml +++ b/apps/radarr.yaml @@ -61,6 +61,8 @@ metadata: app.kubernetes.io/name: radarr spec: replicas: 1 + strategy: + type: Recreate selector: matchLabels: app.kubernetes.io/name: radarr @@ -165,7 +167,7 @@ spec: - port: '7878' protocol: TCP --- -# CiliumNetworkPolicy internet/world egress (vpn class, R-NET-05): radarr-allow-internet-egress +# CiliumNetworkPolicy world egress allow (egress class governs the path; R-NET-05): radarr-allow-internet-egress apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: diff --git a/apps/sonarr.yaml b/apps/sonarr.yaml index b5769b2..f39e26e 100644 --- a/apps/sonarr.yaml +++ b/apps/sonarr.yaml @@ -61,6 +61,8 @@ metadata: app.kubernetes.io/name: sonarr spec: replicas: 1 + strategy: + type: Recreate selector: matchLabels: app.kubernetes.io/name: sonarr @@ -165,7 +167,7 @@ spec: - port: '8989' protocol: TCP --- -# CiliumNetworkPolicy internet/world egress (vpn class, R-NET-05): sonarr-allow-internet-egress +# CiliumNetworkPolicy world egress allow (egress class governs the path; R-NET-05): sonarr-allow-internet-egress apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: diff --git a/catalog/render.py b/catalog/render.py index de0753f..13e1fd0 100644 --- a/catalog/render.py +++ b/catalog/render.py @@ -243,6 +243,17 @@ def r_deployment(s: dict) -> dict: if ann: tmpl_meta["annotations"] = ann + spec = {"replicas": 1} + # An app with persistent storage mounts a ReadWriteOnce Longhorn PVC. The default + # RollingUpdate strategy tries to start the NEW pod before terminating the old one, but + # the old pod still holds the RWO volume -> the new pod is stuck ContainerCreating and + # the rollout deadlocks (single-replica app can never hand the volume over). Recreate + # terminates the old pod first, freeing the PVC for the new one (R-STATE-01/02). + if s["storage"]: + spec["strategy"] = {"type": "Recreate"} + spec["selector"] = {"matchLabels": {"app.kubernetes.io/name": s["name"]}} + spec["template"] = {"metadata": tmpl_meta, "spec": pod_spec} + return { "apiVersion": "apps/v1", "kind": "Deployment", @@ -251,11 +262,7 @@ def r_deployment(s: dict) -> dict: "namespace": s["name"], "labels": {"app.kubernetes.io/name": s["name"]}, }, - "spec": { - "replicas": 1, - "selector": {"matchLabels": {"app.kubernetes.io/name": s["name"]}}, - "template": {"metadata": tmpl_meta, "spec": pod_spec}, - }, + "spec": spec, } diff --git a/conformance/tests/l1-rendering/egress-class-render/golden/egress-internet.expected.yaml b/conformance/tests/l1-rendering/egress-class-render/golden/egress-internet.expected.yaml index dfcbc77..e5adb43 100644 --- a/conformance/tests/l1-rendering/egress-class-render/golden/egress-internet.expected.yaml +++ b/conformance/tests/l1-rendering/egress-class-render/golden/egress-internet.expected.yaml @@ -61,6 +61,8 @@ metadata: app.kubernetes.io/name: sonarr spec: replicas: 1 + strategy: + type: Recreate selector: matchLabels: app.kubernetes.io/name: sonarr diff --git a/conformance/tests/l1-rendering/egress-class-render/golden/egress-vpn.expected.yaml b/conformance/tests/l1-rendering/egress-class-render/golden/egress-vpn.expected.yaml index dce9285..5093288 100644 --- a/conformance/tests/l1-rendering/egress-class-render/golden/egress-vpn.expected.yaml +++ b/conformance/tests/l1-rendering/egress-class-render/golden/egress-vpn.expected.yaml @@ -61,6 +61,8 @@ metadata: app.kubernetes.io/name: sonarr spec: replicas: 1 + strategy: + type: Recreate selector: matchLabels: app.kubernetes.io/name: sonarr