Remove container lifecycle image ref dependency.

Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
Lantao Liu 2018-12-06 01:39:49 -08:00
parent db0c4dea24
commit 515ef02473
5 changed files with 62 additions and 36 deletions

View File

@ -187,6 +187,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
opts = append(opts, customopts.WithVolumes(mountMap)) opts = append(opts, customopts.WithVolumes(mountMap))
} }
meta.ImageRef = image.ID meta.ImageRef = image.ID
meta.StopSignal = image.ImageSpec.Config.StopSignal
// Get container log path. // Get container log path.
if config.GetLogPath() != "" { if config.GetLogPath() != "" {

View File

@ -24,6 +24,7 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
"github.com/containerd/cri/pkg/store"
containerstore "github.com/containerd/cri/pkg/store/container" containerstore "github.com/containerd/cri/pkg/store/container"
) )
@ -43,17 +44,20 @@ func (c *criService) ContainerStatus(ctx context.Context, r *runtime.ContainerSt
imageRef := container.ImageRef imageRef := container.ImageRef
image, err := c.imageStore.Get(imageRef) image, err := c.imageStore.Get(imageRef)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "failed to get image %q", imageRef) if err != store.ErrNotExist {
} return nil, errors.Wrapf(err, "failed to get image %q", imageRef)
repoTags, repoDigests := parseImageReferences(image.References) }
if len(repoTags) > 0 { } else {
// Based on current behavior of dockershim, this field should be repoTags, repoDigests := parseImageReferences(image.References)
// image tag. if len(repoTags) > 0 {
spec = &runtime.ImageSpec{Image: repoTags[0]} // Based on current behavior of dockershim, this field should be
} // image tag.
if len(repoDigests) > 0 { spec = &runtime.ImageSpec{Image: repoTags[0]}
// Based on the CRI definition, this field will be consumed by user. }
imageRef = repoDigests[0] if len(repoDigests) > 0 {
// Based on the CRI definition, this field will be consumed by user.
imageRef = repoDigests[0]
}
} }
status := toCRIContainerStatus(container, spec, imageRef) status := toCRIContainerStatus(container, spec, imageRef)
info, err := toCRIContainerInfo(ctx, container, r.GetVerbose()) info, err := toCRIContainerInfo(ctx, container, r.GetVerbose())

View File

@ -27,6 +27,7 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2" runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
"github.com/containerd/cri/pkg/store"
containerstore "github.com/containerd/cri/pkg/store/container" containerstore "github.com/containerd/cri/pkg/store/container"
) )
@ -76,24 +77,36 @@ func (c *criService) stopContainer(ctx context.Context, container containerstore
// We only need to kill the task. The event handler will Delete the // We only need to kill the task. The event handler will Delete the
// task from containerd after it handles the Exited event. // task from containerd after it handles the Exited event.
if timeout > 0 { if timeout > 0 {
stopSignal := unix.SIGTERM stopSignal := "SIGTERM"
image, err := c.imageStore.Get(container.ImageRef) if container.StopSignal != "" {
if err != nil { stopSignal = container.StopSignal
// NOTE(random-liu): It's possible that the container is stopped, } else {
// deleted and image is garbage collected before this point. However, // The image may have been deleted, and the `StopSignal` field is
// the chance is really slim, even it happens, it's still fine to return // just introduced to handle that.
// an error here. // However, for containers created before the `StopSignal` field is
return errors.Wrapf(err, "failed to get image metadata %q", container.ImageRef) // introduced, still try to get the stop signal from the image config.
} // If the image has been deleted, logging an error and using the
if image.ImageSpec.Config.StopSignal != "" { // default SIGTERM is still better than returning error and leaving
stopSignal, err = signal.ParseSignal(image.ImageSpec.Config.StopSignal) // the container unstoppable. (See issue #990)
// TODO(random-liu): Remove this logic when containerd 1.2 is deprecated.
image, err := c.imageStore.Get(container.ImageRef)
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to parse stop signal %q", if err != store.ErrNotExist {
image.ImageSpec.Config.StopSignal) return errors.Wrapf(err, "failed to get image %q", container.ImageRef)
}
logrus.Warningf("Image %q not found, stop container with signal %q", container.ImageRef, stopSignal)
} else {
if image.ImageSpec.Config.StopSignal != "" {
stopSignal = image.ImageSpec.Config.StopSignal
}
} }
} }
logrus.Infof("Stop container %q with signal %v", id, stopSignal) sig, err := signal.ParseSignal(stopSignal)
if err = task.Kill(ctx, stopSignal); err != nil && !errdefs.IsNotFound(err) { if err != nil {
return errors.Wrapf(err, "failed to parse stop signal %q", stopSignal)
}
logrus.Infof("Stop container %q with signal %v", id, sig)
if err = task.Kill(ctx, sig); err != nil && !errdefs.IsNotFound(err) {
return errors.Wrapf(err, "failed to stop container %q", id) return errors.Wrapf(err, "failed to stop container %q", id)
} }

View File

@ -39,8 +39,9 @@ func TestContainerStore(t *testing.T) {
Attempt: 1, Attempt: 1,
}, },
}, },
ImageRef: "TestImage-1", ImageRef: "TestImage-1",
LogPath: "/test/log/path/1", StopSignal: "SIGTERM",
LogPath: "/test/log/path/1",
}, },
"2abcd": { "2abcd": {
ID: "2abcd", ID: "2abcd",
@ -52,8 +53,9 @@ func TestContainerStore(t *testing.T) {
Attempt: 2, Attempt: 2,
}, },
}, },
ImageRef: "TestImage-2", StopSignal: "SIGTERM",
LogPath: "/test/log/path/2", ImageRef: "TestImage-2",
LogPath: "/test/log/path/2",
}, },
"4a333": { "4a333": {
ID: "4a333", ID: "4a333",
@ -65,8 +67,9 @@ func TestContainerStore(t *testing.T) {
Attempt: 3, Attempt: 3,
}, },
}, },
ImageRef: "TestImage-3", StopSignal: "SIGTERM",
LogPath: "/test/log/path/3", ImageRef: "TestImage-3",
LogPath: "/test/log/path/3",
}, },
"4abcd": { "4abcd": {
ID: "4abcd", ID: "4abcd",
@ -78,7 +81,8 @@ func TestContainerStore(t *testing.T) {
Attempt: 1, Attempt: 1,
}, },
}, },
ImageRef: "TestImage-4abcd", StopSignal: "SIGTERM",
ImageRef: "TestImage-4abcd",
}, },
} }
statuses := map[string]Status{ statuses := map[string]Status{
@ -182,8 +186,9 @@ func TestWithContainerIO(t *testing.T) {
Attempt: 1, Attempt: 1,
}, },
}, },
ImageRef: "TestImage-1", ImageRef: "TestImage-1",
LogPath: "/test/log/path", StopSignal: "SIGTERM",
LogPath: "/test/log/path",
} }
status := Status{ status := Status{
Pid: 1, Pid: 1,

View File

@ -27,7 +27,7 @@ import (
// 1) Metadata is immutable after created. // 1) Metadata is immutable after created.
// 2) Metadata is checkpointed as containerd container label. // 2) Metadata is checkpointed as containerd container label.
// metadataVersion is current version of container metadata. // metadataVersion is current version of container metadata.
const metadataVersion = "v1" // nolint const metadataVersion = "v1" // nolint
// versionedMetadata is the internal versioned container metadata. // versionedMetadata is the internal versioned container metadata.
@ -58,6 +58,9 @@ type Metadata struct {
ImageRef string ImageRef string
// LogPath is the container log path. // LogPath is the container log path.
LogPath string LogPath string
// StopSignal is the system call signal that will be sent to the container to exit.
// TODO(random-liu): Add integration test for stop signal.
StopSignal string
} }
// MarshalJSON encodes Metadata into bytes in json format. // MarshalJSON encodes Metadata into bytes in json format.