Bound and hash the drain PDB's node label - #511
Open
boddumanohar wants to merge 1 commit into
Open
Conversation
ensurePDB built the per-node PodDisruptionBudget's selector from the raw
Node name, while labelStoragePod labeled the pods that selector has to
match through sanitizeLabelValue. A Node name may be 253 characters and
a label value stops at 63, so the two diverged the moment a name needed
shortening, and three things went wrong at once:
- The selector value was illegal for a name over 63 bytes, so the API
server rejected the PDB and drain protection was never established.
- Even had it been accepted, it selected a value no pod carried, so
the budget protected nothing and eviction proceeded unblocked.
- sanitizeLabelValue truncated without a digest, so two names sharing
a 63-character prefix produced one label value and one PDB name.
Draining the second node then retargeted the first node's budget.
sanitizeLabelValue now returns a name that is already a legal label
value unchanged, and otherwise cuts it to leave room for a digest of the
whole original and joins the two. That bounds the result, keeps a
readable prefix, keeps distinct names distinct, and cannot end on a
character a label value may not end on. It is deterministic, so the same
node yields the same value on every reconcile. The PDB selector now uses
it, so the selector and the pod label are derived the same way.
Because an already-legal value passes through untouched, every node name
in use on a cluster today keeps the label value it has, and a drain in
flight across the upgrade is unaffected.
Verified: TestDrainPDBLabelIsBoundedAndMatchesPod is red on the
unchanged tree in all three cases — the selector value is "not a legal
label value", the selector "protects nothing", and two names "both
derive the label value" — and green after. The operator suite (15
packages) passes, including the pre-existing TestSanitizeLabelValue and
TestEnsurePDB cases, which pin the unchanged short-name behavior.
make -C operator lint reports 0 issues.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What
ensurePDBbuilt the per-node PDB's selector from the raw Node name, whilelabelStoragePodlabeled the pods that selector must match throughsanitizeLabelValue. A Node name may be 253 characters; a label value stops at 63. Three things went wrong at once:sanitizeLabelValuetruncated without a digest, so two names sharing a 63-character prefix yield one label value and one PDB name — draining the second node retargets the first node's budgetFix
sanitizeLabelValuereturns an already-legal value unchanged; otherwise it cuts the name to leave room for a digest of the whole original and joins the two. Bounded, readable, deterministic, and it cannot end on a character a label value may not end on. The PDB selector now uses it, so selector and pod label are derived the same way.Upgrade
No effect on existing clusters: an already-legal value passes through untouched, so every node name in use today keeps the label value it has, and a drain in flight across the upgrade is unaffected.
Tests
TestDrainPDBLabelIsBoundedAndMatchesPod— red on the unchanged tree in all three cases (illegal value, selector matching no pod, two names colliding), green after. The pre-existingTestSanitizeLabelValueandTestEnsurePDB*cases still pass, which is what pins the unchanged short-name behavior.Gates
Operator suite (15 packages) passes;
make -C operator lint0 issues; no generator drift.Two notes, neither addressed here:
operator/docs/tests/, so there was no matrix to add a row to. Enumerating one is atest-scenariosjob, not a drive-by.sanitiseDNSLabel(storage.simplyblock.io/worker) andnodeprobe.labelValueare two more hand-rolled variants of this same primitive, andsanitiseDNSLabelhas the same unbounded defect on a different label. Consolidating the three intoatlas-lib/kubeis the obvious follow-up.🤖 Generated with Claude Code