Support NVIDIADriver reconciliation and driver upgrades without a ClusterPolicy - #2572
Conversation
8ffcfc3 to
479562c
Compare
5691bbc to
e5dcecd
Compare
479562c to
0e75d4c
Compare
3b7cc55 to
4ad2c9d
Compare
1a06b01 to
b101993
Compare
0e75d4c to
7f38f41
Compare
b101993 to
7f26b3c
Compare
fdb7c6e to
a9629e2
Compare
| return reconcile.Result{}, err | ||
| } | ||
|
|
||
| if clusterPolicy == nil { |
There was a problem hiding this comment.
We can merge two if blocks into one with this change
| if clusterPolicy == nil { | |
| if clusterPolicy == nil || clusterPolicy.Spec.Driver.UseNvidiaDriverCRDType() { |
There was a problem hiding this comment.
Actually, isn't it possible now to have both ClusterPolicy-backed drivers and NVIDIADriver-backed drivers (we can continue to debate whether this is actually desired or not in a separate thread)? IIUC the upgrade-controller, as currently implemented, does not account for that use case -- it only calls reconcileNVIDIADriverUpgrades() OR reconcileClusterPolicyDriverUpgrades.
There was a problem hiding this comment.
The problematic scenario -- ClusterPolicy and GPUCluster exist; clusterpolicy.spec.driver.useNvidiaDriverCRD=false; NVIDIADriver CRs exist which target DRA nodes. In this case, the upgrade-controller will not be able to manage the upgrades for both the ClusterPolicy-owned driver daemonsets and the NVIDIADriver-owned driver daemonsets.
There was a problem hiding this comment.
Good catch. You are right that the upgrade controller does not handle that.
As we discussed offline, we decided not to support it. To summaize, enabling DRA now requires that all driver management in the cluster is done through NVIDIADriver CRs. A ClusterPolicy with useNvidiaDriverCRD=false alongside a GPUCluster is treated as an invalid configuration.
| } | ||
| hostRoot = clusterPolicy.Spec.HostPaths.RootFS | ||
| case gpuCluster != nil: | ||
| hostRoot = gpuCluster.Spec.HostPaths.RootFS |
There was a problem hiding this comment.
Correct me if I am wrong, but in the scenario where both ClusterPolicy and GPUCluster exist, will the .spec.hostPaths.rootFS from GPUCluster have the higher order of precedence?
There was a problem hiding this comment.
ClusterPolicy takes precedence today. Now, I believe this combination is only valid when the ClusterPolicy sets useNvidiaDriverCRD=true, and in that case ClusterPolicy's hostPaths.rootFS is used.
There was a problem hiding this comment.
I see that this hostRoot value gets used here
- name: host-root
hostPath:
path: {{ .HostRoot | default "/" }}
Thinking about this more, it doesn't make much sense to make this global value and we are better off getting this value from the NVIDIADriver CR. For this, we would need to add a new field called hostRoot to the NVIDIADriver CR. This is the behaviour I envision in the following scenarios:
- If the
GPUClusterresource is present (whether by itself or along withClusterPolicy, then we get the hostRoot from theNVIDIADriverCR, else we fallback to the GPUCluster hostRoot. Here we will never get the hostRoot fromClusterPolicy. This way we ensure zero dependency onClusterPolicyin aGPUClusterflow - If only
ClusterPolicyis present, then we either get the hostRoot from theNVIDIADriver CR(the newly added field), else we fallback to theClusterPolicy.Spec.HostPaths.RootFS
This can be done in a follow-up PR
There was a problem hiding this comment.
Note that when we add hostRoot to the NVIDIADriver CR, it'll be an additive change and it will be an optional field. If this is empty, it will be defaulted to "/" as we currently do today
There was a problem hiding this comment.
Note, the host root is needed for many of our daemonsets, not just the driver. So we still need this field to be present in the GPUCluster CR. What is the benefit in having users configure this field in multiple places (GPUCluster and NVIDIADriver CRs)?
There was a problem hiding this comment.
Yes, the rest of the HostPaths fields are used correctly in operands whether they come from GPUCluster or ClusterPolicy. For the driver daemonset however, it's just the .HostPaths.RootFS field that is relevant
There was a problem hiding this comment.
I'm in favor of moving hostRoot to NVIDIADriver and removing it entirely from GPUCluster.
In the legacy ClusterPolicy path, we can get the hostRoot from either NVIDIADriver CR (if specified) or from ClusterPolicy.Spec.HostPaths.RootFS when useNvidiaDriverCRD=true, and from ClusterPolicy.Spec.HostPaths.RootFS only when useNvidiaDriverCRD=false.
There was a problem hiding this comment.
After discussing internally, we have come to a consensus on how to move forward with this. The main issue we that we want to address (in a follow-up PR) is that there should be no cross-CR or circular dependency between the custom resources.
- The hostRoot will be hard-coded as
/for now. - We had between two approaches to fix this problem. Either adding a new hostRoot field to the
NVIDIADriverCRD or adding a new environment variable to determine the hostRoot to be set in both the driver daemonset and the DRA driver kubelet plugin daemonset. This is still ongoing.
There was a problem hiding this comment.
Done. The host root is now hard-coded to / whenever a GPUCluster is present, including when a ClusterPolicy coexists with it, so NVIDIADriver never reads it from another CR. Only the ClusterPolicy-only legacy path still sources spec.hostPaths.rootFS. Also added a ClusterPolicy-only test case for that path.
|
Thanks @karthikvetrivel! Can you also squash your commit history here? |
f9e8163 to
aeca33f
Compare
| if err := r.List(ctx, clusterPolicies); err != nil { | ||
| return "", fmt.Errorf("error listing ClusterPolicy objects: %w", err) | ||
| } | ||
| for i := range clusterPolicies.Items { |
There was a problem hiding this comment.
Does it make sense to loop through every possible clusterPolicy? Don't we only need to care about the active/singleton clusterPolicy?
There was a problem hiding this comment.
I was thinking about this as well, but we don't ever enforce a singleton ClusterPolicy. You're right — there is only one active ClusterPolicy and extra CPs get status.state = Ignored, but only asynchronously after the CP controller reconciles them so filtering on status could lead to a potential races.
There was a problem hiding this comment.
This is somewhat related to the TODO above resolveActiveConfig, which we can address in a follow up.
There was a problem hiding this comment.
Can you add the TODO here too?
aeca33f to
cb4dbc6
Compare
| if err := r.List(ctx, clusterPolicies); err != nil { | ||
| return "", fmt.Errorf("error listing ClusterPolicy objects: %w", err) | ||
| } | ||
| for i := range clusterPolicies.Items { |
There was a problem hiding this comment.
| for i := range clusterPolicies.Items { | |
| for _, clusterPolicy := range clusterPolicies.Items { |
| default: | ||
| err := fmt.Errorf("no ClusterPolicy or GPUCluster object found in the cluster") | ||
| logger.Error(err, "failed to retrieve hostPaths information. No ClusterPolicy or GPUCluster object found in the cluster") |
There was a problem hiding this comment.
Question -- should we not default to / in this case too? That way, one could deploy NVIDIADriver CRs without having to deploy either a ClusterPolicy or GPUCluster first?
There was a problem hiding this comment.
Yes, I think so. I added it.
9043f10 to
0380d19
Compare
0380d19 to
77b8ebb
Compare
…sterPolicy Signed-off-by: Karthik Vetrivel <kvetrivel@nvidia.com>
77b8ebb to
edfdd7a
Compare
Summary
This PR lets the NVIDIADriver controller reconcile without a ClusterPolicy, so a GPUCluster (the DRA stack) can use operator-managed drivers standalone.
InfoTypeHostRootcatalog entry rather than reading the ClusterPolicy directly, which decouples it from thegpuv1types. When both CRs exist, the ClusterPolicy'shostPaths.rootFStakes precedence. Otherwise the GPUCluster's value is used.Testing
There is unit coverage for the host-root sourcing and the gate transitions, plus two live validations on a single-node Tesla T4 cluster (Kubernetes 1.34, containerd 2.2).
devRoot=/run/nvidia/driver) and published its DeviceClasses and ResourceSlice. A pod with a DRA claim rannvidia-smiagainst the operator-installed driver..status.statetransitions on a cluster converted from a released operator install. A ClusterPolicy that is not delegating with no GPUCluster produceddisabled. A GPUCluster alone producedready. With neither CR, the NVIDIADriver wentnotReadywith the expected message. The ClusterPolicy plus GPUCluster coexistence path is covered by the unit tests.