diff --git a/manifests/multus/30-browser-vpn-proxy.yaml b/manifests/multus/30-browser-vpn-proxy.yaml index 43f1f44..4a5c22b 100644 --- a/manifests/multus/30-browser-vpn-proxy.yaml +++ b/manifests/multus/30-browser-vpn-proxy.yaml @@ -1,11 +1,26 @@ -# sync-wave 3 — after RBAC/DaemonSet (0), the NAD (1), and the canary -# (2). Moved here from manifests/multus/reserved/ (2026-08-24) now that -# qBittorrent and JDownloader have both independently passed their -# canary, validation, and soak gates — the reservation this file's -# earlier header described is satisfied. Still governed only by the -# `multus` Argo CD Application's own manual-sync gate (no automated -# sync there at all) — the same gate already used for the DaemonSet, NAD, -# and canary, not a new mechanism. +# sync-wave 1 — same wave as the NAD (10-nad-vlan50.yaml), the only +# thing this actually needs to exist first. NOT wave 3/after-the-canary +# as originally drafted: that was a documentation convention, not a real +# dependency, and it turned out to actively break syncing. Root-caused +# live (2026-08-24): this cluster's argocd-cm sets +# resource.customizations.ignoreResourceUpdates.all to ignore /status +# changes cluster-wide (a deliberate, existing setting, not something to +# change just for this file) — Argo's wave orchestrator waits for each +# wave's resources to report Healthy before starting the next wave, but +# a Pod that's deleted and recreated (exactly what the canary is, every +# test round) needs Argo to observe a fresh Pending -> Running /status +# transition *during that sync*, which the ignore-updates config +# prevents it from ever seeing — so the operation hangs forever on +# "waiting for healthy state of /Pod/vlan50-canary" even once the Pod is +# actually Running. Already-stable resources (the DaemonSet, RBAC, NAD) +# never hit this because their cached health from a prior sync is still +# valid when nothing about them changed. Moved here from +# manifests/multus/reserved/ (2026-08-24) now that qBittorrent and +# JDownloader have both independently passed their canary, validation, +# and soak gates — the reservation this file's earlier header described +# is satisfied. Still governed only by the `multus` Argo CD Application's +# own manual-sync gate (no automated sync there at all) — the same gate +# already used for the DaemonSet, NAD, and canary, not a new mechanism. # # Before applying: # 1. Verify the NodePort below (30889) doesn't collide with anything @@ -85,7 +100,7 @@ metadata: name: browser-vpn-proxy namespace: downloads annotations: - argocd.argoproj.io/sync-wave: "3" + argocd.argoproj.io/sync-wave: "1" spec: replicas: 1 strategy: diff --git a/manifests/multus/README.md b/manifests/multus/README.md index 73f6665..3198cbb 100644 --- a/manifests/multus/README.md +++ b/manifests/multus/README.md @@ -13,9 +13,9 @@ comment. Nothing here applies to the cluster just because it's merged to | `01-rbac.yaml` | 0 | Multus ServiceAccount/ClusterRole/ClusterRoleBinding | | `02-daemonset.yaml` | 0 | Multus thick-plugin DaemonSet — **nodeSelector restricted to `nik-debian` only**, k3s-specific CNI paths | | `10-nad-vlan50.yaml` | 1 | VLAN 50 `NetworkAttachmentDefinition`, macvlan bridge on `enp1s0.50`, static IPAM | +| `30-browser-vpn-proxy.yaml` | 1 | `.12` — SOCKS5 proxy for browser traffic via PIA, replaces `manifests/media/gluetun-proxy.yaml`. No auth, no app-level IP allowlist (see its own header for why and what actually restricts access instead). Deliberately **not** waved after the canary — see its own header's "sync-wave 1" note for why that would hang the sync entirely — **do not sync without separate explicit approval** | | `vlan50-egress-guard-script.yaml` | (no wave annotation — apply alongside 10) | Shared init-container script consumed by the canary, qBittorrent, JDownloader, and `browser-vpn-proxy` | | `20-canary.yaml` | 2 | Temporary canary pod — **do not sync without separate explicit approval**, see its own header | -| `30-browser-vpn-proxy.yaml` | 3 | `.12` — SOCKS5 proxy for browser traffic via PIA, replaces `manifests/media/gluetun-proxy.yaml`. No auth, no app-level IP allowlist (see its own header for why and what actually restricts access instead) — **do not sync without separate explicit approval** | ## Before applying anything here @@ -30,10 +30,27 @@ comment. Nothing here applies to the cluster just because it's merged to 3. Sync order matters even within this one manual-sync Application: 00 → 01 → 02, confirm the Multus pod is actually Running on `nik-debian` and `/var/lib/rancher/k3s/agent/etc/cni/net.d` now has a generated - `00-multus.conf`, *then* 10, *then* — only with separate approval — 20. + `00-multus.conf`, *then* 10 (and, independently, 30 — same wave, no + ordering between them), *then* — only with separate approval — 20. `30-browser-vpn-proxy.yaml` follows the same "separate approval" gate as 20 — no Secret precondition, it needs no credentials at all (see its own header for why). +4. **This cluster's Argo CD ignores `/status` updates for reconciliation + purposes on every resource** (`argocd-cm`'s + `resource.customizations.ignoreResourceUpdates.all`, cluster-wide, not + specific to this Application — do not change it just for this + directory). Practical effect: a sync that wave-gates on a resource + whose health depends on a `/status` transition happening *during that + sync* — e.g. a Pod that was just deleted and recreated, going + Pending → Running — can hang forever on "waiting for healthy state of + /X", even once the resource is actually healthy live. This is why + `20-canary.yaml` no longer has anything synced after it in this + Application (see `30-browser-vpn-proxy.yaml`'s header) — don't + sync-wave anything new after the canary for the same reason. If a + sync ever hangs like this: `kubectl -n argocd patch application + multus --type=merge -p '{"operation": null}'` clears the stuck + operation (touches nothing in the actual cluster, just Argo's own + tracking) so a fresh sync can start. ## Canary lifecycle — re-running it after a Multus/CNI change