summaryrefslogtreecommitdiff
path: root/plugin/executor
diff options
context:
space:
mode:
authorJohn Howard <jhoward@microsoft.com>2019-01-08 14:30:52 -0800
committerJohn Howard <jhoward@microsoft.com>2019-03-12 18:41:55 -0700
commit85ad4b16c11425eaeace532bfce9029cfdcabe4b (patch)
treed371a1341804721d3fb18f0b74f616a6c3d09309 /plugin/executor
parent1feaf88aa0c141fa8d8a3232eb1eede63d7872a7 (diff)
downloaddocker-85ad4b16c11425eaeace532bfce9029cfdcabe4b.tar.gz
Windows: Experimental: Allow containerd for runtime
Signed-off-by: John Howard <jhoward@microsoft.com> This is the first step in refactoring moby (dockerd) to use containerd on Windows. Similar to the current model in Linux, this adds the option to enable it for runtime. It does not switch the graphdriver to containerd snapshotters. - Refactors libcontainerd to a series of subpackages so that either a "local" containerd (1) or a "remote" (2) containerd can be loaded as opposed to conditional compile as "local" for Windows and "remote" for Linux. - Updates libcontainerd such that Windows has an option to allow the use of a "remote" containerd. Here, it communicates over a named pipe using GRPC. This is currently guarded behind the experimental flag, an environment variable, and the providing of a pipename to connect to containerd. - Infrastructure pieces such as under pkg/system to have helper functions for determining whether containerd is being used. (1) "local" containerd is what the daemon on Windows has used since inception. It's not really containerd at all - it's simply local invocation of HCS APIs directly in-process from the daemon through the Microsoft/hcsshim library. (2) "remote" containerd is what docker on Linux uses for it's runtime. It means that there is a separate containerd service running, and docker communicates over GRPC to it. To try this out, you will need to start with something like the following: Window 1: containerd --log-level debug Window 2: $env:DOCKER_WINDOWS_CONTAINERD=1 dockerd --experimental -D --containerd \\.\pipe\containerd-containerd You will need the following binary from github.com/containerd/containerd in your path: - containerd.exe You will need the following binaries from github.com/Microsoft/hcsshim in your path: - runhcs.exe - containerd-shim-runhcs-v1.exe For LCOW, it will require and initrd.img and kernel in `C:\Program Files\Linux Containers`. This is no different to the current requirements. However, you may need updated binaries, particularly initrd.img built from Microsoft/opengcs as (at the time of writing), Linuxkit binaries are somewhat out of date. Note that containerd and hcsshim for HCS v2 APIs do not yet support all the required functionality needed for docker. This will come in time - this is a baby (although large) step to migrating Docker on Windows to containerd. Note that the HCS v2 APIs are only called on RS5+ builds. RS1..RS4 will still use HCS v1 APIs as the v2 APIs were not fully developed enough on these builds to be usable. This abstraction is done in HCSShim. (Referring specifically to runtime) Note the LCOW graphdriver still uses HCS v1 APIs regardless. Note also that this does not migrate docker to use containerd snapshotters rather than graphdrivers. This needs to be done in conjunction with Linux also doing the same switch.
Diffstat (limited to 'plugin/executor')
-rw-r--r--plugin/executor/containerd/containerd.go19
-rw-r--r--plugin/executor/containerd/containerd_test.go14
2 files changed, 17 insertions, 16 deletions
diff --git a/plugin/executor/containerd/containerd.go b/plugin/executor/containerd/containerd.go
index a3401dce79..2c6368fec8 100644
--- a/plugin/executor/containerd/containerd.go
+++ b/plugin/executor/containerd/containerd.go
@@ -12,6 +12,7 @@ import (
"github.com/containerd/containerd/runtime/linux/runctypes"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/libcontainerd"
+ libcontainerdtypes "github.com/docker/docker/libcontainerd/types"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -30,11 +31,11 @@ type ExitHandler interface {
// However right now this whole package is tied to github.com/docker/docker/libcontainerd
type Client interface {
Create(ctx context.Context, containerID string, spec *specs.Spec, runtimeOptions interface{}) error
- Restore(ctx context.Context, containerID string, attachStdio libcontainerd.StdioCallback) (alive bool, pid int, err error)
- Status(ctx context.Context, containerID string) (libcontainerd.Status, error)
+ Restore(ctx context.Context, containerID string, attachStdio libcontainerdtypes.StdioCallback) (alive bool, pid int, err error)
+ Status(ctx context.Context, containerID string) (libcontainerdtypes.Status, error)
Delete(ctx context.Context, containerID string) error
DeleteTask(ctx context.Context, containerID string) (uint32, time.Time, error)
- Start(ctx context.Context, containerID, checkpointDir string, withStdin bool, attachStdio libcontainerd.StdioCallback) (pid int, err error)
+ Start(ctx context.Context, containerID, checkpointDir string, withStdin bool, attachStdio libcontainerdtypes.StdioCallback) (pid int, err error)
SignalProcess(ctx context.Context, containerID, processID string, signal int) error
}
@@ -87,7 +88,7 @@ func (e *Executor) Create(id string, spec specs.Spec, stdout, stderr io.WriteClo
logrus.WithError(err2).WithField("id", id).Warn("Received an error while attempting to read plugin status")
}
} else {
- if status != libcontainerd.StatusRunning && status != libcontainerd.StatusUnknown {
+ if status != libcontainerdtypes.StatusRunning && status != libcontainerdtypes.StatusUnknown {
if err2 := e.client.Delete(ctx, id); err2 != nil && !errdefs.IsNotFound(err2) {
logrus.WithError(err2).WithField("plugin", id).Error("Error cleaning up containerd container")
}
@@ -122,19 +123,19 @@ func (e *Executor) Restore(id string, stdout, stderr io.WriteCloser) (bool, erro
// IsRunning returns if the container with the given id is running
func (e *Executor) IsRunning(id string) (bool, error) {
status, err := e.client.Status(context.Background(), id)
- return status == libcontainerd.StatusRunning, err
+ return status == libcontainerdtypes.StatusRunning, err
}
// Signal sends the specified signal to the container
func (e *Executor) Signal(id string, signal int) error {
- return e.client.SignalProcess(context.Background(), id, libcontainerd.InitProcessName, signal)
+ return e.client.SignalProcess(context.Background(), id, libcontainerdtypes.InitProcessName, signal)
}
// ProcessEvent handles events from containerd
// All events are ignored except the exit event, which is sent of to the stored handler
-func (e *Executor) ProcessEvent(id string, et libcontainerd.EventType, ei libcontainerd.EventInfo) error {
+func (e *Executor) ProcessEvent(id string, et libcontainerdtypes.EventType, ei libcontainerdtypes.EventInfo) error {
switch et {
- case libcontainerd.EventExit:
+ case libcontainerdtypes.EventExit:
deleteTaskAndContainer(context.Background(), e.client, id)
return e.exitHandler.HandleExitEvent(ei.ContainerID)
}
@@ -152,7 +153,7 @@ func (c *rio) Wait() {
c.IO.Wait()
}
-func attachStreamsFunc(stdout, stderr io.WriteCloser) libcontainerd.StdioCallback {
+func attachStreamsFunc(stdout, stderr io.WriteCloser) libcontainerdtypes.StdioCallback {
return func(iop *cio.DirectIO) (cio.IO, error) {
if iop.Stdin != nil {
iop.Stdin.Close()
diff --git a/plugin/executor/containerd/containerd_test.go b/plugin/executor/containerd/containerd_test.go
index 3fb45981f3..7443cb9e8e 100644
--- a/plugin/executor/containerd/containerd_test.go
+++ b/plugin/executor/containerd/containerd_test.go
@@ -8,7 +8,7 @@ import (
"testing"
"time"
- "github.com/docker/docker/libcontainerd"
+ libcontainerdtypes "github.com/docker/docker/libcontainerd/types"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"gotest.tools/assert"
@@ -82,22 +82,22 @@ func (c *mockClient) Create(ctx context.Context, id string, _ *specs.Spec, _ int
return nil
}
-func (c *mockClient) Restore(ctx context.Context, id string, attachStdio libcontainerd.StdioCallback) (alive bool, pid int, err error) {
+func (c *mockClient) Restore(ctx context.Context, id string, attachStdio libcontainerdtypes.StdioCallback) (alive bool, pid int, err error) {
return false, 0, nil
}
-func (c *mockClient) Status(ctx context.Context, id string) (libcontainerd.Status, error) {
+func (c *mockClient) Status(ctx context.Context, id string) (libcontainerdtypes.Status, error) {
c.mu.Lock()
defer c.mu.Unlock()
running, ok := c.containers[id]
if !ok {
- return libcontainerd.StatusUnknown, errors.New("not found")
+ return libcontainerdtypes.StatusUnknown, errors.New("not found")
}
if running {
- return libcontainerd.StatusRunning, nil
+ return libcontainerdtypes.StatusRunning, nil
}
- return libcontainerd.StatusStopped, nil
+ return libcontainerdtypes.StatusStopped, nil
}
func (c *mockClient) Delete(ctx context.Context, id string) error {
@@ -111,7 +111,7 @@ func (c *mockClient) DeleteTask(ctx context.Context, id string) (uint32, time.Ti
return 0, time.Time{}, nil
}
-func (c *mockClient) Start(ctx context.Context, id, checkpointDir string, withStdin bool, attachStdio libcontainerd.StdioCallback) (pid int, err error) {
+func (c *mockClient) Start(ctx context.Context, id, checkpointDir string, withStdin bool, attachStdio libcontainerdtypes.StdioCallback) (pid int, err error) {
c.mu.Lock()
defer c.mu.Unlock()