Repository navigation
memex 503 on node drain: 2 replicas, no PodDisruptionBudget (PDB gated on keda.enabled), no anti-affinity #3772
Description
What happened
memex.systemorph.com answered 503 for ~90 s from 01:05:45Z on 2026-09-09. Both portal pods of one ReplicaSet (memex-portal-deployment-76c99bdc6-9stvn, -g7f89) logged Application is shutting down... at 01:05:01Z simultaneously; replacements -kcb4d / -mwnnb reached PortalReady at 01:05:58Z / 01:06:01Z. No image change, no rollout (same ReplicaSet), no crash (createdump/Unhandled absent).
Read cluster-wide through Loki (all namespaces, 70 min): at 01:09:08Z monitoring/loki-0, loki-alertmanager-0, loki-prometheus-pushgateway, memex-cloud/memex-website and both k8s-dashboard pods stopped/restarted within 15 s; at 01:09:23Z memex/…-kcb4d and memex-cloud/…-276kb shut down together; replacements Ready 01:10:35Z / 01:10:36Z; a further memex-cloud replacement at 01:13:30Z. That is a node drain rolling node by node (an AKS node-pool operation — planned maintenance / node image upgrade / autoscaler consolidation; which one needs az, which is break-glass under the operate-through-memex directive). Pods across three namespaces on one node stopping together is not an application event.
Modules:AutoRecycleOnStaleBuild is excluded: the converge branch posts a hub DisposeRequest (NodeTypeEnrichmentHelpers.cs:2122), never a process exit. The operator-image patch on the record and the CD run that started at 01:02Z were coincidental.
The defect that is ours
A single drain took BOTH memex replicas because nothing stopped it:
deploy/helm/templates/memex-portal/pdb.yamlis gated onkeda.enabled. memex's helm-release lane renders-f vault-values.yaml -f values.memex.public.yaml(Memexhelm-release.yml:530) — notdeploy/aks/values.aks.yaml, where KEDA is on — and the memex overlay never mentionskeda. So memex runsreplicas.portal: 2with no PodDisruptionBudget: the eviction API had nothing to honour and evicted both pods at once.- The pod template has no
podAntiAffinity/topologySpreadConstraints, so the scheduler is free to co-locate both replicas on one node (memex also has no nodeSelector — thesilospool is min 2 / max 4 nodes, so spreading was possible).cluster-autoscaler.kubernetes.io/safe-to-evict: "false"only speaks to the autoscaler's bin-packing; a drain ignores it. check-chart-invariants.pyasserts "a PDB implies a floor > 1" (invariant 6) but not the converse — a floor > 1 with no PDB rendered green.
Fix
- Render the PDB whenever the replica floor is ≥ 2 —
keda.enabledORreplicas.portal >= 2—maxUnavailable: 1as today. - Add
podAntiAffinity(preferred,kubernetes.io/hostname) to the portal pod template so two replicas land on two nodes when two are available, without ever leaving a pod Pending. - Invariants: a replica floor > 1 implies a PDB is rendered, and implies the pod template spreads replicas across hosts.
- Doc: DeploymentAKS → what a drain does to a 2-replica namespace with and without a budget.
Secondary (separate issue): Loki lost the 01:05Z lines when loki-0 itself was drained at 01:09:08Z — read at 01:08, gone at 01:11 — so the monitoring stack has no WAL / persistence for unflushed chunks.
Activity
rbuergi commentedon Sep 9, 2026
Fixed on
mainby PR #3774 (merged 2026-09-09T01:46:46Z). The PR body carriesCloses #3772, but closing keywords do not fire in this repo — merges land through the queue/bot — so this was left open. Verified in the merged chart rather than taken from the PR body:The PDB gate no longer keys on
keda.enabled(deploy/helm/templates/memex-portal/pdb.yamlL1–2):so the budget is rendered for every HA deployment — KEDA
minReplicasor a plainreplicas.portal: 2. The file records the incident in place:Anti-affinity is present in
memex-portal/deployment.yaml(podAntiAffinity), the other half this issue named.The chart also fixes a shape the issue did not reach:
minAvailable: 2would demand BOTH pods and block every voluntary eviction, so the budget is derived from the replica floor rather than hard-coded.🚨 This is the CHART, not the cluster. A rendered template only takes effect on the next
helm upgradeof each namespace. Until memex is deployed from a release carrying this, the running Deployment still has no PDB and a node drain can still take both pods together — the 503 this issue is about. Closing it as fixed, not as deployed; if the same 503 recurs before the roll, that is expected and not a reopen.rbuergi commentedon Sep 9, 2026
Backlog verification: fixed by merged PR #3774 (b9731a1). The current chart renders the PDB for a replica floor >= 2 independently of KEDA and includes preferred hostname pod anti-affinity. Both requested invariants and the non-KEDA two-replica fixture are present; rerunning check-chart-invariants.sh passed all 7 rendered combinations. The requested DeploymentAKS documentation and Fix release note are present. Closing the implemented chart defect; this check establishes the repository fix, not a fresh observation of the live cluster rollout.