diff --git a/docs/config.md b/docs/config.md index f2bb2879d..c33c0c0d4 100644 --- a/docs/config.md +++ b/docs/config.md @@ -77,6 +77,12 @@ version = 2 # when using containerd with Kubernetes <=1.11. disable_proc_mount = false + # default_oci_hooks is the filepath to an OCI runtime spec Hooks struct in json. + # see details and example: + # https://github.com/opencontainers/runtime-spec/blob/master/config.md#posix-platform-hooks + # ** Note: Overridden if set by CRI + default_oci_hooks = "" + # 'plugins."io.containerd.grpc.v1.cri".containerd' contains config related to containerd [plugins."io.containerd.grpc.v1.cri".containerd] diff --git a/pkg/config/config.go b/pkg/config/config.go index fabcdf35f..0c205615b 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -205,6 +205,10 @@ type PluginConfig struct { // DisableProcMount disables Kubernetes ProcMount support. This MUST be set to `true` // when using containerd with Kubernetes <=1.11. DisableProcMount bool `toml:"disable_proc_mount" json:"disableProcMount"` + // DefaultOCIHooks (optional) is a path to a json file that specifies a + // default OCI spec Hooks struct. ** Note: The any hooks set by default can be + // overridden if/when the hooks are set via the CRI. + DefaultOCIHooks string `toml:"default_oci_hooks" json:"defaultOCIHooks,omitempty"` } // X509KeyPairStreaming contains the x509 configuration for streaming diff --git a/pkg/containerd/opts/spec.go b/pkg/containerd/opts/spec.go index d4d030f8c..6b2746dca 100644 --- a/pkg/containerd/opts/spec.go +++ b/pkg/containerd/opts/spec.go @@ -101,6 +101,14 @@ func (m orderedMounts) parts(i int) int { return strings.Count(filepath.Clean(m[i].ContainerPath), string(os.PathSeparator)) } +// WithHooks sets or replaces the runtimespec.Hooks with the provided hooks +func WithHooks(hooks *runtimespec.Hooks) oci.SpecOpts { + return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { + s.Hooks = hooks + return nil + } +} + // WithAnnotation sets the provided annotation func WithAnnotation(k, v string) oci.SpecOpts { return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) error { diff --git a/pkg/server/container_create.go b/pkg/server/container_create.go index cfb5d6aad..4818125b7 100644 --- a/pkg/server/container_create.go +++ b/pkg/server/container_create.go @@ -17,6 +17,8 @@ limitations under the License. package server import ( + "encoding/json" + "io/ioutil" "path/filepath" "time" @@ -293,3 +295,19 @@ func runtimeSpec(id string, opts ...oci.SpecOpts) (*runtimespec.Spec, error) { } return spec, nil } + +// generateOCIHooks generates a runtimespec.Hooks struct from json in the passed in filepath. +func (c *criService) generateOCIHooks(profile string) (*runtimespec.Hooks, error) { + if profile == "" { + return nil, nil + } + hooks := &runtimespec.Hooks{} + f, err := ioutil.ReadFile(profile) + if err != nil { + return nil, err + } + if err := json.Unmarshal(f, hooks); err != nil { + return nil, err + } + return hooks, nil +} diff --git a/pkg/server/container_create_unix.go b/pkg/server/container_create_unix.go index d7993bf63..074b2e071 100644 --- a/pkg/server/container_create_unix.go +++ b/pkg/server/container_create_unix.go @@ -164,6 +164,15 @@ func (c *criService) containerSpec(id string, sandboxID string, sandboxPid uint3 specOpts = append(specOpts, oci.WithReadonlyPaths(securityContext.GetReadonlyPaths())) } + ociHooksProfile := c.config.DefaultOCIHooks + hooks, err := c.generateOCIHooks(ociHooksProfile) + if err != nil { // TODO (mikebrow): clean up prototype + return nil, errors.Wrapf(err, "failed to generate OCI hooks %+v", ociHooksProfile) + } + if hooks != nil { + specOpts = append(specOpts, customopts.WithHooks(hooks)) + } + if securityContext.GetPrivileged() { if !sandboxConfig.GetLinux().GetSecurityContext().GetPrivileged() { return nil, errors.New("no privileged container allowed in sandbox") diff --git a/pkg/server/container_create_windows.go b/pkg/server/container_create_windows.go index 799a5a039..a0316256d 100644 --- a/pkg/server/container_create_windows.go +++ b/pkg/server/container_create_windows.go @@ -27,6 +27,7 @@ import ( "github.com/containerd/cri/pkg/annotations" "github.com/containerd/cri/pkg/config" customopts "github.com/containerd/cri/pkg/containerd/opts" + "github.com/pkg/errors" ) // No container mounts for windows. @@ -86,6 +87,15 @@ func (c *criService) containerSpec(id string, sandboxID string, sandboxPid uint3 specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue)) } + ociHooksProfile := c.config.DefaultOCIHooks + hooks, err := c.generateOCIHooks(ociHooksProfile) + if err != nil { // TODO (mikebrow): clean up prototype + return nil, errors.Wrapf(err, "failed to generate OCI hooks %+v", ociHooksProfile) + } + if hooks != nil { + specOpts = append(specOpts, customopts.WithHooks(hooks)) + } + specOpts = append(specOpts, customopts.WithAnnotation(annotations.ContainerType, annotations.ContainerTypeContainer), customopts.WithAnnotation(annotations.SandboxID, sandboxID),