Skip to content

Commit 96e1c6d

Browse files
committed
feature: support containerd shim v2
Signed-off-by: zhuangqh <[email protected]>
1 parent a07f1ba commit 96e1c6d

File tree

8 files changed

+121
-51
lines changed

8 files changed

+121
-51
lines changed

apis/swagger.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2011,6 +2011,13 @@ definitions:
20112011
and SELinux.
20122012
type: "object"
20132013
properties:
2014+
type:
2015+
description: The runtime type used in containerd.
2016+
type: "string"
2017+
example: "io.containerd.runtime.v1.linux"
2018+
options:
2019+
description: Options are config options for specific runtime.
2020+
x-go-type: "interface{}"
20142021
path:
20152022
description: |
20162023
Name and, optional, path, of the OCI executable binary.
@@ -2022,6 +2029,7 @@ definitions:
20222029
runtimeArgs:
20232030
description: |
20242031
List of command-line arguments to pass to the runtime when invoked.
2032+
DEPRECATED: Use Options instead. Remove when shim v1 is deprecated.
20252033
type: "array"
20262034
x-nullable: true
20272035
items:
@@ -2452,6 +2460,12 @@ definitions:
24522460
Runtime:
24532461
type: "string"
24542462
description: "Runtime to use with this container."
2463+
RuntimeType:
2464+
type: "string"
2465+
description: "The runtime type used in containerd."
2466+
RuntimeOptions:
2467+
description: "Runtime specific information."
2468+
x-go-type: "interface{}"
24552469
# Applicable to Windows
24562470
ConsoleSize:
24572471
type: "array"

apis/types/host_config.go

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apis/types/runtime.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ctrd/container.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"encoding/json"
66
"fmt"
77
"io"
8-
"path"
98
"runtime"
109
"strings"
1110
"sync"
@@ -26,14 +25,15 @@ import (
2625
"github.com/containerd/containerd/images"
2726
"github.com/containerd/containerd/leases"
2827
"github.com/containerd/containerd/oci"
29-
"github.com/containerd/containerd/runtime/linux/runctypes"
3028
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
3129
"github.com/pkg/errors"
3230
"github.com/sirupsen/logrus"
3331
)
3432

3533
var (
36-
runtimeRoot = "/run"
34+
RuntimeRoot = "/run"
35+
RuntimeTypeRuncV1 = fmt.Sprintf("io.containerd.runtime.v1.%s", runtime.GOOS)
36+
RuntimeTypeRuncV2 = "io.containerd.runc.v1"
3737
)
3838

3939
type containerPack struct {
@@ -539,11 +539,7 @@ func (c *Client) createContainer(ctx context.Context, ref, id, checkpointDir str
539539
options := []containerd.NewContainerOpts{
540540
containerd.WithSnapshotter(CurrentSnapshotterName(ctx)),
541541
containerd.WithContainerLabels(container.Labels),
542-
containerd.WithRuntime(fmt.Sprintf("io.containerd.runtime.v1.%s", runtime.GOOS), &runctypes.RuncOptions{
543-
Runtime: container.Runtime,
544-
RuntimeRoot: path.Join(runtimeRoot, container.Runtime),
545-
SystemdCgroup: container.UseSystemd,
546-
}),
542+
containerd.WithRuntime(container.RuntimeType, container.RuntimeOptions),
547543
}
548544

549545
rootFSPath := "rootfs"

ctrd/container_types.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ import (
1111
// then create container by specifying the snapshot;
1212
// The other is create container by specify container rootfs, we use `RootFSProvided` flag to mark it,
1313
type Container struct {
14-
ID string
15-
Image string
16-
Runtime string
17-
Labels map[string]string
18-
IO *containerio.IO
19-
Spec *specs.Spec
20-
SnapshotID string
14+
ID string
15+
Image string
16+
RuntimeType string
17+
RuntimeOptions interface{}
18+
Labels map[string]string
19+
IO *containerio.IO
20+
Spec *specs.Spec
21+
SnapshotID string
2122

2223
// BaseFS is rootfs used by containerd container
2324
BaseFS string

daemon/daemon_utils.go

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
package daemon
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"io/ioutil"
67
"os"
78
"path/filepath"
89
"strings"
910

1011
"github.com/alibaba/pouch/apis/types"
12+
"github.com/alibaba/pouch/ctrd"
13+
14+
"github.com/containerd/containerd/runtime/linux/runctypes"
15+
runcoptions "github.com/containerd/containerd/runtime/v2/runc/options"
1116
)
1217

1318
var (
@@ -20,6 +25,7 @@ var (
2025
// we will make a executable script as a path, or runtime.path is record as path.
2126
// NOTE: containerd not support runtime args directly, so we make executable
2227
// script include runtime path and args as a runtime execute binary.
28+
// this solution would be deprecated after shim v1 is deprecated.
2329
func initialRuntime(baseDir string, runtimes map[string]types.Runtime) error {
2430
dir := filepath.Join(baseDir, runtimeDir)
2531

@@ -35,20 +41,48 @@ func initialRuntime(baseDir string, runtimes map[string]types.Runtime) error {
3541

3642
// create script for runtime who has args
3743
for name, r := range runtimes {
38-
if len(r.RuntimeArgs) == 0 {
39-
continue
40-
}
41-
42-
script := filepath.Join(dir, name)
4344
if r.Path == "" {
4445
r.Path = name
4546
}
46-
data := fmt.Sprintf("#!/bin/sh\n%s %s $@\n", r.Path, strings.Join(r.RuntimeArgs, " "))
4747

48-
if err := ioutil.WriteFile(script, []byte(data), runtimeScriptPerm); err != nil {
49-
return fmt.Errorf("failed to create runtime script %s: %s", script, err)
48+
// setup a fake path
49+
if len(r.RuntimeArgs) != 0 {
50+
data := fmt.Sprintf("#!/bin/sh\n%s %s $@\n", r.Path, strings.Join(r.RuntimeArgs, " "))
51+
r.Path = filepath.Join(dir, name)
52+
53+
if err := ioutil.WriteFile(r.Path, []byte(data), runtimeScriptPerm); err != nil {
54+
return fmt.Errorf("failed to create runtime script %s: %s", r.Path, err)
55+
}
5056
}
57+
58+
if r.Type == "" {
59+
r.Type = ctrd.RuntimeTypeRuncV1
60+
}
61+
62+
// convert general json map to specific options type
63+
b, err := json.Marshal(r.Options)
64+
if err != nil {
65+
return fmt.Errorf("failed to marshal options, runtime: %s: %v", name, err)
66+
}
67+
options := getRuntimeOptionsType(r.Type)
68+
if err := json.Unmarshal(b, options); err != nil {
69+
return fmt.Errorf("failed to unmarshal to type %+v: %v", options, err)
70+
}
71+
72+
r.Options = options
5173
}
5274

5375
return nil
5476
}
77+
78+
func getRuntimeOptionsType(runtimeType string) interface{} {
79+
switch runtimeType {
80+
case ctrd.RuntimeTypeRuncV2:
81+
return &runcoptions.Options{}
82+
// using type RuncOptions for runc v1 shim or other v2 shim.
83+
// TODO: using more general options type if containerd does
84+
// or support more v2 shim options type.
85+
default:
86+
return &runctypes.RuncOptions{}
87+
}
88+
}

daemon/mgr/container.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -400,9 +400,12 @@ func (mgr *ContainerManager) Create(ctx context.Context, name string, config *ty
400400
config.HostConfig.Runtime = mgr.Config.DefaultRuntime
401401
}
402402

403-
if _, exist := mgr.Config.Runtimes[config.HostConfig.Runtime]; !exist {
403+
runtimeConfig, err := mgr.getRuntime(config.HostConfig.Runtime)
404+
if err != nil {
404405
return nil, errors.Wrapf(errtypes.ErrInvalidParam, "unknown runtime %s", config.HostConfig.Runtime)
405406
}
407+
config.HostConfig.RuntimeOptions = runtimeConfig.Options
408+
config.HostConfig.RuntimeType = runtimeConfig.Type
406409

407410
snapID := id
408411
// create a snapshot with image.
@@ -780,17 +783,13 @@ func (mgr *ContainerManager) createContainerdContainer(ctx context.Context, c *C
780783
// set container's LogPath
781784
mgr.SetContainerLogPath(c)
782785

783-
runtime, err := mgr.getRuntime(c.HostConfig.Runtime)
784-
if err != nil {
785-
return err
786-
}
787-
788786
c.Lock()
789787
ctrdContainer := &ctrd.Container{
790788
ID: c.ID,
791789
Image: c.Config.Image,
792790
Labels: c.Config.Labels,
793-
Runtime: runtime,
791+
RuntimeType: c.HostConfig.RuntimeType,
792+
RuntimeOptions: c.HostConfig.RuntimeOptions,
794793
Spec: sw.s,
795794
IO: mgr.IOs.Get(c.ID),
796795
RootFSProvided: c.RootFSProvided,
@@ -1919,7 +1918,7 @@ func (mgr *ContainerManager) setBaseFS(ctx context.Context, c *Container) {
19191918

19201919
// io.containerd.runtime.v1.linux as a const used by runc
19211920
c.Lock()
1922-
c.BaseFS = filepath.Join(mgr.Config.HomeDir, "containerd/state", "io.containerd.runtime.v1.linux", mgr.Config.DefaultNamespace, c.ID, "rootfs")
1921+
c.BaseFS = filepath.Join(mgr.Config.HomeDir, "containerd/state", c.HostConfig.RuntimeType, mgr.Config.DefaultNamespace, c.ID, "rootfs")
19231922
c.Unlock()
19241923
}
19251924

daemon/mgr/container_utils.go

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,20 @@ import (
44
"encoding/json"
55
"fmt"
66
"io/ioutil"
7+
"path"
78
"path/filepath"
8-
"runtime"
99
"strconv"
1010
"strings"
1111

1212
"github.com/alibaba/pouch/apis/opts"
1313
"github.com/alibaba/pouch/apis/types"
14+
"github.com/alibaba/pouch/ctrd"
1415
networktypes "github.com/alibaba/pouch/network/types"
1516
"github.com/alibaba/pouch/pkg/errtypes"
1617
"github.com/alibaba/pouch/pkg/meta"
1718
"github.com/alibaba/pouch/pkg/randomid"
1819

20+
"github.com/containerd/containerd/runtime/linux/runctypes"
1921
specs "github.com/opencontainers/runtime-spec/specs-go"
2022
"github.com/opencontainers/selinux/go-selinux/label"
2123
"github.com/pkg/errors"
@@ -105,35 +107,30 @@ func (mgr *ContainerManager) generateName(id string) string {
105107
return name
106108
}
107109

108-
// getRuntime returns runtime real path.
109-
// TODO(huamin): do we need validate runtime is executable ?
110-
func (mgr *ContainerManager) getRuntime(runtime string) (string, error) {
110+
// getRuntime returns runtime config and generate options.
111+
func (mgr *ContainerManager) getRuntime(runtime string) (*types.Runtime, error) {
111112
r, exist := mgr.Config.Runtimes[runtime]
112113
if !exist {
113-
return "", fmt.Errorf("failed to find runtime %s in daemon config", runtime)
114+
return nil, fmt.Errorf("failed to find runtime %s in daemon config", runtime)
114115
}
115116

116-
// it is ok to use runtime name as a path.
117-
rPath := runtime
118-
// generally speaking, path is not be empty, but we not forbid empty path
119-
// in config set, since name can be a path too.
120-
if r.Path != "" {
121-
rPath = r.Path
117+
switch o := r.Options.(type) {
118+
case *runctypes.RuncOptions:
119+
o.Runtime = r.Path
120+
o.RuntimeRoot = ctrd.RuntimeRoot
121+
o.SystemdCgroup = mgr.Config.UseSystemd()
122+
r.Options = o
123+
// TODO: support other v2 shim options.
124+
default:
125+
return nil, fmt.Errorf("unsupported option type")
122126
}
123127

124-
// if Runtime has args, use script path as runtime path.
125-
if len(r.RuntimeArgs) > 0 {
126-
rPath = filepath.Join(mgr.Config.HomeDir, RuntimeDir, runtime)
127-
}
128-
129-
return rPath, nil
128+
return &r, nil
130129
}
131130

132131
// getContainerSpec returns container runtime spec, unmarshal spec from config.json
133-
// TODO: when runtime type can be specified, it need fix
134132
func (mgr *ContainerManager) getContainerSpec(c *Container) (*specs.Spec, error) {
135-
runtimeType := fmt.Sprintf("io.containerd.runtime.v1.%s", runtime.GOOS)
136-
configFile := filepath.Join(mgr.Config.HomeDir, "containerd/state", runtimeType, mgr.Config.DefaultNamespace, c.ID, "config.json")
133+
configFile := filepath.Join(path.Dir(c.BaseFS), "config.json")
137134
var spec specs.Spec
138135
data, err := ioutil.ReadFile(configFile)
139136
if err != nil {

0 commit comments

Comments
 (0)