Skip to content
This repository was archived by the owner on Mar 9, 2022. It is now read-only.

Commit

Permalink
Annotations: Provide container metadata for VM based runtimes
Browse files Browse the repository at this point in the history
For hypervisor-based container runtimes (like Kata Containers, Clear Containers
or runv) a pod will be created in a VM and then create containers within the VM.

When a runtime is requested for container commands like create and start, both
the instal "pause" container and next containers need to be added to the pod
namespace (same VM).

A runtime does not know if it needs to create/start a VM or if it needs to add a
container to an already running VM pod.

This patch adds a way to provide this information through container annotations.
When starting a container or a sandbox, 2 annotations are added:

- type (Container or Sandbox)
- sandbox name

This allow to a VM based runtime to decide if they need to create a pod VM or
container within the VM pod.

Signed-off-by: Jose Carlos Venegas Munoz <[email protected]>
  • Loading branch information
jcvenegas committed Jan 17, 2018
1 parent 44cb406 commit b383b02
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 18 deletions.
32 changes: 32 additions & 0 deletions pkg/annotations/annotations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Copyright 2018 The Containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package annotations

// ContainerType values
const (
// ContainerTypeSandbox represents a pod sandbox container
ContainerTypeSandbox = "sandbox"

// ContainerTypeContainer represents a container running within a pod
ContainerTypeContainer = "container"

// ContainerType is the container type (sandbox or container) annotation
ContainerType = "io.kubernetes.cri.container-type"

// SandboxID is the sandbox ID annotation
SandboxID = "io.kubernetes.cri.sandbox-id"
)
9 changes: 7 additions & 2 deletions pkg/server/container_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"golang.org/x/sys/unix"
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"

"github.com/containerd/cri-containerd/pkg/annotations"
customopts "github.com/containerd/cri-containerd/pkg/containerd/opts"
cio "github.com/containerd/cri-containerd/pkg/server/io"
containerstore "github.com/containerd/cri-containerd/pkg/store/container"
Expand Down Expand Up @@ -143,10 +144,11 @@ func (c *criContainerdService) CreateContainer(ctx context.Context, r *runtime.C
// Generate container runtime spec.
mounts := c.generateContainerMounts(getSandboxRootDir(c.config.RootDir, sandboxID), config)

spec, err := c.generateContainerSpec(id, sandboxPid, config, sandboxConfig, &image.ImageSpec.Config, append(mounts, volumeMounts...))
spec, err := c.generateContainerSpec(id, sandboxID, sandboxPid, config, sandboxConfig, &image.ImageSpec.Config, append(mounts, volumeMounts...))
if err != nil {
return nil, fmt.Errorf("failed to generate container %q spec: %v", id, err)
}

glog.V(4).Infof("Container %q spec: %#+v", id, spew.NewFormatter(spec))

// Set snapshotter before any other options.
Expand Down Expand Up @@ -271,7 +273,7 @@ func (c *criContainerdService) CreateContainer(ctx context.Context, r *runtime.C
return &runtime.CreateContainerResponse{ContainerId: id}, nil
}

func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint32, config *runtime.ContainerConfig,
func (c *criContainerdService) generateContainerSpec(id string, sandboxID string, sandboxPid uint32, config *runtime.ContainerConfig,
sandboxConfig *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig, extraMounts []*runtime.Mount) (*runtimespec.Spec, error) {
// Creates a spec Generator with the default spec.
spec, err := defaultRuntimeSpec(id)
Expand Down Expand Up @@ -365,6 +367,9 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3
g.AddProcessAdditionalGid(uint32(group))
}

g.AddAnnotation(annotations.ContainerType, annotations.ContainerTypeContainer)
g.AddAnnotation(annotations.SandboxID, sandboxID)

return g.Spec(), nil
}

Expand Down
46 changes: 30 additions & 16 deletions pkg/server/container_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/stretchr/testify/require"
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"

"github.com/containerd/cri-containerd/pkg/annotations"
ostesting "github.com/containerd/cri-containerd/pkg/os/testing"
"github.com/containerd/cri-containerd/pkg/util"
)
Expand All @@ -56,7 +57,7 @@ func checkMount(t *testing.T, mounts []runtimespec.Mount, src, dest, typ string,
}

func getCreateContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandboxConfig,
*imagespec.ImageConfig, func(*testing.T, string, uint32, *runtimespec.Spec)) {
*imagespec.ImageConfig, func(*testing.T, string, string, uint32, *runtimespec.Spec)) {
config := &runtime.ContainerConfig{
Metadata: &runtime.ContainerMetadata{
Name: "test-name",
Expand Down Expand Up @@ -122,7 +123,7 @@ func getCreateContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandbox
Cmd: []string{"cmd"},
WorkingDir: "/workspace",
}
specCheck := func(t *testing.T, id string, sandboxPid uint32, spec *runtimespec.Spec) {
specCheck := func(t *testing.T, id string, sandboxID string, sandboxPid uint32, spec *runtimespec.Spec) {
assert.Equal(t, relativeRootfsPath, spec.Root.Path)
assert.Equal(t, []string{"test", "command", "test", "args"}, spec.Process.Args)
assert.Equal(t, "test-cwd", spec.Process.Cwd)
Expand Down Expand Up @@ -168,6 +169,13 @@ func getCreateContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandbox
Type: runtimespec.UTSNamespace,
Path: getUTSNamespace(sandboxPid),
})

t.Logf("Check PodSandbox annotations")
assert.Contains(t, spec.Annotations, annotations.SandboxID)
assert.EqualValues(t, spec.Annotations[annotations.SandboxID], sandboxID)

assert.Contains(t, spec.Annotations, annotations.ContainerType)
assert.EqualValues(t, spec.Annotations[annotations.ContainerType], annotations.ContainerTypeContainer)
}
return config, sandboxConfig, imageConfig, specCheck
}
Expand All @@ -177,13 +185,15 @@ func TestGeneralContainerSpec(t *testing.T) {
testPid := uint32(1234)
config, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
c := newTestCRIContainerdService()
spec, err := c.generateContainerSpec(testID, testPid, config, sandboxConfig, imageConfig, nil)
testSandboxID := "SandboxID"
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
require.NoError(t, err)
specCheck(t, testID, testPid, spec)
specCheck(t, testID, testSandboxID, testPid, spec)
}

func TestContainerCapabilities(t *testing.T) {
testID := "test-id"
testSandboxID := "SandboxID"
testPid := uint32(1234)
config, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
c := newTestCRIContainerdService()
Expand Down Expand Up @@ -231,9 +241,9 @@ func TestContainerCapabilities(t *testing.T) {
} {
t.Logf("TestCase %q", desc)
config.Linux.SecurityContext.Capabilities = test.capability
spec, err := c.generateContainerSpec(testID, testPid, config, sandboxConfig, imageConfig, nil)
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
require.NoError(t, err)
specCheck(t, testID, testPid, spec)
specCheck(t, testID, testSandboxID, testPid, spec)
t.Log(spec.Process.Capabilities.Bounding)
for _, include := range test.includes {
assert.Contains(t, spec.Process.Capabilities.Bounding, include)
Expand All @@ -252,14 +262,15 @@ func TestContainerCapabilities(t *testing.T) {

func TestContainerSpecTty(t *testing.T) {
testID := "test-id"
testSandboxID := "SandboxID"
testPid := uint32(1234)
config, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
c := newTestCRIContainerdService()
for _, tty := range []bool{true, false} {
config.Tty = tty
spec, err := c.generateContainerSpec(testID, testPid, config, sandboxConfig, imageConfig, nil)
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
require.NoError(t, err)
specCheck(t, testID, testPid, spec)
specCheck(t, testID, testSandboxID, testPid, spec)
assert.Equal(t, tty, spec.Process.Terminal)
if tty {
assert.Contains(t, spec.Process.Env, "TERM=xterm")
Expand All @@ -271,20 +282,22 @@ func TestContainerSpecTty(t *testing.T) {

func TestContainerSpecReadonlyRootfs(t *testing.T) {
testID := "test-id"
testSandboxID := "SandboxID"
testPid := uint32(1234)
config, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
c := newTestCRIContainerdService()
for _, readonly := range []bool{true, false} {
config.Linux.SecurityContext.ReadonlyRootfs = readonly
spec, err := c.generateContainerSpec(testID, testPid, config, sandboxConfig, imageConfig, nil)
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
require.NoError(t, err)
specCheck(t, testID, testPid, spec)
specCheck(t, testID, testSandboxID, testPid, spec)
assert.Equal(t, readonly, spec.Root.Readonly)
}
}

func TestContainerSpecWithExtraMounts(t *testing.T) {
testID := "test-id"
testSandboxID := "SandboxID"
testPid := uint32(1234)
config, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
c := newTestCRIContainerdService()
Expand All @@ -299,9 +312,9 @@ func TestContainerSpecWithExtraMounts(t *testing.T) {
HostPath: "test-host-path-extra",
Readonly: true,
}
spec, err := c.generateContainerSpec(testID, testPid, config, sandboxConfig, imageConfig, []*runtime.Mount{extraMount})
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, []*runtime.Mount{extraMount})
require.NoError(t, err)
specCheck(t, testID, testPid, spec)
specCheck(t, testID, testSandboxID, testPid, spec)
var mounts []runtimespec.Mount
for _, m := range spec.Mounts {
if m.Destination == "test-container-path" {
Expand Down Expand Up @@ -688,22 +701,23 @@ func TestMountPropagation(t *testing.T) {
func TestPidNamespace(t *testing.T) {
testID := "test-id"
testPid := uint32(1234)
testSandboxID := "SandboxID"
config, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
c := newTestCRIContainerdService()
t.Logf("should not set pid namespace when host pid is true")
config.Linux.SecurityContext.NamespaceOptions = &runtime.NamespaceOption{HostPid: true}
spec, err := c.generateContainerSpec(testID, testPid, config, sandboxConfig, imageConfig, nil)
spec, err := c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
require.NoError(t, err)
specCheck(t, testID, testPid, spec)
specCheck(t, testID, testSandboxID, testPid, spec)
for _, ns := range spec.Linux.Namespaces {
assert.NotEqual(t, ns.Type, runtimespec.PIDNamespace)
}

t.Logf("should set pid namespace when host pid is false")
config.Linux.SecurityContext.NamespaceOptions = &runtime.NamespaceOption{HostPid: false}
spec, err = c.generateContainerSpec(testID, testPid, config, sandboxConfig, imageConfig, nil)
spec, err = c.generateContainerSpec(testID, testSandboxID, testPid, config, sandboxConfig, imageConfig, nil)
require.NoError(t, err)
specCheck(t, testID, testPid, spec)
specCheck(t, testID, testSandboxID, testPid, spec)
assert.Contains(t, spec.Linux.Namespaces, runtimespec.LinuxNamespace{
Type: runtimespec.PIDNamespace,
})
Expand Down
4 changes: 4 additions & 0 deletions pkg/server/sandbox_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"golang.org/x/sys/unix"
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"

"github.com/containerd/cri-containerd/pkg/annotations"
customopts "github.com/containerd/cri-containerd/pkg/containerd/opts"
sandboxstore "github.com/containerd/cri-containerd/pkg/store/sandbox"
"github.com/containerd/cri-containerd/pkg/util"
Expand Down Expand Up @@ -331,6 +332,9 @@ func (c *criContainerdService) generateSandboxContainerSpec(id string, config *r
g.SetLinuxResourcesCPUShares(uint64(defaultSandboxCPUshares))
g.SetProcessOOMScoreAdj(int(defaultSandboxOOMAdj))

g.AddAnnotation(annotations.ContainerType, annotations.ContainerTypeSandbox)
g.AddAnnotation(annotations.SandboxID, id)

return g.Spec(), nil
}

Expand Down
8 changes: 8 additions & 0 deletions pkg/server/sandbox_run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"os"
"testing"

"github.com/containerd/cri-containerd/pkg/annotations"
"github.com/containerd/typeurl"
"github.com/cri-o/ocicni/pkg/ocicni"
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
Expand Down Expand Up @@ -64,6 +65,13 @@ func getRunPodSandboxTestData() (*runtime.PodSandboxConfig, *imagespec.ImageConf
assert.Equal(t, "/workspace", spec.Process.Cwd)
assert.EqualValues(t, *spec.Linux.Resources.CPU.Shares, defaultSandboxCPUshares)
assert.EqualValues(t, *spec.Process.OOMScoreAdj, defaultSandboxOOMAdj)

t.Logf("Check PodSandbox annotations")
assert.Contains(t, spec.Annotations, annotations.SandboxID)
assert.EqualValues(t, spec.Annotations[annotations.SandboxID], id)

assert.Contains(t, spec.Annotations, annotations.ContainerType)
assert.EqualValues(t, spec.Annotations[annotations.ContainerType], annotations.ContainerTypeSandbox)
}
return config, imageConfig, specCheck
}
Expand Down

0 comments on commit b383b02

Please sign in to comment.