Skip to content

Commit c8c059c

Browse files
Implement Drop-In Lifecycle Support for Containerd and Crio Configuration
Signed-off-by: Carlos Eduardo Arango Gutierrez <[email protected]>
1 parent 77e8f4b commit c8c059c

File tree

12 files changed

+695
-231
lines changed

12 files changed

+695
-231
lines changed

cmd/nvidia-ctk-installer/container/runtime/containerd/config_v2_test.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"testing"
2222

2323
testlog "github.com/sirupsen/logrus/hooks/test"
24+
"github.com/stretchr/testify/assert"
2425
"github.com/stretchr/testify/require"
2526

2627
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container"
@@ -85,8 +86,9 @@ func TestUpdateV2ConfigDefaultRuntime(t *testing.T) {
8586

8687
cfg := v2.(*containerd.Config)
8788

88-
defaultRuntimeName := cfg.GetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "default_runtime_name"})
89-
require.EqualValues(t, tc.expectedDefaultRuntimeName, defaultRuntimeName)
89+
// For v2 configs, default runtime is set in NVConfig (drop-in configuration)
90+
defaultRuntimeName := cfg.NVConfig.GetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "default_runtime_name"})
91+
assert.Equal(t, tc.expectedDefaultRuntimeName, defaultRuntimeName)
9092
})
9193
}
9294
}
@@ -358,10 +360,22 @@ func TestUpdateV2ConfigWithRuncPresent(t *testing.T) {
358360
err = o.UpdateConfig(v2)
359361
require.NoError(t, err)
360362

361-
expected, err := toml.TreeFromMap(tc.expectedConfig)
362-
require.NoError(t, err)
363+
cfg := v2.(*containerd.Config)
363364

364-
require.Equal(t, expected.String(), v2.String())
365+
// Verify nvidia runtimes are in NVConfig
366+
for _, runtimeName := range []string{tc.runtimeName, "nvidia-cdi", "nvidia-legacy"} {
367+
if tc.runtimeName == "NAME" && runtimeName == "nvidia" {
368+
continue // Skip "nvidia" when runtime name is "NAME"
369+
}
370+
runtimePath := cfg.NVConfig.GetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes", runtimeName, "options", "BinaryName"})
371+
assert.NotNil(t, runtimePath)
372+
}
373+
374+
// Verify main Tree remains unchanged (still contains original runc runtime)
375+
originalConfig := runcConfigMapV2("/runc-binary")
376+
expectedMain, err := toml.TreeFromMap(originalConfig)
377+
require.NoError(t, err)
378+
assert.Equal(t, expectedMain.String(), cfg.Tree.String(), "Main config should remain unchanged")
365379
})
366380
}
367381
}
@@ -397,18 +411,23 @@ func TestUpdateV2ConfigEnableCDI(t *testing.T) {
397411
cfg, err := toml.LoadMap(map[string]interface{}{})
398412
require.NoError(t, err)
399413

414+
nvConfig, err := toml.LoadMap(map[string]interface{}{})
415+
require.NoError(t, err)
416+
400417
v2 := &containerd.Config{
401418
Logger: logger,
402419
Tree: cfg,
420+
NVConfig: nvConfig,
403421
RuntimeType: runtimeType,
404422
CRIRuntimePluginName: "io.containerd.grpc.v1.cri",
405423
}
406424

407425
err = o.UpdateConfig(v2)
408426
require.NoError(t, err)
409427

410-
enableCDIValue := cfg.GetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "enable_cdi"})
411-
require.EqualValues(t, tc.expectedEnableCDIValue, enableCDIValue)
428+
// For v2 configs, enable_cdi is set in NVConfig (drop-in configuration)
429+
enableCDIValue := v2.NVConfig.GetPath([]string{"plugins", "io.containerd.grpc.v1.cri", "enable_cdi"})
430+
assert.Equal(t, tc.expectedEnableCDIValue, enableCDIValue)
412431
})
413432
}
414433
}

cmd/nvidia-ctk-installer/container/runtime/containerd/containerd.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ type Options struct {
4747
ContainerRuntimeModesCDIAnnotationPrefixes []string
4848

4949
runtimeConfigOverrideJSON string
50+
51+
dropInDir string
5052
}
5153

5254
func Flags(opts *Options) []cli.Flag {
@@ -79,6 +81,12 @@ func Flags(opts *Options) []cli.Flag {
7981
Value: "{}",
8082
Sources: cli.EnvVars("RUNTIME_CONFIG_OVERRIDE", "CONTAINERD_RUNTIME_CONFIG_OVERRIDE"),
8183
},
84+
&cli.StringFlag{
85+
Name: "containerd-drop-in-dir",
86+
Usage: "the directory to store the drop-in configuration for the containerd runtime",
87+
Value: "/etc/containerd/conf.d",
88+
Destination: &opts.dropInDir,
89+
},
8290
}
8391

8492
return flags
@@ -180,5 +188,6 @@ func getRuntimeConfig(o *container.Options, co *Options) (engine.Interface, erro
180188
containerd.WithRuntimeType(co.runtimeType),
181189
containerd.WithUseLegacyConfig(co.useLegacyConfig),
182190
containerd.WithContainerAnnotations(co.containerAnnotationsFromCDIPrefixes()...),
191+
containerd.WithDropInDir(co.dropInDir),
183192
)
184193
}

cmd/nvidia-ctk-installer/main_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,18 @@ swarm-resource = ""
437437
"--toolkit-source-root=" + filepath.Join(artifactRoot, "deb"),
438438
}
439439

440-
err := app.Run(context.Background(), append(testArgs, tc.args...))
440+
// Add containerd drop-in directory for containerd runtime tests to avoid permission issues
441+
finalArgs := make([]string, 0, len(testArgs)+len(tc.args)+1)
442+
finalArgs = append(finalArgs, testArgs...)
443+
finalArgs = append(finalArgs, tc.args...)
444+
for _, arg := range tc.args {
445+
if arg == "--runtime=containerd" {
446+
finalArgs = append(finalArgs, "--containerd-drop-in-dir="+filepath.Join(testRoot, "containerd", "conf.d"))
447+
break
448+
}
449+
}
450+
451+
err := app.Run(context.Background(), finalArgs)
441452

442453
require.NoError(t, err)
443454

cmd/nvidia-ctk/runtime/configure/configure.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ const (
4646
defaultCrioConfigFilePath = "/etc/crio/crio.conf"
4747
defaultDockerConfigFilePath = "/etc/docker/daemon.json"
4848

49+
defaultContainerdDropInDir = "/etc/containerd/conf.d"
50+
defaultCrioDropInDir = "/etc/crio/conf.d"
51+
defaultDropInFileName = "99.nvidia.toml"
52+
4953
defaultConfigSource = configSourceFile
5054
configSourceCommand = "command"
5155
configSourceFile = "file"
@@ -66,13 +70,14 @@ func NewCommand(logger logger.Interface) *cli.Command {
6670
// config defines the options that can be set for the CLI through config files,
6771
// environment variables, or command line config
6872
type config struct {
69-
dryRun bool
70-
runtime string
71-
configFilePath string
72-
executablePath string
73-
configSource string
74-
mode string
75-
hookFilePath string
73+
dryRun bool
74+
runtime string
75+
configFilePath string
76+
executablePath string
77+
configSource string
78+
mode string
79+
hookFilePath string
80+
dropInConfigPath string
7681

7782
nvidiaRuntime struct {
7883
name string
@@ -170,6 +175,11 @@ func (m command) build() *cli.Command {
170175
Usage: "Enable CDI in the configured runtime",
171176
Destination: &config.cdi.enabled,
172177
},
178+
&cli.StringFlag{
179+
Name: "drop-in-config-path",
180+
Usage: "the path to the drop-in configuration file for the containerd runtime",
181+
Destination: &config.dropInConfigPath,
182+
},
173183
},
174184
}
175185

@@ -262,24 +272,37 @@ func (m command) configureConfigFile(config *config) error {
262272
}
263273

264274
var cfg engine.Interface
275+
var outputPath string
265276
switch config.runtime {
266277
case "containerd":
278+
if config.dropInConfigPath == "" {
279+
config.dropInConfigPath = filepath.Join(defaultContainerdDropInDir, defaultDropInFileName)
280+
}
267281
cfg, err = containerd.New(
268282
containerd.WithLogger(m.logger),
269283
containerd.WithPath(config.configFilePath),
270284
containerd.WithConfigSource(configSource),
285+
containerd.WithDropInDir(config.dropInConfigPath),
271286
)
287+
outputPath = config.dropInConfigPath
272288
case "crio":
289+
if config.dropInConfigPath == "" {
290+
// CRI-O uses .conf extension for drop-in files
291+
config.dropInConfigPath = filepath.Join(defaultCrioDropInDir, "99-nvidia.conf")
292+
}
273293
cfg, err = crio.New(
274294
crio.WithLogger(m.logger),
275295
crio.WithPath(config.configFilePath),
276296
crio.WithConfigSource(configSource),
297+
crio.WithDropInDir(config.dropInConfigPath),
277298
)
299+
outputPath = config.dropInConfigPath
278300
case "docker":
279301
cfg, err = docker.New(
280302
docker.WithLogger(m.logger),
281303
docker.WithPath(config.configFilePath),
282304
)
305+
outputPath = config.getOutputConfigPath()
283306
default:
284307
err = fmt.Errorf("unrecognized runtime '%v'", config.runtime)
285308
}
@@ -300,7 +323,6 @@ func (m command) configureConfigFile(config *config) error {
300323
cfg.EnableCDI()
301324
}
302325

303-
outputPath := config.getOutputConfigPath()
304326
n, err := cfg.Save(outputPath)
305327
if err != nil {
306328
return fmt.Errorf("unable to flush config: %v", err)

0 commit comments

Comments
 (0)