Swicth to 1.0.0-alpha2 containerd api.
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
This commit is contained in:
parent
6017d84040
commit
73748840da
@ -61,6 +61,7 @@ if [ ! -x "$(command -v containerd)" ]; then
|
|||||||
fi
|
fi
|
||||||
sudo pkill containerd
|
sudo pkill containerd
|
||||||
sudo containerd -l debug &> ${REPORT_DIR}/containerd.log &
|
sudo containerd -l debug &> ${REPORT_DIR}/containerd.log &
|
||||||
|
sleep 1 # sleep 1 seconds for containerd to be ready.
|
||||||
|
|
||||||
# Start cri-containerd
|
# Start cri-containerd
|
||||||
cd ${ROOT}
|
cd ${ROOT}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
RUNC_VERSION=639454475cb9c8b861cc599f8bcd5c8c790ae402
|
RUNC_VERSION=e775f0fba3ea329b8b766451c892c41a3d49594d
|
||||||
CNI_VERSION=v0.4.0
|
CNI_VERSION=v0.4.0
|
||||||
CONTAINERD_VERSION=8ed1e24ae925b5c6d8195858ee89dddb0507d65f
|
CONTAINERD_VERSION=2386062ce152d6f158d22be5991fe11c7cf67535
|
||||||
CRITEST_VERSION=74bbd4e142f752f13c648d9dde23defed3e472a2
|
CRITEST_VERSION=74bbd4e142f752f13c648d9dde23defed3e472a2
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/api/services/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
prototypes "github.com/gogo/protobuf/types"
|
prototypes "github.com/gogo/protobuf/types"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
@ -135,24 +135,22 @@ func (c *criContainerdService) CreateContainer(ctx context.Context, r *runtime.C
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Create containerd container.
|
// Create containerd container.
|
||||||
if _, err = c.containerService.Create(ctx, &containers.CreateContainerRequest{
|
if _, err = c.containerService.Create(ctx, containers.Container{
|
||||||
Container: containers.Container{
|
ID: id,
|
||||||
ID: id,
|
// TODO(random-liu): Checkpoint metadata into container labels.
|
||||||
// TODO(random-liu): Checkpoint metadata into container labels.
|
Image: image.ID,
|
||||||
Image: image.ID,
|
Runtime: containers.RuntimeInfo{Name: defaultRuntime},
|
||||||
Runtime: defaultRuntime,
|
Spec: &prototypes.Any{
|
||||||
Spec: &prototypes.Any{
|
TypeUrl: runtimespec.Version,
|
||||||
TypeUrl: runtimespec.Version,
|
Value: rawSpec,
|
||||||
Value: rawSpec,
|
|
||||||
},
|
|
||||||
RootFS: id,
|
|
||||||
},
|
},
|
||||||
|
RootFS: id,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, fmt.Errorf("failed to create containerd container: %v", err)
|
return nil, fmt.Errorf("failed to create containerd container: %v", err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
if _, err := c.containerService.Delete(ctx, &containers.DeleteContainerRequest{ID: id}); err != nil {
|
if err := c.containerService.Delete(ctx, id); err != nil {
|
||||||
glog.Errorf("Failed to delete containerd container %q: %v", id, err)
|
glog.Errorf("Failed to delete containerd container %q: %v", id, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -419,8 +417,8 @@ func setOCILinuxResource(g *generate.Generator, resources *runtime.LinuxContaine
|
|||||||
g.SetLinuxResourcesCPUPeriod(uint64(resources.GetCpuPeriod()))
|
g.SetLinuxResourcesCPUPeriod(uint64(resources.GetCpuPeriod()))
|
||||||
g.SetLinuxResourcesCPUQuota(resources.GetCpuQuota())
|
g.SetLinuxResourcesCPUQuota(resources.GetCpuQuota())
|
||||||
g.SetLinuxResourcesCPUShares(uint64(resources.GetCpuShares()))
|
g.SetLinuxResourcesCPUShares(uint64(resources.GetCpuShares()))
|
||||||
g.SetLinuxResourcesMemoryLimit(uint64(resources.GetMemoryLimitInBytes()))
|
g.SetLinuxResourcesMemoryLimit(resources.GetMemoryLimitInBytes())
|
||||||
g.SetLinuxResourcesOOMScoreAdj(int(resources.GetOomScoreAdj()))
|
g.SetProcessOOMScoreAdj(int(resources.GetOomScoreAdj()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// setOCICapabilities adds/drops process capabilities.
|
// setOCICapabilities adds/drops process capabilities.
|
||||||
|
@ -128,7 +128,7 @@ func getCreateContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandbox
|
|||||||
assert.EqualValues(t, *spec.Linux.Resources.CPU.Quota, 200)
|
assert.EqualValues(t, *spec.Linux.Resources.CPU.Quota, 200)
|
||||||
assert.EqualValues(t, *spec.Linux.Resources.CPU.Shares, 300)
|
assert.EqualValues(t, *spec.Linux.Resources.CPU.Shares, 300)
|
||||||
assert.EqualValues(t, *spec.Linux.Resources.Memory.Limit, 400)
|
assert.EqualValues(t, *spec.Linux.Resources.Memory.Limit, 400)
|
||||||
assert.EqualValues(t, *spec.Linux.Resources.OOMScoreAdj, 500)
|
assert.EqualValues(t, *spec.Process.OOMScoreAdj, 500)
|
||||||
|
|
||||||
t.Logf("Check capabilities")
|
t.Logf("Check capabilities")
|
||||||
assert.Contains(t, spec.Process.Capabilities.Bounding, "CAP_SYS_ADMIN")
|
assert.Contains(t, spec.Process.Capabilities.Bounding, "CAP_SYS_ADMIN")
|
||||||
|
@ -23,9 +23,9 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/containerd/containerd/api/services/containers"
|
"github.com/containerd/containerd/api/services/events/v1"
|
||||||
"github.com/containerd/containerd/api/services/execution"
|
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||||
"github.com/containerd/containerd/api/types/task"
|
"github.com/containerd/containerd/typeurl"
|
||||||
prototypes "github.com/gogo/protobuf/types"
|
prototypes "github.com/gogo/protobuf/types"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
@ -58,15 +58,15 @@ func (c *criContainerdService) ExecSync(ctx context.Context, r *runtime.ExecSync
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get exec process spec.
|
// Get exec process spec.
|
||||||
cntrResp, err := c.containerService.Get(ctx, &containers.GetContainerRequest{ID: id})
|
container, err := c.containerService.Get(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get container %q from containerd: %v", id, err)
|
return nil, fmt.Errorf("failed to get container %q from containerd: %v", id, err)
|
||||||
}
|
}
|
||||||
var spec runtimespec.Spec
|
var spec runtimespec.Spec
|
||||||
if err := json.Unmarshal(cntrResp.Container.Spec.Value, &spec); err != nil {
|
if err := json.Unmarshal(container.Spec.Value, &spec); err != nil {
|
||||||
return nil, fmt.Errorf("failed to unmarshal container spec: %v", err)
|
return nil, fmt.Errorf("failed to unmarshal container spec: %v", err)
|
||||||
}
|
}
|
||||||
pspec := &spec.Process
|
pspec := spec.Process
|
||||||
pspec.Args = r.GetCmd()
|
pspec.Args = r.GetCmd()
|
||||||
rawSpec, err := json.Marshal(pspec)
|
rawSpec, err := json.Marshal(pspec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -98,15 +98,16 @@ func (c *criContainerdService) ExecSync(ctx context.Context, r *runtime.ExecSync
|
|||||||
go io.Copy(stderrBuf, stderrPipe) // nolint: errcheck
|
go io.Copy(stderrBuf, stderrPipe) // nolint: errcheck
|
||||||
|
|
||||||
// Get containerd event client first, so that we won't miss any events.
|
// Get containerd event client first, so that we won't miss any events.
|
||||||
// TODO(random-liu): Handle this in event handler. Create an events client for
|
// TODO(random-liu): Add filter to only subscribe events of the exec process.
|
||||||
// each exec introduces unnecessary overhead.
|
|
||||||
cancellable, cancel := context.WithCancel(ctx)
|
cancellable, cancel := context.WithCancel(ctx)
|
||||||
events, err := c.taskService.Events(cancellable, &execution.EventsRequest{})
|
eventstream, err := c.eventService.Subscribe(cancellable, &events.SubscribeRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get containerd event: %v", err)
|
return nil, fmt.Errorf("failed to get containerd event: %v", err)
|
||||||
}
|
}
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
resp, err := c.taskService.Exec(ctx, &execution.ExecRequest{
|
execID := generateID()
|
||||||
|
_, err = c.taskService.Exec(ctx, &tasks.ExecProcessRequest{
|
||||||
ContainerID: id,
|
ContainerID: id,
|
||||||
Terminal: false,
|
Terminal: false,
|
||||||
Stdout: stdout,
|
Stdout: stdout,
|
||||||
@ -115,14 +116,22 @@ func (c *criContainerdService) ExecSync(ctx context.Context, r *runtime.ExecSync
|
|||||||
TypeUrl: runtimespec.Version,
|
TypeUrl: runtimespec.Version,
|
||||||
Value: rawSpec,
|
Value: rawSpec,
|
||||||
},
|
},
|
||||||
|
ExecID: execID,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to exec in container %q: %v", id, err)
|
return nil, fmt.Errorf("failed to exec in container %q: %v", id, err)
|
||||||
}
|
}
|
||||||
exitCode, err := waitContainerExec(cancel, events, id, resp.Pid, r.GetTimeout())
|
exitCode, err := c.waitContainerExec(eventstream, id, execID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to wait for exec in container %q to finish: %v", id, err)
|
return nil, fmt.Errorf("failed to wait for exec in container %q to finish: %v", id, err)
|
||||||
}
|
}
|
||||||
|
if _, err := c.taskService.DeleteProcess(ctx, &tasks.DeleteProcessRequest{
|
||||||
|
ContainerID: id,
|
||||||
|
ExecID: execID,
|
||||||
|
}); err != nil && !isContainerdGRPCNotFoundError(err) {
|
||||||
|
return nil, fmt.Errorf("failed to delete exec %q in container %q: %v", execID, id, err)
|
||||||
|
}
|
||||||
|
// TODO(random-liu): [P1] Deal with timeout, kill and wait again on timeout.
|
||||||
|
|
||||||
// TODO(random-liu): Make sure stdout/stderr are drained.
|
// TODO(random-liu): Make sure stdout/stderr are drained.
|
||||||
return &runtime.ExecSyncResponse{
|
return &runtime.ExecSyncResponse{
|
||||||
@ -133,30 +142,24 @@ func (c *criContainerdService) ExecSync(ctx context.Context, r *runtime.ExecSync
|
|||||||
}
|
}
|
||||||
|
|
||||||
// waitContainerExec waits for container exec to finish and returns the exit code.
|
// waitContainerExec waits for container exec to finish and returns the exit code.
|
||||||
func waitContainerExec(cancel context.CancelFunc, events execution.Tasks_EventsClient, id string,
|
func (c *criContainerdService) waitContainerExec(eventstream events.Events_SubscribeClient, id string,
|
||||||
pid uint32, timeout int64) (uint32, error) {
|
execID string) (uint32, error) {
|
||||||
// TODO(random-liu): [P1] Support ExecSync timeout.
|
|
||||||
// TODO(random-liu): Delete process after containerd upgrade.
|
|
||||||
defer func() {
|
|
||||||
// Stop events and drain the event channel. grpc-go#188
|
|
||||||
cancel()
|
|
||||||
for {
|
|
||||||
_, err := events.Recv()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
for {
|
for {
|
||||||
e, err := events.Recv()
|
evt, err := eventstream.Recv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Return non-zero exit code just in case.
|
// Return non-zero exit code just in case.
|
||||||
return unknownExitCode, err
|
return unknownExitCode, err
|
||||||
}
|
}
|
||||||
if e.Type != task.Event_EXIT {
|
// Continue until the event received is of type task exit.
|
||||||
|
if !typeurl.Is(evt.Event, &events.TaskExit{}) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if e.ID == id && e.Pid == pid {
|
any, err := typeurl.UnmarshalAny(evt.Event)
|
||||||
|
if err != nil {
|
||||||
|
return unknownExitCode, err
|
||||||
|
}
|
||||||
|
e := any.(*events.TaskExit)
|
||||||
|
if e.ContainerID == id && e.ID == execID {
|
||||||
return e.ExitStatus, nil
|
return e.ExitStatus, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,7 @@ package server
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/containerd/containerd/api/services/containers"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/snapshot"
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||||
@ -71,7 +70,7 @@ func (c *criContainerdService) RemoveContainer(ctx context.Context, r *runtime.R
|
|||||||
|
|
||||||
// Remove container snapshot.
|
// Remove container snapshot.
|
||||||
if err := c.snapshotService.Remove(ctx, id); err != nil {
|
if err := c.snapshotService.Remove(ctx, id); err != nil {
|
||||||
if !snapshot.IsNotExist(err) {
|
if !errdefs.IsNotFound(err) {
|
||||||
return nil, fmt.Errorf("failed to remove container snapshot %q: %v", id, err)
|
return nil, fmt.Errorf("failed to remove container snapshot %q: %v", id, err)
|
||||||
}
|
}
|
||||||
glog.V(5).Infof("Remove called for snapshot %q that does not exist", id)
|
glog.V(5).Infof("Remove called for snapshot %q that does not exist", id)
|
||||||
@ -89,7 +88,7 @@ func (c *criContainerdService) RemoveContainer(ctx context.Context, r *runtime.R
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete containerd container.
|
// Delete containerd container.
|
||||||
if _, err := c.containerService.Delete(ctx, &containers.DeleteContainerRequest{ID: id}); err != nil {
|
if err := c.containerService.Delete(ctx, id); err != nil {
|
||||||
if !isContainerdGRPCNotFoundError(err) {
|
if !isContainerdGRPCNotFoundError(err) {
|
||||||
return nil, fmt.Errorf("failed to delete containerd container %q: %v", id, err)
|
return nil, fmt.Errorf("failed to delete containerd container %q: %v", id, err)
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/api/services/execution"
|
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||||
"github.com/containerd/containerd/api/types/mount"
|
"github.com/containerd/containerd/api/types"
|
||||||
"github.com/containerd/containerd/api/types/task"
|
"github.com/containerd/containerd/api/types/task"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
@ -97,7 +97,7 @@ func (c *criContainerdService) startContainer(ctx context.Context, id string, me
|
|||||||
sandboxConfig := sandbox.Config
|
sandboxConfig := sandbox.Config
|
||||||
sandboxID := meta.SandboxID
|
sandboxID := meta.SandboxID
|
||||||
// Make sure sandbox is running.
|
// Make sure sandbox is running.
|
||||||
sandboxInfo, err := c.taskService.Info(ctx, &execution.InfoRequest{ContainerID: sandboxID})
|
sandboxInfo, err := c.taskService.Get(ctx, &tasks.GetTaskRequest{ContainerID: sandboxID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get sandbox container %q info: %v", sandboxID, err)
|
return fmt.Errorf("failed to get sandbox container %q info: %v", sandboxID, err)
|
||||||
}
|
}
|
||||||
@ -153,9 +153,9 @@ func (c *criContainerdService) startContainer(ctx context.Context, id string, me
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get rootfs mounts %q: %v", id, err)
|
return fmt.Errorf("failed to get rootfs mounts %q: %v", id, err)
|
||||||
}
|
}
|
||||||
var rootfs []*mount.Mount
|
var rootfs []*types.Mount
|
||||||
for _, m := range rootfsMounts {
|
for _, m := range rootfsMounts {
|
||||||
rootfs = append(rootfs, &mount.Mount{
|
rootfs = append(rootfs, &types.Mount{
|
||||||
Type: m.Type,
|
Type: m.Type,
|
||||||
Source: m.Source,
|
Source: m.Source,
|
||||||
Options: m.Options,
|
Options: m.Options,
|
||||||
@ -163,7 +163,7 @@ func (c *criContainerdService) startContainer(ctx context.Context, id string, me
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create containerd task.
|
// Create containerd task.
|
||||||
createOpts := &execution.CreateRequest{
|
createOpts := &tasks.CreateTaskRequest{
|
||||||
ContainerID: id,
|
ContainerID: id,
|
||||||
Rootfs: rootfs,
|
Rootfs: rootfs,
|
||||||
Stdin: stdin,
|
Stdin: stdin,
|
||||||
@ -180,14 +180,14 @@ func (c *criContainerdService) startContainer(ctx context.Context, id string, me
|
|||||||
defer func() {
|
defer func() {
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
// Cleanup the containerd task if an error is returned.
|
// Cleanup the containerd task if an error is returned.
|
||||||
if _, err := c.taskService.Delete(ctx, &execution.DeleteRequest{ContainerID: id}); err != nil {
|
if _, err := c.taskService.Delete(ctx, &tasks.DeleteTaskRequest{ContainerID: id}); err != nil {
|
||||||
glog.Errorf("Failed to delete containerd task %q: %v", id, err)
|
glog.Errorf("Failed to delete containerd task %q: %v", id, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Start containerd task.
|
// Start containerd task.
|
||||||
if _, err := c.taskService.Start(ctx, &execution.StartRequest{ContainerID: id}); err != nil {
|
if _, err := c.taskService.Start(ctx, &tasks.StartTaskRequest{ContainerID: id}); err != nil {
|
||||||
return fmt.Errorf("failed to start containerd task %q: %v", id, err)
|
return fmt.Errorf("failed to start containerd task %q: %v", id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/api/services/execution"
|
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||||
"github.com/docker/docker/pkg/signal"
|
"github.com/docker/docker/pkg/signal"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
@ -94,10 +94,10 @@ func (c *criContainerdService) stopContainer(ctx context.Context, container cont
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
glog.V(2).Infof("Stop container %q with signal %v", id, stopSignal)
|
glog.V(2).Infof("Stop container %q with signal %v", id, stopSignal)
|
||||||
_, err = c.taskService.Kill(ctx, &execution.KillRequest{
|
_, err = c.taskService.Kill(ctx, &tasks.KillRequest{
|
||||||
ContainerID: id,
|
ContainerID: id,
|
||||||
Signal: uint32(stopSignal),
|
Signal: uint32(stopSignal),
|
||||||
PidOrAll: &execution.KillRequest_All{All: true},
|
All: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !isContainerdGRPCNotFoundError(err) && !isRuncProcessAlreadyFinishedError(err) {
|
if !isContainerdGRPCNotFoundError(err) && !isRuncProcessAlreadyFinishedError(err) {
|
||||||
@ -115,10 +115,10 @@ func (c *criContainerdService) stopContainer(ctx context.Context, container cont
|
|||||||
|
|
||||||
// Event handler will Delete the container from containerd after it handles the Exited event.
|
// Event handler will Delete the container from containerd after it handles the Exited event.
|
||||||
glog.V(2).Infof("Kill container %q", id)
|
glog.V(2).Infof("Kill container %q", id)
|
||||||
_, err := c.taskService.Kill(ctx, &execution.KillRequest{
|
_, err := c.taskService.Kill(ctx, &tasks.KillRequest{
|
||||||
ContainerID: id,
|
ContainerID: id,
|
||||||
Signal: uint32(unix.SIGKILL),
|
Signal: uint32(unix.SIGKILL),
|
||||||
PidOrAll: &execution.KillRequest_All{All: true},
|
All: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !isContainerdGRPCNotFoundError(err) && !isRuncProcessAlreadyFinishedError(err) {
|
if !isContainerdGRPCNotFoundError(err) && !isRuncProcessAlreadyFinishedError(err) {
|
||||||
|
@ -19,8 +19,9 @@ package server
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/api/services/execution"
|
"github.com/containerd/containerd/api/services/events/v1"
|
||||||
"github.com/containerd/containerd/api/types/task"
|
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||||
|
"github.com/containerd/containerd/typeurl"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/jpillora/backoff"
|
"github.com/jpillora/backoff"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
@ -48,7 +49,7 @@ func (c *criContainerdService) startEventMonitor() {
|
|||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
events, err := c.taskService.Events(context.Background(), &execution.EventsRequest{})
|
eventstream, err := c.eventService.Subscribe(context.Background(), &events.SubscribeRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to connect to containerd event stream: %v", err)
|
glog.Errorf("Failed to connect to containerd event stream: %v", err)
|
||||||
time.Sleep(b.Duration())
|
time.Sleep(b.Duration())
|
||||||
@ -59,7 +60,7 @@ func (c *criContainerdService) startEventMonitor() {
|
|||||||
// TODO(random-liu): Relist to recover state, should prevent other operations
|
// TODO(random-liu): Relist to recover state, should prevent other operations
|
||||||
// until state is fully recovered.
|
// until state is fully recovered.
|
||||||
for {
|
for {
|
||||||
if err := c.handleEventStream(events); err != nil {
|
if err := c.handleEventStream(eventstream); err != nil {
|
||||||
glog.Errorf("Failed to handle event stream: %v", err)
|
glog.Errorf("Failed to handle event stream: %v", err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -69,27 +70,34 @@ func (c *criContainerdService) startEventMonitor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handleEventStream receives an event from containerd and handles the event.
|
// handleEventStream receives an event from containerd and handles the event.
|
||||||
func (c *criContainerdService) handleEventStream(events execution.Tasks_EventsClient) error {
|
func (c *criContainerdService) handleEventStream(eventstream events.Events_SubscribeClient) error {
|
||||||
e, err := events.Recv()
|
e, err := eventstream.Recv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
glog.V(2).Infof("Received container event: %+v", e)
|
glog.V(4).Infof("Received container event timestamp - %v, namespace - %q, topic - %q", e.Timestamp, e.Namespace, e.Topic)
|
||||||
c.handleEvent(e)
|
c.handleEvent(e)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleEvent handles a containerd event.
|
// handleEvent handles a containerd event.
|
||||||
func (c *criContainerdService) handleEvent(e *task.Event) {
|
func (c *criContainerdService) handleEvent(evt *events.Envelope) {
|
||||||
switch e.Type {
|
any, err := typeurl.UnmarshalAny(evt.Event)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("Failed to convert event envelope %+v: %v", evt, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch any.(type) {
|
||||||
// If containerd-shim exits unexpectedly, there will be no corresponding event.
|
// If containerd-shim exits unexpectedly, there will be no corresponding event.
|
||||||
// However, containerd could not retrieve container state in that case, so it's
|
// However, containerd could not retrieve container state in that case, so it's
|
||||||
// fine to leave out that case for now.
|
// fine to leave out that case for now.
|
||||||
// TODO(random-liu): [P2] Handle containerd-shim exit.
|
// TODO(random-liu): [P2] Handle containerd-shim exit.
|
||||||
case task.Event_EXIT:
|
case *events.TaskExit:
|
||||||
cntr, err := c.containerStore.Get(e.ID)
|
e := any.(*events.TaskExit)
|
||||||
|
glog.V(2).Infof("TaskExit event %+v", e)
|
||||||
|
cntr, err := c.containerStore.Get(e.ContainerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to get container %q: %v", e.ID, err)
|
glog.Errorf("Failed to get container %q: %v", e.ContainerID, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if e.Pid != cntr.Status.Get().Pid {
|
if e.Pid != cntr.Status.Get().Pid {
|
||||||
@ -97,10 +105,11 @@ func (c *criContainerdService) handleEvent(e *task.Event) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Delete the container from containerd.
|
// Delete the container from containerd.
|
||||||
_, err = c.taskService.Delete(context.Background(), &execution.DeleteRequest{ContainerID: e.ID})
|
_, err = c.taskService.Delete(context.Background(), &tasks.DeleteTaskRequest{ContainerID: e.ContainerID})
|
||||||
|
// TODO(random-liu): Change isContainerdGRPCNotFoundError to use errdefs.
|
||||||
if err != nil && !isContainerdGRPCNotFoundError(err) {
|
if err != nil && !isContainerdGRPCNotFoundError(err) {
|
||||||
// TODO(random-liu): [P0] Enqueue the event and retry.
|
// TODO(random-liu): [P0] Enqueue the event and retry.
|
||||||
glog.Errorf("Failed to delete container %q: %v", e.ID, err)
|
glog.Errorf("Failed to delete container %q: %v", e.ContainerID, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = cntr.Status.Update(func(status containerstore.Status) (containerstore.Status, error) {
|
err = cntr.Status.Update(func(status containerstore.Status) (containerstore.Status, error) {
|
||||||
@ -115,21 +124,23 @@ func (c *criContainerdService) handleEvent(e *task.Event) {
|
|||||||
return status, nil
|
return status, nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to update container %q state: %v", e.ID, err)
|
glog.Errorf("Failed to update container %q state: %v", e.ContainerID, err)
|
||||||
// TODO(random-liu): [P0] Enqueue the event and retry.
|
// TODO(random-liu): [P0] Enqueue the event and retry.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case task.Event_OOM:
|
case *events.TaskOOM:
|
||||||
cntr, err := c.containerStore.Get(e.ID)
|
e := any.(*events.TaskOOM)
|
||||||
|
glog.V(2).Infof("TaskOOM event %+v", e)
|
||||||
|
cntr, err := c.containerStore.Get(e.ContainerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to get container %q: %v", e.ID, err)
|
glog.Errorf("Failed to get container %q: %v", e.ContainerID, err)
|
||||||
}
|
}
|
||||||
err = cntr.Status.Update(func(status containerstore.Status) (containerstore.Status, error) {
|
err = cntr.Status.Update(func(status containerstore.Status) (containerstore.Status, error) {
|
||||||
status.Reason = oomExitReason
|
status.Reason = oomExitReason
|
||||||
return status, nil
|
return status, nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Failed to update container %q oom: %v", e.ID, err)
|
glog.Errorf("Failed to update container %q oom: %v", e.ContainerID, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
containerdmetadata "github.com/containerd/containerd/metadata"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
"github.com/docker/docker/pkg/stringid"
|
"github.com/docker/docker/pkg/stringid"
|
||||||
imagedigest "github.com/opencontainers/go-digest"
|
imagedigest "github.com/opencontainers/go-digest"
|
||||||
@ -69,7 +69,7 @@ const (
|
|||||||
relativeRootfsPath = "rootfs"
|
relativeRootfsPath = "rootfs"
|
||||||
// defaultRuntime is the runtime to use in containerd. We may support
|
// defaultRuntime is the runtime to use in containerd. We may support
|
||||||
// other runtime in the future.
|
// other runtime in the future.
|
||||||
defaultRuntime = "linux"
|
defaultRuntime = "io.containerd.runtime.v1.linux"
|
||||||
// sandboxesDir contains all sandbox root. A sandbox root is the running
|
// sandboxesDir contains all sandbox root. A sandbox root is the running
|
||||||
// directory of the sandbox, all files created for the sandbox will be
|
// directory of the sandbox, all files created for the sandbox will be
|
||||||
// placed under this directory.
|
// placed under this directory.
|
||||||
@ -339,7 +339,7 @@ func (c *criContainerdService) localResolve(ctx context.Context, ref string) (*i
|
|||||||
}
|
}
|
||||||
imageInContainerd, err := c.imageStoreService.Get(ctx, normalized.String())
|
imageInContainerd, err := c.imageStoreService.Get(ctx, normalized.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if containerdmetadata.IsNotFound(err) {
|
if errdefs.IsNotFound(err) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("an error occurred when getting image %q from containerd image store: %v",
|
return nil, fmt.Errorf("an error occurred when getting image %q from containerd image store: %v",
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
containerdimages "github.com/containerd/containerd/images"
|
containerdimages "github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/remotes"
|
"github.com/containerd/containerd/remotes"
|
||||||
"github.com/containerd/containerd/remotes/docker"
|
"github.com/containerd/containerd/remotes/docker"
|
||||||
@ -279,9 +280,8 @@ func (c *criContainerdService) pullImage(ctx context.Context, rawRef string, aut
|
|||||||
if r == "" {
|
if r == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := c.imageStoreService.Put(ctx, r, desc); err != nil {
|
if err := c.createImageReference(ctx, r, desc); err != nil {
|
||||||
return "", "", "", fmt.Errorf("failed to put image reference %q desc %v into containerd image store: %v",
|
return "", "", "", fmt.Errorf("failed to update image reference %q: %v", r, err)
|
||||||
r, desc, err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Do not cleanup if following operations fail so as to make resumable download possible.
|
// Do not cleanup if following operations fail so as to make resumable download possible.
|
||||||
@ -331,13 +331,34 @@ func (c *criContainerdService) pullImage(ctx context.Context, rawRef string, aut
|
|||||||
// Use config digest as imageID to conform to oci image spec, and also add image id as
|
// Use config digest as imageID to conform to oci image spec, and also add image id as
|
||||||
// image reference.
|
// image reference.
|
||||||
imageID := configDesc.Digest.String()
|
imageID := configDesc.Digest.String()
|
||||||
if err := c.imageStoreService.Put(ctx, imageID, desc); err != nil {
|
if err := c.createImageReference(ctx, imageID, desc); err != nil {
|
||||||
return "", "", "", fmt.Errorf("failed to put image id %q into containerd image store: %v",
|
return "", "", "", fmt.Errorf("failed to update image id %q: %v", imageID, err)
|
||||||
imageID, err)
|
|
||||||
}
|
}
|
||||||
return imageID, repoTag, repoDigest, nil
|
return imageID, repoTag, repoDigest, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createImageReference creates image reference inside containerd image store.
|
||||||
|
// Note that because create and update are not finished in one transaction, there could be race. E.g.
|
||||||
|
// the image reference is deleted by someone else after create returns already exists, but before update
|
||||||
|
// happens.
|
||||||
|
func (c *criContainerdService) createImageReference(ctx context.Context, name string, desc imagespec.Descriptor) error {
|
||||||
|
img := containerdimages.Image{
|
||||||
|
Name: name,
|
||||||
|
Target: desc,
|
||||||
|
}
|
||||||
|
// TODO(random-liu): Figure out which is the more performant sequence create then update or
|
||||||
|
// update then create.
|
||||||
|
_, err := c.imageStoreService.Create(ctx, img)
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil && !errdefs.IsAlreadyExists(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = c.imageStoreService.Update(ctx, img, "target")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// waitDownloadingPollInterval is the interval to check resource downloading progress.
|
// waitDownloadingPollInterval is the interval to check resource downloading progress.
|
||||||
const waitDownloadingPollInterval = 200 * time.Millisecond
|
const waitDownloadingPollInterval = 200 * time.Millisecond
|
||||||
|
|
||||||
@ -350,7 +371,7 @@ func (c *criContainerdService) waitForResourcesDownloading(ctx context.Context,
|
|||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
// TODO(random-liu): Use better regexp when containerd `MakeRefKey` contains more
|
// TODO(random-liu): Use better regexp when containerd `MakeRefKey` contains more
|
||||||
// information.
|
// information.
|
||||||
statuses, err := c.contentStoreService.Status(ctx, "")
|
statuses, err := c.contentStoreService.ListStatuses(ctx, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get content status: %v", err)
|
return fmt.Errorf("failed to get content status: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ package server
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
containerdmetadata "github.com/containerd/containerd/metadata"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||||
@ -51,8 +51,10 @@ func (c *criContainerdService) RemoveImage(ctx context.Context, r *runtime.Remov
|
|||||||
for _, ref := range append(append(image.RepoTags, image.RepoDigests...), image.ID) {
|
for _, ref := range append(append(image.RepoTags, image.RepoDigests...), image.ID) {
|
||||||
// TODO(random-liu): Containerd should schedule a garbage collection immediately,
|
// TODO(random-liu): Containerd should schedule a garbage collection immediately,
|
||||||
// and we may want to wait for the garbage collection to be over here.
|
// and we may want to wait for the garbage collection to be over here.
|
||||||
|
// TODO(random-liu): Should check whether descriptor is as expected before delete,
|
||||||
|
// so as to avoid deleting new reference because of staled reference.
|
||||||
err = c.imageStoreService.Delete(ctx, ref)
|
err = c.imageStoreService.Delete(ctx, ref)
|
||||||
if err == nil || containerdmetadata.IsNotFound(err) {
|
if err == nil || errdefs.IsNotFound(err) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("failed to delete image reference %q for image %q: %v", ref, image.ID, err)
|
return nil, fmt.Errorf("failed to delete image reference %q for image %q: %v", ref, image.ID, err)
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
|
||||||
"github.com/containerd/containerd/api/services/execution"
|
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||||
|
|
||||||
"github.com/containerd/containerd/api/types/task"
|
"github.com/containerd/containerd/api/types/task"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||||
@ -42,7 +42,7 @@ func (c *criContainerdService) ListPodSandbox(ctx context.Context, r *runtime.Li
|
|||||||
// List all sandboxes from store.
|
// List all sandboxes from store.
|
||||||
sandboxesInStore := c.sandboxStore.List()
|
sandboxesInStore := c.sandboxStore.List()
|
||||||
|
|
||||||
resp, err := c.taskService.List(ctx, &execution.ListRequest{})
|
resp, err := c.taskService.List(ctx, &tasks.ListTasksRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to list sandbox containers: %v", err)
|
return nil, fmt.Errorf("failed to list sandbox containers: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,8 @@ package server
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/containerd/containerd/api/services/containers"
|
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||||
"github.com/containerd/containerd/api/services/execution"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/snapshot"
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||||
@ -55,7 +54,7 @@ func (c *criContainerdService) RemovePodSandbox(ctx context.Context, r *runtime.
|
|||||||
|
|
||||||
// Return error if sandbox container is not fully stopped.
|
// Return error if sandbox container is not fully stopped.
|
||||||
// TODO(random-liu): [P0] Make sure network is torn down, may need to introduce a state.
|
// TODO(random-liu): [P0] Make sure network is torn down, may need to introduce a state.
|
||||||
_, err = c.taskService.Info(ctx, &execution.InfoRequest{ContainerID: id})
|
_, err = c.taskService.Get(ctx, &tasks.GetTaskRequest{ContainerID: id})
|
||||||
if err != nil && !isContainerdGRPCNotFoundError(err) {
|
if err != nil && !isContainerdGRPCNotFoundError(err) {
|
||||||
return nil, fmt.Errorf("failed to get sandbox container info for %q: %v", id, err)
|
return nil, fmt.Errorf("failed to get sandbox container info for %q: %v", id, err)
|
||||||
}
|
}
|
||||||
@ -65,7 +64,7 @@ func (c *criContainerdService) RemovePodSandbox(ctx context.Context, r *runtime.
|
|||||||
|
|
||||||
// Remove sandbox container snapshot.
|
// Remove sandbox container snapshot.
|
||||||
if err := c.snapshotService.Remove(ctx, id); err != nil {
|
if err := c.snapshotService.Remove(ctx, id); err != nil {
|
||||||
if !snapshot.IsNotExist(err) {
|
if !errdefs.IsNotFound(err) {
|
||||||
return nil, fmt.Errorf("failed to remove sandbox container snapshot %q: %v", id, err)
|
return nil, fmt.Errorf("failed to remove sandbox container snapshot %q: %v", id, err)
|
||||||
}
|
}
|
||||||
glog.V(5).Infof("Remove called for snapshot %q that does not exist", id)
|
glog.V(5).Infof("Remove called for snapshot %q that does not exist", id)
|
||||||
@ -97,7 +96,7 @@ func (c *criContainerdService) RemovePodSandbox(ctx context.Context, r *runtime.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete sandbox container.
|
// Delete sandbox container.
|
||||||
if _, err := c.containerService.Delete(ctx, &containers.DeleteContainerRequest{ID: id}); err != nil {
|
if err := c.containerService.Delete(ctx, id); err != nil {
|
||||||
if !isContainerdGRPCNotFoundError(err) {
|
if !isContainerdGRPCNotFoundError(err) {
|
||||||
return nil, fmt.Errorf("failed to delete sandbox container %q: %v", id, err)
|
return nil, fmt.Errorf("failed to delete sandbox container %q: %v", id, err)
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/api/services/containers"
|
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||||
"github.com/containerd/containerd/api/services/execution"
|
"github.com/containerd/containerd/api/types"
|
||||||
"github.com/containerd/containerd/api/types/mount"
|
"github.com/containerd/containerd/containers"
|
||||||
prototypes "github.com/gogo/protobuf/types"
|
prototypes "github.com/gogo/protobuf/types"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
@ -90,9 +90,9 @@ func (c *criContainerdService) RunPodSandbox(ctx context.Context, r *runtime.Run
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
var rootfs []*mount.Mount
|
var rootfs []*types.Mount
|
||||||
for _, m := range rootfsMounts {
|
for _, m := range rootfsMounts {
|
||||||
rootfs = append(rootfs, &mount.Mount{
|
rootfs = append(rootfs, &types.Mount{
|
||||||
Type: m.Type,
|
Type: m.Type,
|
||||||
Source: m.Source,
|
Source: m.Source,
|
||||||
Options: m.Options,
|
Options: m.Options,
|
||||||
@ -109,24 +109,22 @@ func (c *criContainerdService) RunPodSandbox(ctx context.Context, r *runtime.Run
|
|||||||
return nil, fmt.Errorf("failed to marshal oci spec %+v: %v", spec, err)
|
return nil, fmt.Errorf("failed to marshal oci spec %+v: %v", spec, err)
|
||||||
}
|
}
|
||||||
glog.V(4).Infof("Sandbox container spec: %+v", spec)
|
glog.V(4).Infof("Sandbox container spec: %+v", spec)
|
||||||
if _, err = c.containerService.Create(ctx, &containers.CreateContainerRequest{
|
if _, err = c.containerService.Create(ctx, containers.Container{
|
||||||
Container: containers.Container{
|
ID: id,
|
||||||
ID: id,
|
// TODO(random-liu): Checkpoint metadata into container labels.
|
||||||
// TODO(random-liu): Checkpoint metadata into container labels.
|
Image: image.ID,
|
||||||
Image: image.ID,
|
Runtime: containers.RuntimeInfo{Name: defaultRuntime},
|
||||||
Runtime: defaultRuntime,
|
Spec: &prototypes.Any{
|
||||||
Spec: &prototypes.Any{
|
TypeUrl: runtimespec.Version,
|
||||||
TypeUrl: runtimespec.Version,
|
Value: rawSpec,
|
||||||
Value: rawSpec,
|
|
||||||
},
|
|
||||||
RootFS: id,
|
|
||||||
},
|
},
|
||||||
|
RootFS: id,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, fmt.Errorf("failed to create containerd container: %v", err)
|
return nil, fmt.Errorf("failed to create containerd container: %v", err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
if _, err := c.containerService.Delete(ctx, &containers.DeleteContainerRequest{ID: id}); err != nil {
|
if err := c.containerService.Delete(ctx, id); err != nil {
|
||||||
glog.Errorf("Failed to delete containerd container%q: %v", id, err)
|
glog.Errorf("Failed to delete containerd container%q: %v", id, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,7 +179,7 @@ func (c *criContainerdService) RunPodSandbox(ctx context.Context, r *runtime.Run
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
createOpts := &execution.CreateRequest{
|
createOpts := &tasks.CreateTaskRequest{
|
||||||
ContainerID: id,
|
ContainerID: id,
|
||||||
Rootfs: rootfs,
|
Rootfs: rootfs,
|
||||||
// No stdin for sandbox container.
|
// No stdin for sandbox container.
|
||||||
@ -199,9 +197,8 @@ func (c *criContainerdService) RunPodSandbox(ctx context.Context, r *runtime.Run
|
|||||||
defer func() {
|
defer func() {
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
// Cleanup the sandbox container if an error is returned.
|
// Cleanup the sandbox container if an error is returned.
|
||||||
if _, err = c.taskService.Delete(ctx, &execution.DeleteRequest{ContainerID: id}); err != nil {
|
if err := c.stopSandboxContainer(ctx, id); err != nil {
|
||||||
glog.Errorf("Failed to delete sandbox container %q: %v",
|
glog.Errorf("Failed to delete sandbox container %q: %v", id, err)
|
||||||
id, err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -226,7 +223,7 @@ func (c *criContainerdService) RunPodSandbox(ctx context.Context, r *runtime.Run
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start sandbox container in containerd.
|
// Start sandbox container in containerd.
|
||||||
if _, err := c.taskService.Start(ctx, &execution.StartRequest{ContainerID: id}); err != nil {
|
if _, err := c.taskService.Start(ctx, &tasks.StartTaskRequest{ContainerID: id}); err != nil {
|
||||||
return nil, fmt.Errorf("failed to start sandbox container %q: %v",
|
return nil, fmt.Errorf("failed to start sandbox container %q: %v",
|
||||||
id, err)
|
id, err)
|
||||||
}
|
}
|
||||||
@ -314,7 +311,7 @@ func (c *criContainerdService) generateSandboxContainerSpec(id string, config *r
|
|||||||
// TODO(random-liu): [P2] Set apparmor and seccomp from annotations.
|
// TODO(random-liu): [P2] Set apparmor and seccomp from annotations.
|
||||||
|
|
||||||
g.SetLinuxResourcesCPUShares(uint64(defaultSandboxCPUshares))
|
g.SetLinuxResourcesCPUShares(uint64(defaultSandboxCPUshares))
|
||||||
g.SetLinuxResourcesOOMScoreAdj(int(defaultSandboxOOMAdj))
|
g.SetProcessOOMScoreAdj(int(defaultSandboxOOMAdj))
|
||||||
|
|
||||||
return g.Spec(), nil
|
return g.Spec(), nil
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ func getRunPodSandboxTestData() (*runtime.PodSandboxConfig, *imagespec.ImageConf
|
|||||||
assert.Equal(t, []string{"/pause", "forever"}, spec.Process.Args)
|
assert.Equal(t, []string{"/pause", "forever"}, spec.Process.Args)
|
||||||
assert.Equal(t, "/workspace", spec.Process.Cwd)
|
assert.Equal(t, "/workspace", spec.Process.Cwd)
|
||||||
assert.EqualValues(t, *spec.Linux.Resources.CPU.Shares, defaultSandboxCPUshares)
|
assert.EqualValues(t, *spec.Linux.Resources.CPU.Shares, defaultSandboxCPUshares)
|
||||||
assert.EqualValues(t, *spec.Linux.Resources.OOMScoreAdj, defaultSandboxOOMAdj)
|
assert.EqualValues(t, *spec.Process.OOMScoreAdj, defaultSandboxOOMAdj)
|
||||||
}
|
}
|
||||||
return config, imageConfig, specCheck
|
return config, imageConfig, specCheck
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
|
||||||
"github.com/containerd/containerd/api/services/execution"
|
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||||
"github.com/containerd/containerd/api/types/task"
|
"github.com/containerd/containerd/api/types/task"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||||
@ -47,7 +47,7 @@ func (c *criContainerdService) PodSandboxStatus(ctx context.Context, r *runtime.
|
|||||||
// Use the full sandbox id.
|
// Use the full sandbox id.
|
||||||
id := sandbox.ID
|
id := sandbox.ID
|
||||||
|
|
||||||
info, err := c.taskService.Info(ctx, &execution.InfoRequest{ContainerID: id})
|
info, err := c.taskService.Get(ctx, &tasks.GetTaskRequest{ContainerID: id})
|
||||||
if err != nil && !isContainerdGRPCNotFoundError(err) {
|
if err != nil && !isContainerdGRPCNotFoundError(err) {
|
||||||
return nil, fmt.Errorf("failed to get sandbox container info for %q: %v", id, err)
|
return nil, fmt.Errorf("failed to get sandbox container info for %q: %v", id, err)
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/api/services/events/v1"
|
||||||
|
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||||
|
"github.com/containerd/containerd/api/types/task"
|
||||||
|
"github.com/containerd/containerd/typeurl"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
"github.com/containerd/containerd/api/services/execution"
|
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -77,16 +79,73 @@ func (c *criContainerdService) StopPodSandbox(ctx context.Context, r *runtime.St
|
|||||||
glog.V(2).Infof("TearDown network for sandbox %q successfully", id)
|
glog.V(2).Infof("TearDown network for sandbox %q successfully", id)
|
||||||
|
|
||||||
sandboxRoot := getSandboxRootDir(c.rootDir, id)
|
sandboxRoot := getSandboxRootDir(c.rootDir, id)
|
||||||
if err = c.unmountSandboxFiles(sandboxRoot, sandbox.Config); err != nil {
|
if err := c.unmountSandboxFiles(sandboxRoot, sandbox.Config); err != nil {
|
||||||
return nil, fmt.Errorf("failed to unmount sandbox files in %q: %v", sandboxRoot, err)
|
return nil, fmt.Errorf("failed to unmount sandbox files in %q: %v", sandboxRoot, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(random-liu): [P1] Handle sandbox container graceful deletion.
|
if err := c.stopSandboxContainer(ctx, id); err != nil {
|
||||||
// Delete the sandbox container from containerd.
|
return nil, fmt.Errorf("failed to stop sandbox container %q: %v", id, err)
|
||||||
_, err = c.taskService.Delete(ctx, &execution.DeleteRequest{ContainerID: id})
|
|
||||||
if err != nil && !isContainerdGRPCNotFoundError(err) {
|
|
||||||
return nil, fmt.Errorf("failed to delete sandbox container %q: %v", id, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &runtime.StopPodSandboxResponse{}, nil
|
return &runtime.StopPodSandboxResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// stopSandboxContainer kills and deletes sandbox container.
|
||||||
|
func (c *criContainerdService) stopSandboxContainer(ctx context.Context, id string) error {
|
||||||
|
cancellable, cancel := context.WithCancel(ctx)
|
||||||
|
eventstream, err := c.eventService.Subscribe(cancellable, &events.SubscribeRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get containerd event: %v", err)
|
||||||
|
}
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
resp, err := c.taskService.Get(ctx, &tasks.GetTaskRequest{ContainerID: id})
|
||||||
|
if err != nil {
|
||||||
|
if isContainerdGRPCNotFoundError(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to get sandbox container: %v", err)
|
||||||
|
}
|
||||||
|
if resp.Task.Status != task.StatusStopped {
|
||||||
|
// TODO(random-liu): [P1] Handle sandbox container graceful deletion.
|
||||||
|
if _, err := c.taskService.Kill(ctx, &tasks.KillRequest{
|
||||||
|
ContainerID: id,
|
||||||
|
Signal: uint32(unix.SIGKILL),
|
||||||
|
All: true,
|
||||||
|
}); err != nil && !isContainerdGRPCNotFoundError(err) && !isRuncProcessAlreadyFinishedError(err) {
|
||||||
|
return fmt.Errorf("failed to kill sandbox container: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.waitSandboxContainer(eventstream, id, resp.Task.Pid); err != nil {
|
||||||
|
return fmt.Errorf("failed to wait for pod sandbox to stop: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the sandbox container from containerd.
|
||||||
|
_, err = c.taskService.Delete(ctx, &tasks.DeleteTaskRequest{ContainerID: id})
|
||||||
|
if err != nil && !isContainerdGRPCNotFoundError(err) {
|
||||||
|
return fmt.Errorf("failed to delete sandbox container: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// waitSandboxContainer wait sandbox container stop event.
|
||||||
|
func (c *criContainerdService) waitSandboxContainer(eventstream events.Events_SubscribeClient, id string, pid uint32) error {
|
||||||
|
for {
|
||||||
|
evt, err := eventstream.Recv()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Continue until the event received is of type task exit.
|
||||||
|
if !typeurl.Is(evt.Event, &events.TaskExit{}) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
any, err := typeurl.UnmarshalAny(evt.Event)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e := any.(*events.TaskExit)
|
||||||
|
if e.ContainerID == id && e.Pid == pid {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -20,9 +20,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/api/services/containers"
|
"github.com/containerd/containerd/api/services/events/v1"
|
||||||
"github.com/containerd/containerd/api/services/execution"
|
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||||
versionapi "github.com/containerd/containerd/api/services/version"
|
versionapi "github.com/containerd/containerd/api/services/version/v1"
|
||||||
|
"github.com/containerd/containerd/containers"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
diffservice "github.com/containerd/containerd/services/diff"
|
diffservice "github.com/containerd/containerd/services/diff"
|
||||||
@ -71,9 +72,9 @@ type criContainerdService struct {
|
|||||||
// imageStore stores all resources associated with images.
|
// imageStore stores all resources associated with images.
|
||||||
imageStore *imagestore.Store
|
imageStore *imagestore.Store
|
||||||
// containerService is containerd containers client.
|
// containerService is containerd containers client.
|
||||||
containerService containers.ContainersClient
|
containerService containers.Store
|
||||||
// taskService is containerd tasks client.
|
// taskService is containerd tasks client.
|
||||||
taskService execution.TasksClient
|
taskService tasks.TasksClient
|
||||||
// contentStoreService is the containerd content service client.
|
// contentStoreService is the containerd content service client.
|
||||||
contentStoreService content.Store
|
contentStoreService content.Store
|
||||||
// snapshotService is the containerd snapshot service client.
|
// snapshotService is the containerd snapshot service client.
|
||||||
@ -93,6 +94,8 @@ type criContainerdService struct {
|
|||||||
agentFactory agents.AgentFactory
|
agentFactory agents.AgentFactory
|
||||||
// client is an instance of the containerd client
|
// client is an instance of the containerd client
|
||||||
client *containerd.Client
|
client *containerd.Client
|
||||||
|
// eventsService is the containerd task service client
|
||||||
|
eventService events.EventsClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCRIContainerdService returns a new instance of CRIContainerdService
|
// NewCRIContainerdService returns a new instance of CRIContainerdService
|
||||||
@ -117,12 +120,14 @@ func NewCRIContainerdService(containerdEndpoint, rootDir, networkPluginBinDir, n
|
|||||||
taskService: client.TaskService(),
|
taskService: client.TaskService(),
|
||||||
imageStoreService: client.ImageService(),
|
imageStoreService: client.ImageService(),
|
||||||
contentStoreService: client.ContentStore(),
|
contentStoreService: client.ContentStore(),
|
||||||
snapshotService: client.SnapshotService(),
|
// Use daemon default snapshotter.
|
||||||
diffService: client.DiffService(),
|
snapshotService: client.SnapshotService(""),
|
||||||
versionService: client.VersionService(),
|
diffService: client.DiffService(),
|
||||||
healthService: client.HealthService(),
|
versionService: client.VersionService(),
|
||||||
agentFactory: agents.NewAgentFactory(),
|
healthService: client.HealthService(),
|
||||||
client: client,
|
agentFactory: agents.NewAgentFactory(),
|
||||||
|
client: client,
|
||||||
|
eventService: client.EventService(),
|
||||||
}
|
}
|
||||||
|
|
||||||
netPlugin, err := ocicni.InitCNI(networkPluginBinDir, networkPluginConfDir)
|
netPlugin, err := ocicni.InitCNI(networkPluginBinDir, networkPluginConfDir)
|
||||||
|
@ -20,7 +20,7 @@ limitations under the License.
|
|||||||
package testing
|
package testing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
version "github.com/containerd/containerd/api/services/version"
|
version "github.com/containerd/containerd/api/services/version/v1"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
empty "github.com/golang/protobuf/ptypes/empty"
|
empty "github.com/golang/protobuf/ptypes/empty"
|
||||||
context "golang.org/x/net/context"
|
context "golang.org/x/net/context"
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
versionapi "github.com/containerd/containerd/api/services/version"
|
versionapi "github.com/containerd/containerd/api/services/version/v1"
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/golang/protobuf/ptypes/empty"
|
"github.com/golang/protobuf/ptypes/empty"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
Loading…
Reference in New Issue
Block a user