Skip to content

Commit b3bde09

Browse files
committed
Add configurable --sysfs-root for NUMA and PCI discovery
Enable mock-GPU test environments to supply synthetic PCI sysfs trees for device-plugin NUMA topology and GFD vGPU PCI scanning without changing production defaults.
1 parent db1ea94 commit b3bde09

14 files changed

Lines changed: 210 additions & 34 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ deploying the plugin via `helm`.
221221
| `--mig-strategy` | `$MIG_STRATEGY` | `"none"` |
222222
| `--fail-on-init-error` | `$FAIL_ON_INIT_ERROR` | `true` |
223223
| `--nvidia-driver-root` | `$NVIDIA_DRIVER_ROOT` | `"/"` |
224+
| `--sysfs-root` | `$SYSFS_ROOT` | `"/sys"` |
224225
| `--pass-device-specs` | `$PASS_DEVICE_SPECS` | `false` |
225226
| `--device-list-strategy` | `$DEVICE_LIST_STRATEGY` | `"envvar"` |
226227
| `--device-id-strategy` | `$DEVICE_ID_STRATEGY` | `"uuid"` |
@@ -234,6 +235,7 @@ flags:
234235
migStrategy: "none"
235236
failOnInitError: true
236237
nvidiaDriverRoot: "/"
238+
sysfsRoot: "/sys"
237239
plugin:
238240
passDeviceSpecs: false
239241
deviceListStrategy: "envvar"

api/config/v1/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ func NewConfig(c *cli.Context, flags []cli.Flag) (*Config, error) {
6969
config.Flags.NvidiaDevRoot = config.Flags.NvidiaDriverRoot
7070
}
7171

72+
if config.Flags.SysfsRoot == nil || *config.Flags.SysfsRoot == "" {
73+
sysfsRoot := DefaultSysfsRoot
74+
config.Flags.SysfsRoot = &sysfsRoot
75+
}
76+
7277
// Preserve the historical MPS behavior unless the config explicitly relaxes it.
7378
if config.Sharing.MPS != nil && config.Sharing.MPS.FailRequestsGreaterThanOne == nil {
7479
t := true

api/config/v1/consts.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,5 @@ const (
5353
DefaultCDIAnnotationPrefix = cdiapi.AnnotationPrefix
5454
DefaultNvidiaCTKPath = "/usr/bin/nvidia-ctk"
5555
DefaultContainerDriverRoot = "/driver-root"
56+
DefaultSysfsRoot = "/sys"
5657
)

api/config/v1/flags.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ type CommandLineFlags struct {
6262
MpsRoot *string `json:"mpsRoot,omitempty" yaml:"mpsRoot,omitempty"`
6363
NvidiaDriverRoot *string `json:"nvidiaDriverRoot,omitempty" yaml:"nvidiaDriverRoot,omitempty"`
6464
NvidiaDevRoot *string `json:"nvidiaDevRoot,omitempty" yaml:"nvidiaDevRoot,omitempty"`
65+
SysfsRoot *string `json:"sysfsRoot,omitempty" yaml:"sysfsRoot,omitempty"`
6566
GDRCopyEnabled *bool `json:"gdrcopyEnabled" yaml:"gdrcopyEnabled"`
6667
GDSEnabled *bool `json:"gdsEnabled" yaml:"gdsEnabled"`
6768
MOFEDEnabled *bool `json:"mofedEnabled" yaml:"mofedEnabled"`
@@ -129,6 +130,8 @@ func (f *Flags) UpdateFromCLIFlags(c *cli.Context, flags []cli.Flag) {
129130
updateFromCLIFlag(&f.NvidiaDriverRoot, c, n)
130131
case "dev-root", "nvidia-dev-root":
131132
updateFromCLIFlag(&f.NvidiaDevRoot, c, n)
133+
case "sysfs-root":
134+
updateFromCLIFlag(&f.SysfsRoot, c, n)
132135
case "gdrcopy-enabled":
133136
updateFromCLIFlag(&f.GDRCopyEnabled, c, n)
134137
case "gds-enabled":

cmd/gpu-feature-discovery/main.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ func main() {
109109
Usage: "the strategy to use to discover devices: 'auto', 'nvml', 'tegra' or 'vfio'",
110110
EnvVars: []string{"DEVICE_DISCOVERY_STRATEGY"},
111111
},
112+
&cli.StringFlag{
113+
Name: "sysfs-root",
114+
Value: spec.DefaultSysfsRoot,
115+
Usage: "the root path for sysfs; used for PCI device discovery",
116+
EnvVars: []string{"SYSFS_ROOT"},
117+
},
112118
&cli.StringFlag{
113119
Name: "driver-root-ctr-path",
114120
Aliases: []string{"container-driver-root"},
@@ -191,7 +197,7 @@ func start(c *cli.Context, cfg *Config) error {
191197
return fmt.Errorf("failed to create resource manager: %w", err)
192198

193199
}
194-
vgpul := vgpu.NewVGPULib(vgpu.NewNvidiaPCILib())
200+
vgpul := vgpu.NewVGPULib(vgpu.NewNvidiaPCILib(*config.Flags.SysfsRoot))
195201

196202
var clientSets flags.ClientSets
197203
if config.Flags.UseNodeFeatureAPI != nil && *config.Flags.UseNodeFeatureAPI {

cmd/nvidia-device-plugin/main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ func main() {
8484
Usage: "the root path for the NVIDIA device nodes on the host (typical values are '/' or '/run/nvidia/driver')",
8585
EnvVars: []string{"NVIDIA_DEV_ROOT"},
8686
},
87+
&cli.StringFlag{
88+
Name: "sysfs-root",
89+
Value: spec.DefaultSysfsRoot,
90+
Usage: "the root path for sysfs; used for PCI device NUMA detection",
91+
EnvVars: []string{"SYSFS_ROOT"},
92+
},
8793
&cli.BoolFlag{
8894
Name: "pass-device-specs",
8995
Value: false,

deployments/helm/nvidia-device-plugin/templates/daemonset-device-plugin.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ spec:
166166
- name: NVIDIA_DEV_ROOT
167167
value: "{{ .Values.nvidiaDevRoot }}"
168168
{{- end }}
169+
{{- if typeIs "string" .Values.sysfsRoot }}
170+
- name: SYSFS_ROOT
171+
value: {{ .Values.sysfsRoot }}
172+
{{- end }}
169173
{{- if typeIs "string" .Values.cdi.nvidiaHookPath }}
170174
- name: NVIDIA_CDI_HOOK_PATH
171175
value: {{ .Values.cdi.nvidiaHookPath }}
@@ -213,6 +217,11 @@ spec:
213217
- name: driver-root
214218
mountPath: /driver-root
215219
readOnly: true
220+
{{- end }}
221+
{{- if and (typeIs "string" .Values.sysfsRoot) (typeIs "string" .Values.sysfsHostPath) }}
222+
- name: sysfs-root
223+
mountPath: {{ .Values.sysfsRoot }}
224+
readOnly: true
216225
{{- end }}
217226
# The MPS /dev/shm is needed to allow for MPS daemon health-checking.
218227
- name: mps-shm
@@ -249,6 +258,12 @@ spec:
249258
path: {{ .Values.nvidiaDriverRoot }}
250259
type: Directory
251260
{{- end }}
261+
{{- if and (typeIs "string" .Values.sysfsRoot) (typeIs "string" .Values.sysfsHostPath) }}
262+
- name: sysfs-root
263+
hostPath:
264+
path: {{ .Values.sysfsHostPath }}
265+
type: Directory
266+
{{- end }}
252267
- name: cdi-root
253268
hostPath:
254269
path: /var/run/cdi

deployments/helm/nvidia-device-plugin/templates/daemonset-gfd.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,22 @@ spec:
178178
- name: DEVICE_DISCOVERY_STRATEGY
179179
value: {{ .Values.deviceDiscoveryStrategy }}
180180
{{- end }}
181+
{{- if typeIs "string" .Values.sysfsRoot }}
182+
- name: SYSFS_ROOT
183+
value: {{ .Values.sysfsRoot }}
184+
{{- end }}
181185
securityContext:
182186
{{- include "gpu-feature-discovery.securityContext" . | nindent 10 }}
183187
volumeMounts:
184188
- name: output-dir
185189
mountPath: "/etc/kubernetes/node-feature-discovery/features.d"
186190
- name: host-sys
187191
mountPath: "/sys"
192+
{{- if and (typeIs "string" .Values.sysfsRoot) (typeIs "string" .Values.sysfsHostPath) }}
193+
- name: sysfs-root
194+
mountPath: {{ .Values.sysfsRoot }}
195+
readOnly: true
196+
{{- end }}
188197
{{- if $options.hasConfigMap }}
189198
- name: available-configs
190199
mountPath: /available-configs
@@ -208,6 +217,12 @@ spec:
208217
hostPath:
209218
path: {{ clean ( join "/" ( list "/" .Values.nvidiaDriverRoot ) ) | quote }}
210219
type: Directory
220+
{{- if and (typeIs "string" .Values.sysfsRoot) (typeIs "string" .Values.sysfsHostPath) }}
221+
- name: sysfs-root
222+
hostPath:
223+
path: {{ .Values.sysfsHostPath }}
224+
type: Directory
225+
{{- end }}
211226
{{- if $options.hasConfigMap }}
212227
- name: available-configs
213228
configMap:

deployments/helm/nvidia-device-plugin/values.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ failOnInitError: null
3333
deviceListStrategy: null
3434
deviceIDStrategy: null
3535
nvidiaDriverRoot: null
36+
sysfsRoot: null
37+
sysfsHostPath: null
3638
gdrcopyEnabled: null
3739
gdsEnabled: null
3840
mofedEnabled: null

internal/rm/device_map.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,20 @@ type deviceMapBuilder struct {
3535
replicatedResources *spec.ReplicatedResources
3636

3737
newGPUDevice func(i int, gpu nvml.Device) (string, deviceInfo)
38+
newMigDevice func(i int, j int, mig nvml.Device) (string, nvmlMigDevice)
3839
}
3940

4041
// DeviceMap stores a set of devices per resource name.
4142
type DeviceMap map[spec.ResourceName]Devices
4243

4344
// NewDeviceMap creates a device map for the specified NVML library and config.
4445
func NewDeviceMap(devicelib device.Interface, config *spec.Config, platform info.Platform) (DeviceMap, error) {
45-
newGPUDevice := newNvmlGPUDevice
46+
sysfsRoot := spec.DefaultSysfsRoot
47+
if config.Flags.SysfsRoot != nil && *config.Flags.SysfsRoot != "" {
48+
sysfsRoot = *config.Flags.SysfsRoot
49+
}
50+
51+
newGPUDevice := newNvmlGPUDevice(sysfsRoot)
4652
if platform == info.PlatformWSL {
4753
newGPUDevice = newWslAllGPUsDevice
4854
}
@@ -53,6 +59,7 @@ func NewDeviceMap(devicelib device.Interface, config *spec.Config, platform info
5359
resources: &config.Resources,
5460
replicatedResources: config.Sharing.ReplicatedResources(),
5561
newGPUDevice: newGPUDevice,
62+
newMigDevice: newMigDevice(sysfsRoot),
5663
}
5764

5865
return b.build()
@@ -143,7 +150,7 @@ func (b *deviceMapBuilder) buildMigDeviceMap() (DeviceMap, error) {
143150
}
144151
for _, resource := range b.resources.MIGs {
145152
if resource.Pattern.Matches(migProfile.String()) {
146-
index, info := newMigDevice(i, j, mig)
153+
index, info := b.newMigDevice(i, j, mig)
147154
return devices.setEntry(resource.Name, index, info)
148155
}
149156
}

0 commit comments

Comments
 (0)