From d6277ddc6d7f1dfb5c16bb88034ef0403ae39047 Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Fri, 26 Feb 2021 23:23:55 +0000 Subject: [PATCH] [WIP] Allow switching Windows runtimes. This adds support for 2 runtimes on Windows, one that uses the built-in HCSv1 integration and another which uses containerd with the runhcs shim. Signed-off-by: Brian Goff --- cmd/dockerd/daemon_windows.go | 1 - daemon/config/config.go | 2 ++ daemon/config/config_windows.go | 4 ++- daemon/daemon.go | 22 ++++++----------- daemon/daemon_unix.go | 13 ++++++++++ daemon/daemon_windows.go | 44 +++++++++++++++++++++++++++++++++ 6 files changed, 69 insertions(+), 17 deletions(-) diff --git a/cmd/dockerd/daemon_windows.go b/cmd/dockerd/daemon_windows.go index ef06b0eb6da10..200babbc6c10d 100644 --- a/cmd/dockerd/daemon_windows.go +++ b/cmd/dockerd/daemon_windows.go @@ -9,7 +9,6 @@ import ( "github.com/docker/docker/daemon/config" "github.com/docker/docker/libcontainerd/supervisor" - "github.com/docker/docker/pkg/system" "github.com/sirupsen/logrus" "golang.org/x/sys/windows" ) diff --git a/daemon/config/config.go b/daemon/config/config.go index ef5320ccec379..2b4e8a2a77a2e 100644 --- a/daemon/config/config.go +++ b/daemon/config/config.go @@ -273,6 +273,8 @@ type CommonConfig struct { ContainerdNamespace string `json:"containerd-namespace,omitempty"` ContainerdPluginNamespace string `json:"containerd-plugin-namespace,omitempty"` + + DefaultRuntime string `json:"default-runtime,omitempty"` } // IsValueSet returns true if a configuration value diff --git a/daemon/config/config_windows.go b/daemon/config/config_windows.go index eb9e71cbc4d93..da9b1b92fe22e 100644 --- a/daemon/config/config_windows.go +++ b/daemon/config/config_windows.go @@ -28,7 +28,9 @@ func (conf *Config) GetRuntime(name string) *types.Runtime { // GetDefaultRuntimeName returns the current default runtime func (conf *Config) GetDefaultRuntimeName() string { - return StockRuntimeName + conf.Lock() + defer conf.Unlock() + return conf.DefaultRuntime } // GetAllRuntimes returns a copy of the runtimes map diff --git a/daemon/daemon.go b/daemon/daemon.go index 4e75d5ee3ca87..9fcacb35c6600 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -42,7 +42,6 @@ import ( "github.com/docker/docker/errdefs" "github.com/docker/docker/image" "github.com/docker/docker/layer" - "github.com/docker/docker/libcontainerd" libcontainerdtypes "github.com/docker/docker/libcontainerd/types" "github.com/docker/docker/libnetwork" "github.com/docker/docker/libnetwork/cluster" @@ -922,23 +921,17 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)), grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize)), } - if config.ContainerdAddr != "" { - d.containerdCli, err = containerd.New(config.ContainerdAddr, containerd.WithDefaultNamespace(config.ContainerdNamespace), containerd.WithDialOpts(gopts), containerd.WithTimeout(60*time.Second)) - if err != nil { - return nil, errors.Wrapf(err, "failed to dial %q", config.ContainerdAddr) - } + d.containerdCli, err = containerd.New(config.ContainerdAddr, containerd.WithDefaultNamespace(config.ContainerdNamespace), containerd.WithDialOpts(gopts), containerd.WithTimeout(60*time.Second)) + if err != nil { + return nil, errors.Wrapf(err, "failed to dial %q", config.ContainerdAddr) } createPluginExec := func(m *plugin.Manager) (plugin.Executor, error) { var pluginCli *containerd.Client - // Windows is not currently using containerd, keep the - // client as nil - if config.ContainerdAddr != "" { - pluginCli, err = containerd.New(config.ContainerdAddr, containerd.WithDefaultNamespace(config.ContainerdPluginNamespace), containerd.WithDialOpts(gopts), containerd.WithTimeout(60*time.Second)) - if err != nil { - return nil, errors.Wrapf(err, "failed to dial %q", config.ContainerdAddr) - } + pluginCli, err = containerd.New(config.ContainerdAddr, containerd.WithDefaultNamespace(config.ContainerdPluginNamespace), containerd.WithDialOpts(gopts), containerd.WithTimeout(60*time.Second)) + if err != nil { + return nil, errors.Wrapf(err, "failed to dial %q", config.ContainerdAddr) } var rt types.Runtime @@ -1113,8 +1106,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S go d.execCommandGC() - d.containerd, err = libcontainerd.NewClient(ctx, d.containerdCli, filepath.Join(config.ExecRoot, "containerd"), config.ContainerdNamespace, d) - if err != nil { + if err := d.initLibcontainerd(ctx); err != nil { return nil, err } diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index 526b6d6ecae8f..d96fa805db97d 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -29,6 +29,7 @@ import ( "github.com/docker/docker/daemon/config" "github.com/docker/docker/daemon/initlayer" "github.com/docker/docker/errdefs" + "github.com/docker/docker/libcontainerd/remote" "github.com/docker/docker/libnetwork" nwconfig "github.com/docker/docker/libnetwork/config" "github.com/docker/docker/libnetwork/drivers/bridge" @@ -1736,3 +1737,15 @@ func (daemon *Daemon) RawSysInfo() *sysinfo.SysInfo { func recursiveUnmount(target string) error { return mount.RecursiveUnmount(target) } + +func (daemon *Daemon) initLibcontainerd(ctx context.Context) error { + var err error + daemon.containerd, err = remote.NewClient( + ctx, + daemon.containerdCli, + filepath.Join(daemon.configStore.ExecRoot, "containerd"), + daemon.configStore.ContainerdNamespace, + daemon, + ) + return err +} diff --git a/daemon/daemon_windows.go b/daemon/daemon_windows.go index f333b737aa47d..cea0ebf59ee12 100644 --- a/daemon/daemon_windows.go +++ b/daemon/daemon_windows.go @@ -14,6 +14,8 @@ import ( containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" "github.com/docker/docker/daemon/config" + "github.com/docker/docker/libcontainerd/local" + "github.com/docker/docker/libcontainerd/remote" "github.com/docker/docker/libnetwork" nwconfig "github.com/docker/docker/libnetwork/config" "github.com/docker/docker/libnetwork/datastore" @@ -40,6 +42,9 @@ const ( windowsMaxCPUShares = 10000 windowsMinCPUPercent = 1 windowsMaxCPUPercent = 100 + + windowsV1RuntimeName = "com.docker.hcsshim.v1" + windowsV2RuntimeName = "io.containerd.runhcs.v1" ) // Windows containers are much larger than Linux containers and each of them @@ -649,3 +654,42 @@ func setupResolvConf(config *config.Config) { func (daemon *Daemon) RawSysInfo() *sysinfo.SysInfo { return sysinfo.New() } + +func (daemon *Daemon) initLibcontainerd(ctx context.Context) error { + var err error + + rt := daemon.configStore.GetDefaultRuntimeName() + if rt == "" { + if daemon.configStore.ContainerdAddr == "" { + rt = windowsV1RuntimeName + } else { + rt = windowsV2RuntimeName + } + } + + switch rt { + case windowsV1RuntimeName: + daemon.containerd, err = local.NewClient( + ctx, + daemon.containerdCli, + filepath.Join(daemon.configStore.ExecRoot, "containerd"), + daemon.configStore.ContainerdNamespace, + daemon, + ) + case windowsV2RuntimeName: + if daemon.configStore.ContainerdAddr == "" { + return fmt.Errorf("cannot use the specified runtime %q without containerd", rt) + } + daemon.containerd, err = remote.NewClient( + ctx, + daemon.containerdCli, + filepath.Join(daemon.configStore.ExecRoot, "containerd"), + daemon.configStore.ContainerdNamespace, + daemon, + ) + default: + return fmt.Errorf("unknown windows runtime %s", rt) + } + + return err +}