Skip to content
This repository was archived by the owner on Mar 9, 2022. It is now read-only.

Commit cfdf872

Browse files
authored
Merge pull request #891 from tallclair/runtimehandler
Add RuntimeHandler support
2 parents 9cd964f + e7189a2 commit cfdf872

File tree

5 files changed

+128
-12
lines changed

5 files changed

+128
-12
lines changed

cri.go

+16
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) {
7171
}
7272
log.G(ctx).Infof("Start cri plugin with config %+v", c)
7373

74+
if err := validateConfig(&c); err != nil {
75+
return nil, errors.Wrap(err, "invalid config")
76+
}
77+
7478
if err := setGLogLevel(); err != nil {
7579
return nil, errors.Wrap(err, "failed to set glog level")
7680
}
@@ -104,6 +108,18 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) {
104108
return s, nil
105109
}
106110

111+
// validateConfig validates the given configuration.
112+
func validateConfig(c *criconfig.Config) error {
113+
// It is an error to provide both an UntrustedWorkloadRuntime & define an 'untrusted' runtime.
114+
if _, ok := c.ContainerdConfig.Runtimes[criconfig.RuntimeUntrusted]; ok {
115+
if c.ContainerdConfig.UntrustedWorkloadRuntime.Type != "" {
116+
return errors.New("conflicting definitions: configuration includes untrusted_workload_runtime and runtimes['untrusted']")
117+
}
118+
}
119+
120+
return nil
121+
}
122+
107123
// getServicesOpts get service options from plugin context.
108124
func getServicesOpts(ic *plugin.InitContext) ([]containerd.ServicesOpt, error) {
109125
plugins, err := ic.GetByType(plugin.ServicePlugin)

docs/config.md

+18
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ The explanation and default value of each configuration item are as follows:
6161
runtime_root = ""
6262

6363
# "plugins.cri.containerd.untrusted_workload_runtime" is a runtime to run untrusted workloads on it.
64+
65+
# DEPRECATED: use plugins.cri.runtimes instead. If provided, this runtime is mapped to the
66+
# runtime handler named 'untrusted'. It is a configuration error to provide both the (now
67+
# deprecated) UntrustedWorkloadRuntime and a handler in the Runtimes handler map (below) for
68+
# 'untrusted' workloads at the same time. Please provide one or the other.
6469
[plugins.cri.containerd.untrusted_workload_runtime]
6570
# runtime_type is the runtime type to use in containerd e.g. io.containerd.runtime.v1.linux
6671
runtime_type = ""
@@ -71,6 +76,19 @@ The explanation and default value of each configuration item are as follows:
7176
# runtime_root is the directory used by containerd for runtime state.
7277
runtime_root = ""
7378

79+
# plugins.cri.containerd.runtimes is a map from CRI RuntimeHandler strings, which specify types
80+
# of runtime configurations, to the matching configurations. In this example,
81+
# 'runtime_handler_name' is the RuntimeHandler string to match.
82+
[plugins.cri.containerd.runtimes.runtime_handler_name]
83+
# runtime_type is the runtime type to use in containerd e.g. io.containerd.runtime.v1.linux
84+
runtime_type = ""
85+
86+
# runtime_engine is the name of the runtime engine used by containerd.
87+
runtime_engine = ""
88+
89+
# runtime_root is the directory used by containerd for runtime state.
90+
runtime_root = ""
91+
7492
# "plugins.cri.cni" contains config related to cni
7593
[plugins.cri.cni]
7694
# bin_dir is the directory in which the binaries for the plugin is kept.

pkg/config/config.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,18 @@ type Runtime struct {
3333
type ContainerdConfig struct {
3434
// Snapshotter is the snapshotter used by containerd.
3535
Snapshotter string `toml:"snapshotter" json:"snapshotter"`
36-
// DefaultRuntime is the runtime to use in containerd.
36+
// DefaultRuntime is the default runtime to use in containerd.
37+
// This runtime is used when no runtime handler (or the empty string) is provided.
3738
DefaultRuntime Runtime `toml:"default_runtime" json:"defaultRuntime"`
3839
// UntrustedWorkloadRuntime is a runtime to run untrusted workloads on it.
40+
// DEPRECATED: use Runtimes instead. If provided, this runtime is mapped to the runtime handler
41+
// named 'untrusted'. It is a configuration error to provide both the (now deprecated)
42+
// UntrustedWorkloadRuntime and a handler in the Runtimes handler map (below) for 'untrusted'
43+
// workloads at the same time. Please provide one or the other.
3944
UntrustedWorkloadRuntime Runtime `toml:"untrusted_workload_runtime" json:"untrustedWorkloadRuntime"`
45+
// Runtimes is a map from CRI RuntimeHandler strings, which specify types of runtime
46+
// configurations, to the matching configurations.
47+
Runtimes map[string]Runtime `toml:"runtimes" json:"runtimes"`
4048
// NoPivot disables pivot-root (linux only), required when running a container in a RamDisk with runc
4149
NoPivot bool `toml:"no_pivot" json:"noPivot"`
4250
}
@@ -183,3 +191,8 @@ func DefaultConfig() PluginConfig {
183191
},
184192
}
185193
}
194+
195+
const (
196+
// RuntimeUntrusted is the implicit runtime defined for ContainerdConfig.UntrustedWorkloadRuntime
197+
RuntimeUntrusted = "untrusted"
198+
)

pkg/server/sandbox_run.go

+22-10
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
131131
}()
132132
}
133133

134-
ociRuntime, err := c.getSandboxRuntime(config)
134+
ociRuntime, err := c.getSandboxRuntime(config, r.GetRuntimeHandler())
135135
if err != nil {
136136
return nil, errors.Wrap(err, "failed to get sandbox runtime")
137137
}
@@ -601,9 +601,13 @@ func hostAccessingSandbox(config *runtime.PodSandboxConfig) bool {
601601
// getSandboxRuntime returns the runtime configuration for sandbox.
602602
// If the sandbox contains untrusted workload, runtime for untrusted workload will be returned,
603603
// or else default runtime will be returned.
604-
func (c *criService) getSandboxRuntime(config *runtime.PodSandboxConfig) (criconfig.Runtime, error) {
605-
untrusted := false
604+
func (c *criService) getSandboxRuntime(config *runtime.PodSandboxConfig, runtimeHandler string) (criconfig.Runtime, error) {
606605
if untrustedWorkload(config) {
606+
// If the untrusted annotation is provided, runtimeHandler MUST be empty.
607+
if runtimeHandler != "" && runtimeHandler != criconfig.RuntimeUntrusted {
608+
return criconfig.Runtime{}, errors.New("untrusted workload with explicit runtime handler is not allowed")
609+
}
610+
607611
// If the untrusted workload is requesting access to the host/node, this request will fail.
608612
//
609613
// Note: If the workload is marked untrusted but requests privileged, this can be granted, as the
@@ -612,14 +616,22 @@ func (c *criService) getSandboxRuntime(config *runtime.PodSandboxConfig) (cricon
612616
if hostAccessingSandbox(config) {
613617
return criconfig.Runtime{}, errors.New("untrusted workload with host access is not allowed")
614618
}
615-
untrusted = true
616-
}
617619

618-
if untrusted {
619-
if c.config.ContainerdConfig.UntrustedWorkloadRuntime.Type == "" {
620-
return criconfig.Runtime{}, errors.New("no runtime for untrusted workload is configured")
620+
// Handle the deprecated UntrustedWorkloadRuntime.
621+
if c.config.ContainerdConfig.UntrustedWorkloadRuntime.Type != "" {
622+
return c.config.ContainerdConfig.UntrustedWorkloadRuntime, nil
621623
}
622-
return c.config.ContainerdConfig.UntrustedWorkloadRuntime, nil
624+
625+
runtimeHandler = criconfig.RuntimeUntrusted
626+
}
627+
628+
if runtimeHandler == "" {
629+
return c.config.ContainerdConfig.DefaultRuntime, nil
630+
}
631+
632+
handler, ok := c.config.ContainerdConfig.Runtimes[runtimeHandler]
633+
if !ok {
634+
return criconfig.Runtime{}, errors.Errorf("no runtime for %q is configured", runtimeHandler)
623635
}
624-
return c.config.ContainerdConfig.DefaultRuntime, nil
636+
return handler, nil
625637
}

pkg/server/sandbox_run_test.go

+58-1
Original file line numberDiff line numberDiff line change
@@ -533,10 +533,18 @@ func TestGetSandboxRuntime(t *testing.T) {
533533
Root: "",
534534
}
535535

536+
fooRuntime := criconfig.Runtime{
537+
Type: "io.containerd.runtime.v1.linux",
538+
Engine: "foo-bar",
539+
Root: "",
540+
}
541+
536542
for desc, test := range map[string]struct {
537543
sandboxConfig *runtime.PodSandboxConfig
544+
runtimeHandler string
538545
defaultRuntime criconfig.Runtime
539546
untrustedWorkloadRuntime criconfig.Runtime
547+
runtimes map[string]criconfig.Runtime
540548
expectErr bool
541549
expectedRuntime criconfig.Runtime
542550
}{
@@ -595,6 +603,54 @@ func TestGetSandboxRuntime(t *testing.T) {
595603
defaultRuntime: defaultRuntime,
596604
expectErr: true,
597605
},
606+
"should use 'untrusted' runtime for untrusted workload": {
607+
sandboxConfig: &runtime.PodSandboxConfig{
608+
Annotations: map[string]string{
609+
annotations.UntrustedWorkload: "true",
610+
},
611+
},
612+
defaultRuntime: defaultRuntime,
613+
runtimes: map[string]criconfig.Runtime{criconfig.RuntimeUntrusted: untrustedWorkloadRuntime},
614+
expectedRuntime: untrustedWorkloadRuntime,
615+
},
616+
"should use 'untrusted' runtime for untrusted workload & handler": {
617+
sandboxConfig: &runtime.PodSandboxConfig{
618+
Annotations: map[string]string{
619+
annotations.UntrustedWorkload: "true",
620+
},
621+
},
622+
runtimeHandler: "untrusted",
623+
defaultRuntime: defaultRuntime,
624+
runtimes: map[string]criconfig.Runtime{criconfig.RuntimeUntrusted: untrustedWorkloadRuntime},
625+
expectedRuntime: untrustedWorkloadRuntime,
626+
},
627+
"should return an error if untrusted annotation with conflicting handler": {
628+
sandboxConfig: &runtime.PodSandboxConfig{
629+
Annotations: map[string]string{
630+
annotations.UntrustedWorkload: "true",
631+
},
632+
},
633+
runtimeHandler: "foo",
634+
defaultRuntime: defaultRuntime,
635+
untrustedWorkloadRuntime: untrustedWorkloadRuntime,
636+
runtimes: map[string]criconfig.Runtime{"foo": fooRuntime},
637+
expectErr: true,
638+
},
639+
"should use correct runtime for a runtime handler": {
640+
sandboxConfig: &runtime.PodSandboxConfig{},
641+
runtimeHandler: "foo",
642+
defaultRuntime: defaultRuntime,
643+
untrustedWorkloadRuntime: untrustedWorkloadRuntime,
644+
runtimes: map[string]criconfig.Runtime{"foo": fooRuntime},
645+
expectedRuntime: fooRuntime,
646+
},
647+
"should return error if runtime handler is required but not configured": {
648+
sandboxConfig: &runtime.PodSandboxConfig{},
649+
runtimeHandler: "bar",
650+
defaultRuntime: defaultRuntime,
651+
runtimes: map[string]criconfig.Runtime{"foo": fooRuntime},
652+
expectErr: true,
653+
},
598654
} {
599655
t.Run(desc, func(t *testing.T) {
600656
cri := newTestCRIService()
@@ -603,7 +659,8 @@ func TestGetSandboxRuntime(t *testing.T) {
603659
}
604660
cri.config.ContainerdConfig.DefaultRuntime = test.defaultRuntime
605661
cri.config.ContainerdConfig.UntrustedWorkloadRuntime = test.untrustedWorkloadRuntime
606-
r, err := cri.getSandboxRuntime(test.sandboxConfig)
662+
cri.config.ContainerdConfig.Runtimes = test.runtimes
663+
r, err := cri.getSandboxRuntime(test.sandboxConfig, test.runtimeHandler)
607664
assert.Equal(t, test.expectErr, err != nil)
608665
assert.Equal(t, test.expectedRuntime, r)
609666
})

0 commit comments

Comments
 (0)