Skip to content

Commit c085fac

Browse files
committed
Move sandbox start behind controller
Signed-off-by: Maksym Pavlenko <[email protected]>
1 parent f51014f commit c085fac

23 files changed

Lines changed: 3885 additions & 188 deletions

pkg/cri/sbserver/helpers.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,9 @@ func getUserFromImage(user string) (*int64, string) {
219219
return &uid, ""
220220
}
221221

222-
// ensureImageExists returns corresponding metadata of the image reference, if image is not
222+
// EnsureImageExists returns corresponding metadata of the image reference, if image is not
223223
// pulled yet, the function will pull the image.
224-
func (c *criService) ensureImageExists(ctx context.Context, ref string, config *runtime.PodSandboxConfig) (*imagestore.Image, error) {
224+
func (c *criService) EnsureImageExists(ctx context.Context, ref string, config *runtime.PodSandboxConfig) (*imagestore.Image, error) {
225225
image, err := c.localResolve(ref)
226226
if err != nil && !errdefs.IsNotFound(err) {
227227
return nil, fmt.Errorf("failed to get image %q: %w", ref, err)
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// These are copied from container_create_linux.go and should be consolidated later.
18+
19+
package podsandbox
20+
21+
import (
22+
"errors"
23+
"fmt"
24+
"strconv"
25+
"strings"
26+
27+
"github.com/containerd/containerd/contrib/seccomp"
28+
"github.com/containerd/containerd/oci"
29+
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
30+
)
31+
32+
const (
33+
// profileNamePrefix is the prefix for loading profiles on a localhost. Eg. AppArmor localhost/profileName.
34+
profileNamePrefix = "localhost/" // TODO (mikebrow): get localhost/ & runtime/default from CRI kubernetes/kubernetes#51747
35+
// runtimeDefault indicates that we should use or create a runtime default profile.
36+
runtimeDefault = "runtime/default"
37+
// dockerDefault indicates that we should use or create a docker default profile.
38+
dockerDefault = "docker/default"
39+
// unconfinedProfile is a string indicating one should run a pod/containerd without a security profile
40+
unconfinedProfile = "unconfined"
41+
)
42+
43+
// generateSeccompSpecOpts generates containerd SpecOpts for seccomp.
44+
func (c *Controller) generateSeccompSpecOpts(sp *runtime.SecurityProfile, privileged, seccompEnabled bool) (oci.SpecOpts, error) {
45+
if privileged {
46+
// Do not set seccomp profile when container is privileged
47+
return nil, nil
48+
}
49+
if !seccompEnabled {
50+
if sp != nil {
51+
if sp.ProfileType != runtime.SecurityProfile_Unconfined {
52+
return nil, errors.New("seccomp is not supported")
53+
}
54+
}
55+
return nil, nil
56+
}
57+
58+
if sp == nil {
59+
return nil, nil
60+
}
61+
62+
if sp.ProfileType != runtime.SecurityProfile_Localhost && sp.LocalhostRef != "" {
63+
return nil, errors.New("seccomp config invalid LocalhostRef must only be set if ProfileType is Localhost")
64+
}
65+
switch sp.ProfileType {
66+
case runtime.SecurityProfile_Unconfined:
67+
// Do not set seccomp profile.
68+
return nil, nil
69+
case runtime.SecurityProfile_RuntimeDefault:
70+
return seccomp.WithDefaultProfile(), nil
71+
case runtime.SecurityProfile_Localhost:
72+
// trimming the localhost/ prefix just in case even though it should not
73+
// be necessary with the new SecurityProfile struct
74+
return seccomp.WithProfile(strings.TrimPrefix(sp.LocalhostRef, profileNamePrefix)), nil
75+
default:
76+
return nil, errors.New("seccomp unknown ProfileType")
77+
}
78+
}
79+
80+
func generateSeccompSecurityProfile(profilePath string, unsetProfilePath string) (*runtime.SecurityProfile, error) {
81+
if profilePath != "" {
82+
return generateSecurityProfile(profilePath)
83+
}
84+
if unsetProfilePath != "" {
85+
return generateSecurityProfile(unsetProfilePath)
86+
}
87+
return nil, nil
88+
}
89+
90+
func generateSecurityProfile(profilePath string) (*runtime.SecurityProfile, error) {
91+
switch profilePath {
92+
case runtimeDefault, dockerDefault, "":
93+
return &runtime.SecurityProfile{
94+
ProfileType: runtime.SecurityProfile_RuntimeDefault,
95+
}, nil
96+
case unconfinedProfile:
97+
return &runtime.SecurityProfile{
98+
ProfileType: runtime.SecurityProfile_Unconfined,
99+
}, nil
100+
default:
101+
// Require and Trim default profile name prefix
102+
if !strings.HasPrefix(profilePath, profileNamePrefix) {
103+
return nil, fmt.Errorf("invalid profile %q", profilePath)
104+
}
105+
return &runtime.SecurityProfile{
106+
ProfileType: runtime.SecurityProfile_Localhost,
107+
LocalhostRef: strings.TrimPrefix(profilePath, profileNamePrefix),
108+
}, nil
109+
}
110+
}
111+
112+
// generateUserString generates valid user string based on OCI Image Spec
113+
// v1.0.0.
114+
//
115+
// CRI defines that the following combinations are valid:
116+
//
117+
// (none) -> ""
118+
// username -> username
119+
// username, uid -> username
120+
// username, uid, gid -> username:gid
121+
// username, gid -> username:gid
122+
// uid -> uid
123+
// uid, gid -> uid:gid
124+
// gid -> error
125+
//
126+
// TODO(random-liu): Add group name support in CRI.
127+
func generateUserString(username string, uid, gid *runtime.Int64Value) (string, error) {
128+
var userstr, groupstr string
129+
if uid != nil {
130+
userstr = strconv.FormatInt(uid.GetValue(), 10)
131+
}
132+
if username != "" {
133+
userstr = username
134+
}
135+
if gid != nil {
136+
groupstr = strconv.FormatInt(gid.GetValue(), 10)
137+
}
138+
if userstr == "" {
139+
if groupstr != "" {
140+
return "", fmt.Errorf("user group %q is specified without user", groupstr)
141+
}
142+
return "", nil
143+
}
144+
if groupstr != "" {
145+
userstr = userstr + ":" + groupstr
146+
}
147+
return userstr, nil
148+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package podsandbox
18+
19+
import (
20+
"context"
21+
22+
"github.com/containerd/containerd"
23+
api "github.com/containerd/containerd/api/services/sandbox/v1"
24+
"github.com/containerd/containerd/oci"
25+
criconfig "github.com/containerd/containerd/pkg/cri/config"
26+
imagestore "github.com/containerd/containerd/pkg/cri/store/image"
27+
sandboxstore "github.com/containerd/containerd/pkg/cri/store/sandbox"
28+
osinterface "github.com/containerd/containerd/pkg/os"
29+
"github.com/containerd/containerd/sandbox"
30+
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
31+
)
32+
33+
// CRIService interface contains things required by controller, but not yet refactored from criService.
34+
// This will be removed in subsequent iterations.
35+
type CRIService interface {
36+
EnsureImageExists(ctx context.Context, ref string, config *runtime.PodSandboxConfig) (*imagestore.Image, error)
37+
38+
StartSandboxExitMonitor(ctx context.Context, id string, pid uint32, exitCh <-chan containerd.ExitStatus) <-chan struct{}
39+
}
40+
41+
type Controller struct {
42+
// config contains all configurations.
43+
config criconfig.Config
44+
// client is an instance of the containerd client
45+
client *containerd.Client
46+
// sandboxStore stores all resources associated with sandboxes.
47+
sandboxStore *sandboxstore.Store
48+
// os is an interface for all required os operations.
49+
os osinterface.OS
50+
// cri is CRI service that provides missing gaps needed by controller.
51+
cri CRIService
52+
// baseOCISpecs contains cached OCI specs loaded via `Runtime.BaseRuntimeSpec`
53+
baseOCISpecs map[string]*oci.Spec
54+
}
55+
56+
func New(
57+
config criconfig.Config,
58+
client *containerd.Client,
59+
sandboxStore *sandboxstore.Store,
60+
os osinterface.OS,
61+
cri CRIService,
62+
baseOCISpecs map[string]*oci.Spec,
63+
) *Controller {
64+
return &Controller{
65+
config: config,
66+
client: client,
67+
sandboxStore: sandboxStore,
68+
os: os,
69+
cri: cri,
70+
baseOCISpecs: baseOCISpecs,
71+
}
72+
}
73+
74+
var _ sandbox.Controller = (*Controller)(nil)
75+
76+
func (c *Controller) Shutdown(ctx context.Context, sandboxID string) error {
77+
panic("implement me")
78+
}
79+
80+
func (c *Controller) Wait(ctx context.Context, sandboxID string) (*api.ControllerWaitResponse, error) {
81+
panic("implement me")
82+
}
83+
84+
func (c *Controller) Status(ctx context.Context, sandboxID string) (*api.ControllerStatusResponse, error) {
85+
panic("implement me")
86+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package podsandbox
18+
19+
import (
20+
criconfig "github.com/containerd/containerd/pkg/cri/config"
21+
"github.com/containerd/containerd/pkg/cri/store/label"
22+
sandboxstore "github.com/containerd/containerd/pkg/cri/store/sandbox"
23+
ostesting "github.com/containerd/containerd/pkg/os/testing"
24+
)
25+
26+
const (
27+
testRootDir = "/test/root"
28+
testStateDir = "/test/state"
29+
// Use an image id as test sandbox image to avoid image name resolve.
30+
// TODO(random-liu): Change this to image name after we have complete image
31+
// management unit test framework.
32+
testSandboxImage = "sha256:c75bebcdd211f41b3a460c7bf82970ed6c75acaab9cd4c9a4e125b03ca113798"
33+
)
34+
35+
var testConfig = criconfig.Config{
36+
RootDir: testRootDir,
37+
StateDir: testStateDir,
38+
PluginConfig: criconfig.PluginConfig{
39+
SandboxImage: testSandboxImage,
40+
TolerateMissingHugetlbController: true,
41+
},
42+
}
43+
44+
// newControllerService creates a fake criService for test.
45+
func newControllerService() *Controller {
46+
labels := label.NewStore()
47+
return &Controller{
48+
config: testConfig,
49+
os: ostesting.NewFakeOS(),
50+
sandboxStore: sandboxstore.NewStore(labels),
51+
}
52+
}

0 commit comments

Comments
 (0)