Repository navigation
Conversation
…[ENG-1881] A release that declares a new index builds it while the upgrade is in flight, and on a 109 GB instances collection that took about an hour. The scheduler cannot warn anyone: by the time it logs, the pods have rolled. A pre-upgrade hook Job runs the new image's `migrate index-plan --gate` against the database the old release is still serving. It only reads, so new code against old data is safe. Over the threshold it exits 2 and Helm stops with the running release untouched. indexes.preUpgrade.mode is one enum rather than separate acknowledge and prebuild switches: the three states are exclusive, and booleans leave combinations with no defined meaning. Helm prints `BackoffLimitExceeded` and not the pod's log, which is where the estimate and the collection names are, so the delete policy keeps the pod and docs/eks/upgrading.md gives the kubectl logs line. activeDeadlineSeconds on the gate only. Reading the plan is a few listIndexes and $collStats calls, so overrunning means MongoDB is not answering, and a hook with no deadline holds helm upgrade open forever. A build gets no deadline because waiting is the point of that mode. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016uVeGDCC9GMmYpp8gZQSYt
The pre-upgrade recipe ran sync-indexes inside a current pod. The running release does not declare the indexes the next one adds, so that rebuilds the existing set and the gate blocks again on the next attempt. Render the hook's own Job at the target version instead, under a name of its own so it neither collides with the failed check nor deletes its log. No new template: the only thing the standalone build needs that the hook does not is a distinct name, and indexes.name already supplies it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016uVeGDCC9GMmYpp8gZQSYt
|
| Topic | Details | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Index Upgrade Check | Run currents-index-check before upgrades to gate or build pending indexes using configurable thresholds, timeouts, hook behavior, and execution settings.Modified files (3)
Latest Contributors(2)
| |||||||||
| Upgrade Runbook | Explain how to inspect failed hook logs and choose pre-build, in-upgrade build, or bypass workflows when an index check stops an upgrade.Modified files (2)
Latest Contributors(2)
|
|
Local evidence on Setup
Rendering, which the description says was never run:
Revision 2 was recorded The pre-build steps from
The other modes
Worth deciding before release: an image without The hook exits 1 and stays failed until the operator finds
Not covered
🤖 Generated with Claude Code |
An operator pinning currents.imageTag to a release older than the chart gets a hook that exits 1 with the migrate usage line, and nothing connects that to indexes.preUpgrade.mode. The check fails closed on purpose, so the way out is a documented flag rather than a weaker check. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016uVeGDCC9GMmYpp8gZQSYt
|
Thank you for running the On the pinned-image question: I think the chart should keep failing closed, and the gap is that the failure is illegible. Pushed as Why not the other two options:
That said, the exit-2/exit-1 split is now unused by its only caller, so if you would rather the hook distinguish them, the mechanism is there and it is a small change to the template. Your call — this is the kind of thing I would rather you decided than have me pick. Worth adding to the CHANGELOG at release time, in whatever wording you prefer: a pinned On the two things you listed as not covered: Generated by Claude Code |
Owner: @twk3
Linear: ENG-1881, ENG-1880
Part 2 of ENG-1881. The CLI verdict it calls is currents-dev/currents#4558 — this cannot be released until that is in an image, because the hook runs
migrate index-plan --gatefrom the image being upgraded to.What and why
A release that declares a new index builds it while the upgrade is in flight, and on a large
instancescollection that has taken about an hour with the install serving nothing. Nothing tells the operator beforehand: the scheduler logs it once the pods have already rolled.This adds a
pre-upgradehook Job,currents-index-check, that runs the new image'smigrateCLI against the database the old release is still serving, before any pod rolls.index-planonly reads, so running the new code against the old data is safe.indexes.preUpgrade.mode:gate(default) — read the plan, fail the hook if the estimate is overthresholdSeconds(600). Helm stops the upgrade with the running release untouched.build— build the indexes first and wait. NoactiveDeadlineSeconds: the point of this mode is to wait.off— render no hook.Helm does not print a failed hook's log
All the operator sees is:
The estimate and the collection names are in the pod. That is why the delete policy is
before-hook-creationand nothook-failed—hook-faileddeletes the pod the moment the Job fails, taking the only copy of the message with it.docs/eks/upgrading.mdleads with thekubectl logsline.ENG-1880 is in here too (second commit)
The gate is only worth having if it can offer something other than a refusal, and the first version of that recipe I wrote was wrong: it ran
sync-indexesinside the running scheduler, which doesn't declare the new indexes, so it rebuilds what is already there and the gate blocks again next time.ENG-1880 planned a separate Job template for this. It doesn't need one. The hook in
mode: buildalready is that Job — same image, same command — and the only thing a standalone pre-build needs that the hook doesn't is a name of its own, whichindexes.namesupplies:helm templatewrites nothing to the cluster, so--versionis what reaches the next image. The operator picks the window, nothing is down, and the build records a measured rate that makes later estimates trustworthy.I filed the two tickets together rather than splitting because ENG-1880's whole delivery is the docs section for the feature in commit 1, and separating them would mean shipping a gate that tells operators to do the wrong thing.
Verification
I could not render this: downloading
helmandhelm-docswas blocked in my container and I didn't work around it. I checked theif/with/endbalance by hand, hand-rendered both modes into YAML thatyaml.safe_loadparses with the right command, deadline and annotations, and derived the 9docs/configuration.mdrows from the# --annotations using helm-docs' own formatting rules.That has since been checked properly, and both parts held:
docs-check(helm-docs) andlint-test(ct lint, which renders) are green, so the table matches and the template compiles.instances, including thepre-upgradeexecution thatct installcannot reach:gateblocked with the running release untouched at generation 1, the pre-build recipe built the index and the next upgrade passed withNo index builds pending., andbuildandoffbehaved as intended.Still unverified: the
--repo/--versionform of the pre-build recipe, which needs a published chart, and MongoDB with authentication.Two things worth a reviewer's eye
currents.imageTagis pinned to a release older than the one carrying--gate, the hook exits 1 with themigrateusage line. The chart fails closed here on purpose — a gate that silently stops gating is worse than one that fires confusingly — so the fix is legibility, not tolerance:docs/eks/upgrading.mdnow matches on that usage line and givesmode: offas the way through. Reasoning in full, including why a version floor and a tolerant wrapper are both worse. Worth a CHANGELOG line at release.The container sets
HOME=/tmpwith a writableemptyDirbecauseglobal.securityContextsetsreadOnlyRootFilesystem; both modes ran under that security context in the local run.No
Chart.yamlorCHANGELOG.mdbump — the repo does those in separaterelease:PRs.🤖 Generated with Claude Code
https://claude.ai/code/session_016uVeGDCC9GMmYpp8gZQSYt