From b56a868b4ea5111526d2468101c7211542078050 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Thu, 4 Jun 2026 07:52:02 +0000 Subject: [PATCH] wealthfolio-sync: podAffinity to co-locate with app pod (RWO multi-attach fix) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The monthly wealthfolio-sync CronJob mounts the same RWO wealthfolio-data-encrypted volume (shared wealthfolio.db SQLite) as the always-running wealthfolio app Deployment. RWO attaches to only one node, but the sync had no affinity — so the 2026-06-01 run landed on node4 while the app held the volume on node3 and hung in ContainerCreating for 3 days (FailedAttachVolume / Multi-Attach), surfacing as a problematic_pods WARN. Add a required podAffinity (app=wealthfolio, topologyKey hostname) so the sync always schedules onto the app's node, where the volume is already attached (RWO permits multiple pods on the same node). Verified: a fresh sync run co-located on node3, attached cleanly, and broker-sync started. --- stacks/wealthfolio/main.tf | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/stacks/wealthfolio/main.tf b/stacks/wealthfolio/main.tf index 51247086..fd8e2e98 100644 --- a/stacks/wealthfolio/main.tf +++ b/stacks/wealthfolio/main.tf @@ -10,7 +10,7 @@ resource "kubernetes_namespace" "wealthfolio" { name = "wealthfolio" labels = { "istio-injection" : "disabled" - tier = local.tiers.aux + tier = local.tiers.aux "keel.sh/enrolled" = "true" } } @@ -657,6 +657,25 @@ resource "kubernetes_cron_job_v1" "wealthfolio_sync" { metadata {} spec { restart_policy = "OnFailure" + # Co-locate with the main wealthfolio app pod: both mount the same + # RWO `wealthfolio-data-encrypted` volume (the shared wealthfolio.db + # SQLite). An RWO volume attaches to only ONE node, so without this + # the monthly sync pod can land on a different node than the app and + # hang forever with a Multi-Attach error (observed 2026-06-04: a + # 2026-06-01 sync sat ContainerCreating for 3 days on node4 while the + # app held the volume on node3). + affinity { + pod_affinity { + required_during_scheduling_ignored_during_execution { + label_selector { + match_labels = { + app = "wealthfolio" + } + } + topology_key = "kubernetes.io/hostname" + } + } + } image_pull_secrets { name = "registry-credentials" }