Skip to content

daemon: support alternative runtimes MVP#43800

Merged
cpuguy83 merged 1 commit intomoby:masterfrom
corhere:implicit-runtime-config
Jul 29, 2022
Merged

daemon: support alternative runtimes MVP#43800
cpuguy83 merged 1 commit intomoby:masterfrom
corhere:implicit-runtime-config

Conversation

@corhere
Copy link
Copy Markdown
Contributor

@corhere corhere commented Jul 13, 2022

Contrary to popular belief, the OCI Runtime specification does not specify the command-line API for runtimes. Looking at containerd's architecture from the lens of the OCI Runtime spec, the shim is the OCI Runtime and runC is "just" an implementation detail of the io.containerd.runc.v2 runtime. When one configures a non-default runtime in Docker, what they're really doing is instructing Docker to create containers using the io.containerd.runc.v2 runtime with a configuration option telling the runtime that the runC binary is at some non-default path. Consequently, only OCI runtimes which are compatible with the io.containerd.runc.v2 shim, such as crun, can be used in this manner. Other OCI runtimes, including kata-containers v2, come with their own containerd shim and are not compatible with io.containerd.runc.v2. As Docker has not historically provided a way to select a non-default runtime which requires its own shim, runtimes such as kata-containers v2 could not be used with Docker.

Allow other ContainerD shims to be used with Docker; no daemon configuration required. If the daemon is instructed to create a container with a runtime name which does not match any of the configured or stock runtimes, it passes the name along to ContainerD verbatim. A user can start a container with the kata-containers runtime, for example, simply by calling

docker run --runtime io.containerd.kata.v2

Runtime names which ContainerD would interpret as a path to an arbitrary binary are disallowed. While handy for development and testing it is not strictly necessary and would allow anyone with Engine API access to trivially execute any binary on the host as root, so we have decided it would be safest for our users if it was not allowed.

It is not yet possible to set an alternative ContainerD shim as the default runtime; it can only be configured per-container. Doing so properly, with validation and configuration reload handling, is quite the nontrivial undertaking with the current state of the daemon configuration logic. That will be addressed in a subsequent PR.

- What I did

- How I did it

- How to verify it
Unit and integration tests cover the new functionality.

To manually verify:

  • Install an alternative runtime with a shim that implements Containerd Runtime v2 on $PATH
  • docker run --rm --runtime io.containerd.my-runtime.v1 alpine ls

The io.containerd.runc.v2 shim is aliased to io.containerd.runc-alias.v2 in the development container image as a convenience for manual testing.

- Description for the changelog

  • Alternative OCI runtimes compatible with the Containerd Runtime v2 API which are installed on the system can now be used to start containers. These runtimes are not listed in docker info and cannot be set as the default runtime at this time.

- A picture of a cute animal (not mandatory but encouraged)

@corhere corhere requested review from cpuguy83 and tianon July 13, 2022 00:22
@cpuguy83
Copy link
Copy Markdown
Member

How about an integration test?
Could possibly just copy the runc shim to a different name (and path, should test both cases).

@thaJeztah
Copy link
Copy Markdown
Member

Let me post my comment from the other PR here for consideration #43736 (comment)

From a UX perspective, the --runtime option was meant to be the more "convenient" option, where the user can use docker info to see which runtimes are available/configured on the daemon, and use those as option (--runtime=runc, --runtime=kata), and the daemon-configuratioin can contain additional config options (IIRC, this could even be multiple versions of runc, e.g.).

No daemon.json configuration would be required to use alternative runtimes if the daemon was to interpret --runtime values

I know that access to the API already is equivalent to root, but if the --runtime value passed can be (as is being discussed here) either a name (io.containerd.runc.v2) or a path to a binary, that could potentially open up some "interesting" things (--runtime=/bin/rm, --runtime=/some/arbitrary/script.sh)

@corhere
Copy link
Copy Markdown
Contributor Author

corhere commented Jul 13, 2022

From a UX perspective, the --runtime option was meant to be the more "convenient" option, where the user can use docker info to see which runtimes are available/configured on the daemon, and use those as option (--runtime=runc, --runtime=kata), and the daemon-configuratioin can contain additional config options (IIRC, this could even be multiple versions of runc, e.g.).

And from a perspective of the dockerd<->containerd interface, the --runtime option looks a lot like picking a "configuration profile" which specifies some of the container level shim configuration the daemon should pass to the io.containerd.runc.v2 ContainerD Runtime on container creation. Extending this "configuration profile" concept to support defining a profile in daemon.json which specifies an arbitrary ContainerD Runtime with corresponding container level shim configuration is not very feasible with the current state of the ecosystem, at least not with a UX that mortals could use as the container level shim configuration is passed to containerd inside a protobuf.Any message. So I am making no attempt to support such extended profiles in this PR, though I have been mindful to not add further complications to building it out in the future. Without support for container level shim configuration, a configuration profile with an arbitrary ContainerD Runtime is little more than an alias.

One of my motivations for wanting the daemon to support using ContainerD Runtimes without needing to first explicitly inform the daemon of their existence is to remove a significant hurdle to packaging, installing and using alternative runtimes with Docker. Distributors could package runtimes purely as ContainerD Runtimes with no Docker awareness, and users would still be able to use the runtimes with Docker immediately after installation. And the daemon could dynamically discover which runtimes are available so they could be listed in docker info alongside the explicit runtime profiles. The ContainerD Runtime v2 spec defines a mapping from runtime name to shim binary name. As this mapping is (more or less) invertible, installed ContainerD Runtimes could be discovered by searching $PATH for executables matching ^containerd-shim-([^-]+)-(v\d+)$ and mapping the file name to its runtime name io.containerd.\1.\2. (Ideally, containerd should be responsible for performing the search as its $PATH environment variable could differ from dockerd's.)

I know that access to the API already is equivalent to root, but if the --runtime value passed can be (as is being discussed here) either a name (io.containerd.runc.v2) or a path to a binary, that could potentially open up some "interesting" things (--runtime=/bin/rm, --runtime=/some/arbitrary/script.sh)

As they say, with great power comes great responsibility. Containerd only accepts absolute paths, not relative, so it should hopefully be a red flag if someone instructs you to specify a runtime of /some/arbitrary/script.sh. If there is demand for it, we could add daemon config options for the more paranoid admins such as restricting the permissible --runtime values with an allowlist or disallowing runtimes-as-paths.

@corhere corhere changed the title daemon: use other runtimes without configuration daemon: support alternative runtimes MVP Jul 13, 2022
@corhere corhere force-pushed the implicit-runtime-config branch from 4fdadd1 to a5f43f0 Compare July 19, 2022 20:07
@corhere corhere force-pushed the implicit-runtime-config branch 2 times, most recently from 193b197 to 4cf6771 Compare July 20, 2022 21:59
Comment on lines -337 to +341
"-E", "XDG_RUNTIME_DIR="+d.rootlessXDGRuntimeDir,
"-E", "HOME="+d.rootlessUser.HomeDir,
"-E", "PATH="+os.Getenv("PATH"),
"--preserve-env",
"XDG_RUNTIME_DIR="+d.rootlessXDGRuntimeDir,
"HOME="+d.rootlessUser.HomeDir,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for reviewers: the sudo -E flag takes no arguments. sudo -E HOME=/home/rootlessuser is parsed as two separate flags: preserve all environment variables, and set the HOME variable. The extra -E flags were redundant. The only functional change I have made is to stop overriding the PATH variable.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the reason for removing PATH from the list? Depending on the environment, PATH may be a protected env-var, and therefore reset to its default (which can lead to fun situations; see moby/term#21 (comment))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hoping to pass through PATH from the os/exec.Cmd.Args so the path override in my integration test (daemon.WithEnvVars) would Just Work in rootless mode. Guess I'll need to find a different way to accomplish that.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that would still be possible 🤔 as in; when it would run sudo -E PATH=/foo:/bar PATH=/bar/baz, the second PATH would override the former (default "inherited") path, correct?

// it would resolve to a binary named "containerd-shim---".
// https://github.com/containerd/containerd/blob/11ded166c15f92450958078cd13c6d87131ec563/runtime/v2/manager.go#L297-L317
// https://github.com/containerd/containerd/blob/11ded166c15f92450958078cd13c6d87131ec563/runtime/v2/shim/util.go#L83-L93
return !filepath.IsAbs(name) && !strings.ContainsRune(name, '/') && strings.ContainsRune(name, '.')
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This path would always be "local", for containerd, right? (i.e., no need to take cross-platform into account) otherwise we would need something like docker/cli#1990

I think ideally;

  • we should consume some function from containerd that performs the validation, so that we don't diverge
  • perhaps create a tracking issue to contribute such a function in containerd (i.e. based on this code
  • wondering if the containerd validation is (per the above) too relaxed, i.e., does it want to allow con....tai-----nerd-🤣🐳-shim...--- as name? (something like RestrictedNameChars, possibly tweaked to not allow consecutive separators may be good?

Copy link
Copy Markdown
Contributor Author

@corhere corhere Jul 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This path would always be "local", for containerd, right? (i.e., no need to take cross-platform into account) otherwise we would need something like docker/cli#1990

Yes. The barriers to having dockerd operate on a containerd instance over the network include requiring a network filesystem which transparently allows FIFOs in exported shares to be read from and written to (standard container streams) and all the assumptions in dockerd that any observations of system state, such as /proc/mounts, are reflective of the observations from containerd.

I think ideally;

  • we should consume some function from containerd that performs the validation, so that we don't diverge
  • perhaps create a tracking issue to contribute such a function in containerd (i.e. based on this code

This validation function diverges from containerd's validation by design so a function which reports whether containerd would consider the name valid would be of rather limited use to us. I had initially implemented this check in terms of shim.BinaryName but it seemed so trivial a function that all the extra transitive packages vendored in seemed so wasteful. And yet I still managed to mischaracterize the function Fair point about divergence: the validation it performs has recently been made more restrictive than the check in the containerd version we currently vendor. I'll switch back to importing it so we pick up any validation improvements whenever we bump containerd.

  • wondering if the containerd validation is (per the above) too relaxed, i.e., does it want to allow con....tai-----nerd-🤣🐳-shim...--- as name? (something like RestrictedNameChars, possibly tweaked to not allow consecutive separators may be good?

I don't see the need as I don't see a way to exploit the validation. It can't be used to smuggle a path or a path traversal in as any names containing / bytes are blocked. It makes sense to apply limitations such as RestrictedNameChars when assigning a name to an entity, but this is a case of referencing an entity by its preassigned name. I say let users play stupid games with runtime names if they want; they'll be told that the runtime is not installed when they try to start the container, same as would happen when specifying the name of any other not-installed runtime.

}

// isValidC8dRuntimeName tests whether name
// is a well-formed ContainerD runtime name,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note that the canonical name for containerd is all lowercase (containerd)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦 I must've mixed it up with runC

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's an "official" statement, but afaik, it's all lowercase (but I know some people use the capital D) - as we're using lowercase everywhere, best to stick with it 😅

Comment on lines -337 to +341
"-E", "XDG_RUNTIME_DIR="+d.rootlessXDGRuntimeDir,
"-E", "HOME="+d.rootlessUser.HomeDir,
"-E", "PATH="+os.Getenv("PATH"),
"--preserve-env",
"XDG_RUNTIME_DIR="+d.rootlessXDGRuntimeDir,
"HOME="+d.rootlessUser.HomeDir,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that would still be possible 🤔 as in; when it would run sudo -E PATH=/foo:/bar PATH=/bar/baz, the second PATH would override the former (default "inherited") path, correct?

@corhere corhere force-pushed the implicit-runtime-config branch 2 times, most recently from 4797242 to 54de464 Compare July 21, 2022 21:00
@corhere corhere requested a review from cpuguy83 July 21, 2022 22:18
Copy link
Copy Markdown
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall looks good; left some thoughts / ramblings

Comment on lines +120 to +123
if !isPermissibleC8dRuntimeName(name) {
return nil, errdefs.InvalidParameter(errors.Errorf("unknown or invalid runtime name: %s", name))
}
return &types.Runtime{Shim: &types.ShimConfig{Binary: name}}, nil
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slightly on the fence if it would be more idiomatic to change isPermissibleC8dRuntimeName to return the error; something like;

if err := validateRuntimeName(name); err != nil  {
	return nil, err
}

Of course at that point it's debatable if it should also handle converting it to a types.Runtime, so something like;

return getContainerdRuntime(name)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is also laying some groundwork for the follow-up PR to enable a containerd runtime to be set as the default runtime. That function is not returning an error directly because the appropriate error to return is context-dependent. A different error message is more appropriate when validating the configured default runtime.

Of course at that point it's debatable if it should also handle converting it to a types.Runtime, so something like;

return getContainerdRuntime(name)

That hypothetical getContainerdRuntime function would be a near drop-in replacement for (*Daemon).getRuntime, having the same signature and everything. And it would almost seem to work, too. But it would be subtly broken to call it anywhere other than (*Daemon).getRuntime as it would disregard any configured runtimes. I would prefer to have only one function which maps a name to a runtime so there is no possibility to choose wrong.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it would be subtly broken to call it anywhere other than (*Daemon).getRuntime as it would disregard any configured runtimes.

Overall I'm not too concerned (for a non-exported function, which more commonly come with some guidance). Was mostly considering it to be nice if it would return a nicely formatted error with the right type ("invalid name"), and generally err can be used as a "boolean" for validation.

Not a blocker though.

@@ -116,7 +117,10 @@ func (daemon *Daemon) rewriteRuntimePath(name, p string, args []string) (string,
func (daemon *Daemon) getRuntime(name string) (*types.Runtime, error) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also a Windows equivalent of this function; do we need to implement this logic for Windows as well (when using containerd as runtime?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, at least not until an alternative to containerd-shim-runhcs-v1 exists. And I'm not sure one ever will exist, since runhcs covers all the use cases (Windows & Linux containers with Process & VM isolation) and I suspect implementing alternative runtimes would be tricky without access to the Windows source code.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking here was that if Windows containerd has the same semantics, we could expose the --runtime on Windows, and have containerd deal with it (once an alternative comes to exist).

return &types.Runtime{Shim: &types.ShimConfig{Binary: name}}, nil
}

if len(rt.Args) > 0 {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small observation that all code below is only applied to runtimes configured through daemon.json; for clarity we could consider reversing the if rt == nil { to if rt != nil { with those options below in it.

That said, as I see it correctly;

  • setting a runtime through daemon.json without specifying Shim, would result in defaultV2ShimConfig() to be applied. Whereas passing the same through --runtime would not. Which means that I cannot "just" specify io.containerd.FOOBAR.v2 in daemon.json (as that would apply the defaultOptions, assuming it's a variant of runc shim?
  • Args can be passed through daemon.json (but obviously not through --runtime

Not sure what the best migration path is to allow "just" specifying a shim through daemon.json, and/or if some of those options should be marked deprecated and/or produce an error. (input/ideas welcome)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small observation that all code below is only applied to runtimes configured through daemon.json; for clarity we could consider reversing the if rt == nil { to if rt != nil { with those options below in it.

rt == nil is an error condition so its flow is indented.

That said, as I see it correctly;

  • setting a runtime through daemon.json without specifying Shim, would result in defaultV2ShimConfig() to be applied. Whereas passing the same through --runtime dockerd --add-runtime would not. Which means that I cannot "just" specify io.containerd.FOOBAR.v2 in daemon.json (as that would apply the defaultOptions, assuming it's a variant of runc shim CLI binary with the file name io.containerd.FOOBAR.v2)
  • Args can be passed through daemon.json (but obviously not through --runtime --add-runtime

FTFY. runtimes.<name>.Shim cannot be specified in daemon.json as that struct field is tagged json:"-".

Not sure what the best migration path is to allow "just" specifying a shim through daemon.json, and/or if some of those options should be marked deprecated and/or produce an error. (input/ideas welcome)

That's the neat part; you don't! "Just" specify the shim name as the runtime when creating the container. As noted in the PR description, I will be following up with a PR to allow default-runtime to be set to a shim name. No migration path is needed as daemon.json has exactly the same semantics as it always had. People can continue to define "runtimes" which use runC-compatible binaries with the io.containerd.runc.v2 containerd runtime, same as they always have done. I see no need to deprecate that functionality, either.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the neat part; you don't! "Just" specify the shim name as the runtime when creating the container. As noted in the PR description, I will be following up with a PR to allow default-runtime to be set to a shim name.

Ah, right, yes; I was thinking "with this PR, it's possible both through daemon.json and through --runtime to specify a shim.

But currently, daemon.json will continue to be "only runtimes that use the runc shim" (but alternative binary)

@@ -707,8 +707,8 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
hostConfig.Runtime = daemon.configStore.GetDefaultRuntimeName()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not introduced in this PR, but this looks somewhat odd in a verifyXX function; if I see it correctly, this may (due to hostConfig being passed by reference) be mutating the config, both on create and start (and possible other locations that call verifyContainerSettings()).

Possibly the intent was to bake the config into the container's config, but if it's called in multiple locations, it may actually have become mutable 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mutating the config. I cringed when I first noticed it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same! Yes, we should look into that; it's probably ok to perform it when creating a container (set default if not set to "bake" it into the config), but definitely feels fishy for start, and definitely should be outside of a "verify" function.

It may have been for migrating existing container configs after updating docker engine, but if that was the reason, we should have it part as an explicit step during "restore" (where I think we previously did such migrations).

Contrary to popular belief, the OCI Runtime specification does not
specify the command-line API for runtimes. Looking at containerd's
architecture from the lens of the OCI Runtime spec, the _shim_ is the
OCI Runtime and runC is "just" an implementation detail of the
io.containerd.runc.v2 runtime. When one configures a non-default runtime
in Docker, what they're really doing is instructing Docker to create
containers using the io.containerd.runc.v2 runtime with a configuration
option telling the runtime that the runC binary is at some non-default
path. Consequently, only OCI runtimes which are compatible with the
io.containerd.runc.v2 shim, such as crun, can be used in this manner.
Other OCI runtimes, including kata-containers v2, come with their own
containerd shim and are not compatible with io.containerd.runc.v2.
As Docker has not historically provided a way to select a non-default
runtime which requires its own shim, runtimes such as kata-containers v2
could not be used with Docker.

Allow other containerd shims to be used with Docker; no daemon
configuration required. If the daemon is instructed to create a
container with a runtime name which does not match any of the configured
or stock runtimes, it passes the name along to containerd verbatim. A
user can start a container with the kata-containers runtime, for
example, simply by calling

    docker run --runtime io.containerd.kata.v2

Runtime names which containerd would interpret as a path to an arbitrary
binary are disallowed. While handy for development and testing it is not
strictly necessary and would allow anyone with Engine API access to
trivially execute any binary on the host as root, so we have decided it
would be safest for our users if it was not allowed.

It is not yet possible to set an alternative containerd shim as the
default runtime; it can only be configured per-container.

Signed-off-by: Cory Snider <csnider@mirantis.com>
@corhere corhere force-pushed the implicit-runtime-config branch from 54de464 to 547da0d Compare July 27, 2022 18:23
@cpuguy83
Copy link
Copy Markdown
Member

What's up with the vendoring on this? I would not expect any changes to vendor/.

@thaJeztah
Copy link
Copy Markdown
Member

What's up with the vendoring on this? I would not expect any changes to vendor/.

Looks like it's because of the shim.Binaryname() being used, and runc options in one of the tests

@corhere
Copy link
Copy Markdown
Contributor Author

corhere commented Jul 27, 2022

shim.BinaryName() is the only reason for the vendoring explosion. The package with the runc options used in that test is also imported by existing code.

@cpuguy83
Copy link
Copy Markdown
Member

Ah, I totally missed that shim import.

// BinaryName returns the shim binary name from the runtime name,
// empty string returns means runtime name is invalid
func BinaryName(runtime string) string {
	// runtime name should format like $prefix.name.version
	parts := strings.Split(runtime, ".")
	if len(parts) < 2 {
		return ""
	}

	return fmt.Sprintf(shimBinaryFormat, parts[len(parts)-2], parts[len(parts)-1])
}

Seems like we can copy this one.

@corhere
Copy link
Copy Markdown
Contributor Author

corhere commented Jul 27, 2022

Seems like we can copy this one.

That's what I did in the first revision! @thaJeztah wasn't happy about it: #43800 (comment)

@thaJeztah
Copy link
Copy Markdown
Member

That's what I did in the first revision! @thaJeztah wasn't happy about it: #43800 (comment)

Yes, I guess there's pros/cons (no risk of diverging, but more code vendored).

  • Is that a concern for you? Or "OK"? @cpuguy83
  • Will we be using more bits from the shim package going forward (with the containerd integration)?
  • If not (and if there's a risk that the shim package also will cause more indirect dependencies; we could consider looking if we can refactor some bits in containerd and to move such utilities to a smaller package (could be part of "config" validation in general).

Happy to hear your thoughts!

Copy link
Copy Markdown
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

return &types.Runtime{Shim: &types.ShimConfig{Binary: name}}, nil
}

if len(rt.Args) > 0 {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the neat part; you don't! "Just" specify the shim name as the runtime when creating the container. As noted in the PR description, I will be following up with a PR to allow default-runtime to be set to a shim name.

Ah, right, yes; I was thinking "with this PR, it's possible both through daemon.json and through --runtime to specify a shim.

But currently, daemon.json will continue to be "only runtimes that use the runc shim" (but alternative binary)

@@ -116,7 +117,10 @@ func (daemon *Daemon) rewriteRuntimePath(name, p string, args []string) (string,
func (daemon *Daemon) getRuntime(name string) (*types.Runtime, error) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking here was that if Windows containerd has the same semantics, we could expose the --runtime on Windows, and have containerd deal with it (once an alternative comes to exist).

@@ -707,8 +707,8 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
hostConfig.Runtime = daemon.configStore.GetDefaultRuntimeName()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same! Yes, we should look into that; it's probably ok to perform it when creating a container (set default if not set to "bake" it into the config), but definitely feels fishy for start, and definitely should be outside of a "verify" function.

It may have been for migrating existing container configs after updating docker engine, but if that was the reason, we should have it part as an explicit step during "restore" (where I think we previously did such migrations).

Comment on lines +120 to +123
if !isPermissibleC8dRuntimeName(name) {
return nil, errdefs.InvalidParameter(errors.Errorf("unknown or invalid runtime name: %s", name))
}
return &types.Runtime{Shim: &types.ShimConfig{Binary: name}}, nil
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it would be subtly broken to call it anywhere other than (*Daemon).getRuntime as it would disregard any configured runtimes.

Overall I'm not too concerned (for a non-exported function, which more commonly come with some guidance). Was mostly considering it to be nice if it would return a nicely formatted error with the right type ("invalid name"), and generally err can be used as a "boolean" for validation.

Not a blocker though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants