-
Notifications
You must be signed in to change notification settings - Fork 0
fix(chart): render control-plane images from the last-refreshed digest so helm upgrade preserves the pin #1013
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
saqlainsyed007
wants to merge
11
commits into
develop
Choose a base branch
from
fix/199-seed-controlplane-digest-from-annotation
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
d92bdab
fix(chart): render control-plane images from the last-refreshed diges…
8e1fc65
fix(chart): validate the annotation digest and honour imageRefresh.su…
dd07635
test(chart): assert path 2 renders the last-refreshed digest onto the…
62ca905
Merge remote-tracking branch 'origin/develop' into HEAD
616b843
fix(chart): suspend keeps the control-plane pin, add clusterless look…
ad15b4f
Merge remote-tracking branch 'origin/develop' into HEAD
a54deb0
docs(chart): narrow the operator-facing offline-restart guarantee for…
9666cf0
docs(migrations): scope the .image-conflict note to the server-side p…
1c78acf
fix(chart): don't seed the init container, and surface lookup fail-op…
3b4dce6
chore(chart): rebump to 1.9.111 so B sequences above A's 1.9.110 (cli…
a7553fc
Merge remote-tracking branch 'origin/develop' into HEAD
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BLOCKING (High) — a third annotation-vs-live lag state that #1008 cannot heal, and here it becomes a chart-enforced downgrade.
The merge-order section names two lag states (rollout timeout mid-tick,
helm rollback). There is a third, and it is the one that does not self-heal: the image-refresh flap lockout.Mechanism, all in
image-refresh-cronjob.yamlon this branch:annotate_argsis written in ONE batchedkubectl annotatethat runs after all threeset image+rollout statuspairs (~L700). Underset -e, arollout statustimeout onrequests-proxyor the resource-monitor DaemonSet exits the tick before that annotate — soapiis already at@D1while all threelast-refreshed-*annotations still say@D0.ATTEMPT_KEY, which resets only on a fully settled rollout. AfterMAX_REFRESH_ATTEMPTSthe flap guardexit 0s before the annotate block (~L616-631) and requires a human to clear the annotation to re-arm.So the annotations are pinned at
D0indefinitely while the live spec is atD1. With this PR every subsequenthelm upgradenow renders@D0onto all five sites and, because auto-upgrade applies client-side (--reset-then-reuse-values --atomic --cleanup-on-fail, no--server-side), Helm's 3-way merge overwrites the live@D1with@D0— an active, deterministic downgrade ofjobs-manager,pods-monitorandrequests-proxy, potentially off a security refresh. Before this PR the re-render wrote a bare:tag, which was #199 (stale) but never an enforced move backwards.And #1008 does not cover it: its live-spec reconcile sits inside the
recorded == latestbranch. Hererecorded (D0) != latest (D1), so the tick takes the "digest changed" path, hits the flap guard, and the reconcile branch is never reached. Landing #1008 first fixes the rollback state but not this one.Suggested fix in scope for B: make the helper ignore an annotation the live spec has already moved past — or in A, write each image's
last-refreshed-*annotation immediately after that workload's ownrollout statusinstead of batching all three at the end, and write the annotation before the flap guard'sexit 0.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed this is real and needs settling before merge, not leaving to merge order. Going with (a) — fix the annotation timing in #1008, not (b) here. Reasoning:
rollout statussucceeds, and move a settled workload's annotate before the flap guard'sexit 0, so a lockout tick still records what actually rolled. Thenrecorded == latestholds and fix(image-refresh): re-pin the digest when a helm re-render reverts the workload to :tag #1008's existing live-spec reconcile covers the state — it's no longer stranded in therecorded != latestpath.lookupof the live container image with exactly the fail-open semantics you flag one thread down at_helpers.tpl:561(empty map on RBAC/apiserver failure), and it only masks the symptom in the render path — the annotation stays wrong for anything else that reads it, and "live has moved past" is ambiguous about which digest is then authoritative.So this lands in #1008 (per-workload annotate, before the flap-guard
exit 0), #1013 rebases on it, and this thread resolves once that's in. Leaving it open here until then.On the related MIGRATIONS.md point: agreed the SSA-conflict line is Helm-4 hand-run only; I'll scope it to say the automated fleet path (Helm 3.16 client-side) overwrites rather than conflicts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Real, and you're right that #1008 as written doesn't heal it — its live-spec reconcile sits in the
recorded == latestbranch, which the flap-lockout state never reaches. This is a BLOCKING precondition on A (#1008), not something B can fix alone, so per that I'm leaving this open and flagging it on #1008: the robust fix is A-side — write each image'slast-refreshed-*annotation immediately after that workload's ownrollout status(not one batched annotate after all three), and write it before the flap-guard'sexit 0, so the annotation can never lag the live spec into a chart-enforced backward move. Your own 9666cf0 note confirms the mechanism: the fleet path is Helm-3 client-side, whose 3-way merge overwrites live@D1with the rendered@D0rather than conflicting. B stays held behind A until A covers this. (Thetag-lookup-failedsignal I added for the lookup thread makes a:tagfall-back observable, but not this backward-move — that needs the A-side ordering fix.)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Answering the D0-overwrite directly, and settling it rather than leaving it to merge order: option (a), in #1008. The
last-refreshed-<image>annotation should be written per-workload, right after that workload's ownrollout status, and before the flap guard'sexit 0— so a rollout that times out on requests-proxy or the resource-monitor DaemonSet can never leaveapiat@D1with the annotation frozen at@D0. With that, this helper only ever renders a digest the live spec has actually reached, and the "healthy jobs-manager moved backwards D1→D0 underRecreate, every bump while the lockout holds" scenario cannot arise.I'm keeping this in A, not B, because the annotation write-ordering is A's code (
image-refresh-cronjob.yaml), and B renders whatever A records — a B-side "ignore an annotation the live spec moved past" (option b) would have to re-read the live container image and duplicate A's reconcile logic in a template, which is the wrong place for it. B stays held behind A (already its declared prerequisite), and this specific ordering fix is now an explicit precondition on A — I've flagged it on #1008 with your analysis, tied to @LukasWodka's "A's reconcile must run before, not behind, the lockout check." So: not a merge-order hope, a named A-side change that must land before B.Leaving this thread open until #1008 carries it. On the related MIGRATIONS line — you're right; it's scoped to the hand-run Helm-4 SSA path now (the author's 9666cf0 already narrowed it: the Helm-3.16 client-side fleet path overwrites rather than conflicting).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refining the settlement now that A is essentially done. Option (a), split to an internal follow-up ticket rather than held inside #1008 — because your own re-review of A concluded its current scope is complete ("nothing else outstanding from me" after the rebump), and this is ordering hardening, not a gap in what A set out to do. The follow-up carries the exact spec: write each
last-refreshed-<image>-digestannotation immediately after that workload's ownrollout status, and before the flap guard'sexit 0, so the annotation can never trail the live spec.It must land before the exposure can matter on a fleet running B, and it's bounded until then: it needs the flap lockout (repeated rollout timeouts — e.g. a cordoned/NotReady node keeping the DaemonSet's
desiredNumberScheduledfrom settling), A'srecorded == latestreconcile heals every non-locked state, and@D0is a valid, previously-pulled image, not an unstartable ref.So: question answered (option a), fix specced and tracked, A landing first, B held behind it. If that settles it for you, this thread is yours to resolve / approve on; if you'd rather the ordering change land inside A before it merges, say so and I'll move it there instead of the follow-up — no strong preference on my side either, matching yours.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Settled — taking option (a) and the split, and I'm not re-opening the choice. Your reasoning for keeping it A-side is the right one: (b) would put a second live-image
lookupinto the render path with exactly the fail-open semantics of the_helpers.tpl:561thread, and duplicate A's reconcile inside a template. The annotation should stop lying rather than the renderer learn to detect that it is.backend#3575 captures it faithfully — the per-workload annotate, the
exit 0ordering, the rejected alternative, and the bound (needs the durable lockout;@D0is a valid previously-pulled image). Good ticket.Your direct question — "or move it inside A instead" — is moot now: A merged at 07:22:04Z, about five minutes after you wrote that. I checked merged develop rather than assuming:
image-refresh-cronjob.yamlstill writes everylast-refreshed-*-digestthrough the single batchedkubectl annotate $annotate_argsat line 879, after therollout statuscalls (833/842), with the flap guard'sexit 0at line 804 ahead of it. So #3575 is the only remaining home for the fix — the in-A option is gone.That is the one thing I'd still like nailed down, and it's the only reason I'm leaving this open. Your own condition is "it must land before the exposure can matter on a fleet running B." With A merged, nothing sequences #3575 against this PR: #3575 is open, unassigned and unlabelled, and B is otherwise green. The condition is stated in two comment threads and an issue body, none of which can stop B merging first.
So this thread is no longer the original finding — that's answered — it's now just the sequencing marker. Resolve it when either #3575 lands, or the dependency is recorded somewhere that actually gates this PR. Happy either way; I only want the ordering to survive the fact that A is already in.
For the record, I'm not the blocker here — @LukasWodka's change-request is the standing one, and it's on the current head.