Skip to content

Commit 352cfb4

Browse files
Enable configuring containerd plugin runtime options
Signed-off-by: Kate Goldenring <[email protected]>
1 parent 4a81b1d commit 352cfb4

File tree

11 files changed

+148
-23
lines changed

11 files changed

+148
-23
lines changed

api/v1alpha1/shim_types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ type ShimSpec struct {
2626
FetchStrategy FetchStrategy `json:"fetchStrategy"`
2727
RuntimeClass RuntimeClassSpec `json:"runtimeClass"`
2828
RolloutStrategy RolloutStrategy `json:"rolloutStrategy"`
29+
// RuntimeOptions is a map of containerd runtime options for the shim plugin.
30+
// See an example of configuring cgroup driver via runtime options: https://github.com/containerd/containerd/blob/main/docs/cri/config.md#cgroup-driver
31+
RuntimeOptions map[string]string `json:"runtimeOptions"`
2932
}
3033

3134
type FetchStrategy struct {

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/node-installer/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ type Config struct {
2020
Runtime struct {
2121
Name string
2222
ConfigPath string
23+
// Options is a map of containerd runtime options for the shim plugin.
24+
// See an example of the cgroup drive option here:
25+
// https://github.com/containerd/containerd/blob/main/docs/cri/config.md#cgroup-driver
26+
Options map[string]string
2327
}
2428
RCM struct {
2529
Path string

cmd/node-installer/detect_test.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ func Test_DetectDistro(t *testing.T) {
4545
struct {
4646
Name string
4747
ConfigPath string
48-
}{"containerd", preset.MicroK8s.ConfigPath},
48+
Options map[string]string
49+
}{"containerd", preset.MicroK8s.ConfigPath, nil},
4950
struct {
5051
Path string
5152
AssetPath string
@@ -64,7 +65,8 @@ func Test_DetectDistro(t *testing.T) {
6465
struct {
6566
Name string
6667
ConfigPath string
67-
}{"containerd", "/etc/containerd/not_found.toml"},
68+
Options map[string]string
69+
}{"containerd", "/etc/containerd/not_found.toml", nil},
6870
struct {
6971
Path string
7072
AssetPath string
@@ -83,7 +85,8 @@ func Test_DetectDistro(t *testing.T) {
8385
struct {
8486
Name string
8587
ConfigPath string
86-
}{"containerd", ""},
88+
Options map[string]string
89+
}{"containerd", "", nil},
8790
struct {
8891
Path string
8992
AssetPath string
@@ -102,7 +105,8 @@ func Test_DetectDistro(t *testing.T) {
102105
struct {
103106
Name string
104107
ConfigPath string
105-
}{"containerd", ""},
108+
Options map[string]string
109+
}{"containerd", "", nil},
106110
struct {
107111
Path string
108112
AssetPath string
@@ -121,7 +125,8 @@ func Test_DetectDistro(t *testing.T) {
121125
struct {
122126
Name string
123127
ConfigPath string
124-
}{"containerd", ""},
128+
Options map[string]string
129+
}{"containerd", "", nil},
125130
struct {
126131
Path string
127132
AssetPath string
@@ -140,7 +145,8 @@ func Test_DetectDistro(t *testing.T) {
140145
struct {
141146
Name string
142147
ConfigPath string
143-
}{"containerd", ""},
148+
Options map[string]string
149+
}{"containerd", "", nil},
144150
struct {
145151
Path string
146152
AssetPath string
@@ -159,7 +165,8 @@ func Test_DetectDistro(t *testing.T) {
159165
struct {
160166
Name string
161167
ConfigPath string
162-
}{"containerd", ""},
168+
Options map[string]string
169+
}{"containerd", "", nil},
163170
struct {
164171
Path string
165172
AssetPath string
@@ -178,7 +185,8 @@ func Test_DetectDistro(t *testing.T) {
178185
struct {
179186
Name string
180187
ConfigPath string
181-
}{"containerd", ""},
188+
Options map[string]string
189+
}{"containerd", "", nil},
182190
struct {
183191
Path string
184192
AssetPath string

cmd/node-installer/install.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package main
1818

1919
import (
20+
"encoding/json"
2021
"fmt"
2122
"io/fs"
2223
"log/slog"
@@ -50,6 +51,16 @@ var installCmd = &cobra.Command{
5051
os.Exit(1)
5152
}
5253

54+
optionsJson := os.Getenv("RUNTIME_OPTIONS")
55+
config.Runtime.Options = make(map[string]string)
56+
if optionsJson != "" {
57+
err := json.Unmarshal([]byte(optionsJson), &config.Runtime.Options)
58+
if err != nil {
59+
slog.Error("Error unmarshaling runtime options JSON", "error", err)
60+
return
61+
}
62+
}
63+
5364
if err := RunInstall(config, rootFs, hostFs, distro.Restarter); err != nil {
5465
slog.Error("failed to install", "error", err)
5566
os.Exit(1)
@@ -82,7 +93,7 @@ func RunInstall(config Config, rootFs, hostFs afero.Fs, restarter containerd.Res
8293
config.RCM.AssetPath = path.Dir(config.RCM.AssetPath)
8394
}
8495

85-
containerdConfig := containerd.NewConfig(hostFs, config.Runtime.ConfigPath, restarter)
96+
containerdConfig := containerd.NewConfig(hostFs, config.Runtime.ConfigPath, restarter, config.Runtime.Options)
8697
shimConfig := shim.NewConfig(rootFs, hostFs, config.RCM.AssetPath, config.RCM.Path)
8798

8899
anythingChanged := false

cmd/node-installer/install_test.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ func Test_RunInstall(t *testing.T) {
4949
struct {
5050
Name string
5151
ConfigPath string
52-
}{"containerd", "/etc/containerd/config.toml"},
52+
Options map[string]string
53+
}{"containerd", "/etc/containerd/config.toml", nil},
5354
struct {
5455
Path string
5556
AssetPath string
@@ -68,7 +69,8 @@ func Test_RunInstall(t *testing.T) {
6869
struct {
6970
Name string
7071
ConfigPath string
71-
}{"containerd", "/etc/containerd/config.toml"},
72+
Options map[string]string
73+
}{"containerd", "/etc/containerd/config.toml", nil},
7274
struct {
7375
Path string
7476
AssetPath string
@@ -80,6 +82,27 @@ func Test_RunInstall(t *testing.T) {
8082
},
8183
false,
8284
},
85+
{
86+
// TODO figure out how to test that the runtime options are set in the config
87+
"new shim with runtime options",
88+
args{
89+
main.Config{
90+
struct {
91+
Name string
92+
ConfigPath string
93+
Options map[string]string
94+
}{"containerd", "/etc/containerd/config.toml", map[string]string{"SystemdCgroup": "true"}},
95+
struct {
96+
Path string
97+
AssetPath string
98+
}{"/opt/rcm", "/assets"},
99+
struct{ RootPath string }{"/containerd/missing-containerd-shim-config"},
100+
},
101+
tests.FixtureFs("../../testdata/node-installer"),
102+
tests.FixtureFs("../../testdata/node-installer/containerd/missing-containerd-shim-config"),
103+
},
104+
false,
105+
},
83106
}
84107
for _, tt := range tests {
85108
t.Run(tt.name, func(t *testing.T) {

cmd/node-installer/uninstall.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package main
1818

1919
import (
20+
"encoding/json"
2021
"fmt"
2122
"log/slog"
2223
"os"
@@ -45,6 +46,16 @@ var uninstallCmd = &cobra.Command{
4546

4647
config.Runtime.ConfigPath = distro.ConfigPath
4748

49+
optionsJson := os.Getenv("RUNTIME_OPTIONS")
50+
config.Runtime.Options = make(map[string]string)
51+
if optionsJson != "" {
52+
err := json.Unmarshal([]byte(optionsJson), &config.Runtime.Options)
53+
if err != nil {
54+
slog.Error("Error unmarshaling runtime options JSON", "error", err)
55+
return
56+
}
57+
}
58+
4859
if err := RunUninstall(config, rootFs, hostFs, distro.Restarter); err != nil {
4960
slog.Error("failed to uninstall", "error", err)
5061
os.Exit(1)
@@ -61,7 +72,7 @@ func RunUninstall(config Config, rootFs, hostFs afero.Fs, restarter containerd.R
6172
shimName := config.Runtime.Name
6273
runtimeName := path.Join(config.RCM.Path, "bin", shimName)
6374

64-
containerdConfig := containerd.NewConfig(hostFs, config.Runtime.ConfigPath, restarter)
75+
containerdConfig := containerd.NewConfig(hostFs, config.Runtime.ConfigPath, restarter, config.Runtime.Options)
6576
shimConfig := shim.NewConfig(rootFs, hostFs, config.RCM.AssetPath, config.RCM.Path)
6677

6778
binPath, err := shimConfig.Uninstall(shimName)

config/crd/bases/runtime.spinkube.dev_shims.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,18 @@ spec:
9595
- handler
9696
- name
9797
type: object
98+
runtimeOptions:
99+
additionalProperties:
100+
type: string
101+
description: |-
102+
RuntimeOptions is a map of containerd runtime options for the shim plugin.
103+
Read more here: https://github.com/containerd/containerd/blob/main/docs/cri/config.md#cgroup-driver
104+
type: object
98105
required:
99106
- fetchStrategy
100107
- rolloutStrategy
101108
- runtimeClass
109+
- runtimeOptions
102110
type: object
103111
status:
104112
description: ShimStatus defines the observed state of Shim

config/samples/test_shim_spin.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ spec:
1717
anonHttp:
1818
location: "https://github.com/spinframework/containerd-shim-spin/releases/download/v0.19.0/containerd-shim-spin-v2-linux-aarch64.tar.gz"
1919

20+
runtimeOptions:
21+
SystemdCgroup: "true"
22+
2023
runtimeClass:
2124
# Note: this name is used by the Spin Operator project as its default:
2225
# https://github.com/spinframework/spin-operator/blob/main/config/samples/spin-shim-executor.yaml

internal/containerd/configure.go

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,18 @@ type Restarter interface {
3232
}
3333

3434
type Config struct {
35-
hostFs afero.Fs
36-
configPath string
37-
restarter Restarter
35+
hostFs afero.Fs
36+
configPath string
37+
restarter Restarter
38+
runtimeOptions map[string]string
3839
}
3940

40-
func NewConfig(hostFs afero.Fs, configPath string, restarter Restarter) *Config {
41+
func NewConfig(hostFs afero.Fs, configPath string, restarter Restarter, runtimeOptions map[string]string) *Config {
4142
return &Config{
42-
hostFs: hostFs,
43-
configPath: configPath,
44-
restarter: restarter,
43+
hostFs: hostFs,
44+
configPath: configPath,
45+
restarter: restarter,
46+
runtimeOptions: runtimeOptions,
4547
}
4648
}
4749

@@ -61,7 +63,7 @@ func (c *Config) AddRuntime(shimPath string) error {
6163
return nil
6264
}
6365

64-
cfg := generateConfig(shimPath, runtimeName, data)
66+
cfg := generateConfig(shimPath, runtimeName, c.runtimeOptions, data)
6567

6668
// Open file in append mode
6769
file, err := c.hostFs.OpenFile(c.configPath, os.O_APPEND|os.O_WRONLY, 0o644) //nolint:mnd // file permissions
@@ -95,7 +97,7 @@ func (c *Config) RemoveRuntime(shimPath string) (changed bool, err error) {
9597
return false, nil
9698
}
9799

98-
cfg := generateConfig(shimPath, runtimeName, data)
100+
cfg := generateConfig(shimPath, runtimeName, c.runtimeOptions, data)
99101

100102
// Convert the file data to a string and replace the target string with an empty string.
101103
modifiedData := strings.ReplaceAll(string(data), cfg, "")
@@ -113,17 +115,27 @@ func (c *Config) RestartRuntime() error {
113115
return c.restarter.Restart()
114116
}
115117

116-
func generateConfig(shimPath string, runtimeName string, configData []byte) string {
118+
func generateConfig(shimPath string, runtimeName string, runtimeOptions map[string]string, configData []byte) string {
117119
// Config domain for containerd 1.0 (config version 2)
118120
domain := "io.containerd.grpc.v1.cri"
119121
if strings.Contains(string(configData), "version = 3") {
120122
// Config domain for containerd 2.0 (config version 3)
121123
domain = "io.containerd.cri.v1.runtime"
122124
}
123125

124-
return fmt.Sprintf(`
126+
runtimeConfiguration := fmt.Sprintf(`
125127
# RCM runtime config for %s
126128
[plugins."%s".containerd.runtimes.%s]
127129
runtime_type = "%s"
128130
`, runtimeName, domain, runtimeName, shimPath)
131+
// Add runtime options if any are provided
132+
if len(runtimeOptions) > 0 {
133+
options := fmt.Sprintf(`[plugins."%s".containerd.runtimes."%s".options]`, domain, runtimeName)
134+
for k, v := range runtimeOptions {
135+
options += fmt.Sprintf(`
136+
%s = "%s"\n`, k, v)
137+
}
138+
runtimeConfiguration += "\n" + options
139+
}
140+
return runtimeConfiguration
129141
}

0 commit comments

Comments
 (0)