YP6M-3270 Scope the flex GPU device plugin to flex nodes only - #3
Open
brandonli-ybor wants to merge 1 commit into
Conversation
The gpu.nodeSelector matched p6m.dev/node-type=gpu-shared alone, which is not flex-specific: the platform's Karpenter time-sliced-gpu NodePool stamps that same label on cloud GPU nodes, where the gpu-operator already runs its own device plugin. Both plugins bind-mount /var/lib/kubelet/device-plugins and register the resource nvidia.com/gpu, and kubelet's device manager keeps only the last registrant — so a time-sliced node silently advertised 1 GPU instead of 4, depending on which plugin started last. Reproduced on ybor-playground-dev-westus2: restarting the flex plugin pod on a converged capacity-4 T4 dropped it to 1 and it never recovered, while the node labels still read replicas=4. Adding flex.azure.com/node=true (kubelet-set at registration on every flex node, absent on AKS nodes) makes the two DaemonSets mutually exclusive by construction. Refs: YP6M-3270
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.
Problem
gpu.nodeSelectormatchedp6m.dev/node-type=gpu-sharedalone. That label is not flex-specific — the platform's Karpentertime-sliced-gpuNodePool stamps the same label on cloud (AKS) GPU nodes, where the gpu-operator already runs its own device plugin. The chart's comment stated the assumption directly:On
ybor-playground-dev-westus2that is false: this DaemonSet schedules onto Karpenter-provisioned T4 nodes. Both plugins bind-mount/var/lib/kubelet/device-pluginsand register the resourcenvidia.com/gpu; kubelet's device manager keeps only the last registrant. So a time-sliced node advertises 4 GPUs or 1, depending on which plugin happened to start last — and it never self-heals.This is the real cause of YP6M-3270, which had been recorded as a Karpenter label race. It is not: the config label is set by kubelet at first registration (proven via
managedFields), and the gpu-operator's SIGHUP reload correctly re-registers in ~149 ms.Evidence (live,
ybor-playground-dev-westus2, nodeaks-time-sliced-gpu-9nlmk)Fresh node, both plugins present — operator registered last, so it won:
Forcing the reverse order — delete the flex pod, the DaemonSet recreates it so it registers last, operator's plugin untouched (0 restarts, still loaded with
replicas:4):Fix
Require both labels.
flex.azure.com/node=trueis set byterraform/ec2/main.tf:227in this repo as a kubelet--node-labelsentry on every flex node, andp6m.dev/node-type=gpu-sharedis added at:231for GPU-family instance types — same locals block, so a GPU flex node always has both, and an AKS node can never haveflex.azure.com/node. The two DaemonSets become mutually exclusive by construction, with no cloud-init change and no new label.Also updates the two comments that encoded the failed assumption, and bumps the chart 0.3.0 → 0.3.1.
Verification
Applied as a live DaemonSet patch on
ybor-playground-dev-westus2first, then verified end to end:Then the acceptance case — a brand-new Karpenter time-sliced node, zero intervention:
helm templatewithvalues-ybor-playground.yamlrenders the DaemonSet withnodeSelector: {flex.azure.com/node: "true", p6m.dev/node-type: gpu-shared}, matching what was validated live.Risk notes
flex.azure.com/nodewould no longer get the plugin. Today that label comes from this repo's own terraform, so the invariant is co-located; if flex nodes ever gain a second provisioning path, it must set both labels.helm unittestsuite (no*_test.yamlanywhere in the repo), so a selector assertion would mean introducing a test framework — out of scope for a one-line fix. Verified by live run + render instead.flex-node-systemupgrade. Merging this is what makes it permanent.Refs: YP6M-3270