From 8ab1d449678af34cad379fb61a33a5bd11fabe03 Mon Sep 17 00:00:00 2001 From: Maksym Pavlenko Date: Tue, 6 Dec 2022 09:41:01 -0800 Subject: [PATCH] Pass runtime configuration as TOML blob Signed-off-by: Maksym Pavlenko --- pkg/cri/sbserver/helpers.go | 10 +++++ runtime/v2/runc/manager/manager_linux.go | 52 +++++++++--------------- runtime/v2/shim/util.go | 39 ++++++++++++++++++ 3 files changed, 68 insertions(+), 33 deletions(-) diff --git a/pkg/cri/sbserver/helpers.go b/pkg/cri/sbserver/helpers.go index ca3b4aa71..07491c75e 100644 --- a/pkg/cri/sbserver/helpers.go +++ b/pkg/cri/sbserver/helpers.go @@ -348,6 +348,16 @@ func generateRuntimeOptions(r criconfig.Runtime, c criconfig.Config) (interface{ if err := optionsTree.Unmarshal(options); err != nil { return nil, err } + + // For generic configuration, if no config path specified (preserving old behavior), pass + // the whole TOML configuration section to the runtime. + if runtimeOpts, ok := options.(*runtimeoptions.Options); ok && runtimeOpts.ConfigPath == "" { + runtimeOpts.ConfigBody, err = optionsTree.Marshal() + if err != nil { + return nil, fmt.Errorf("failed to marshal TOML blob for runtime %q: %v", r.Type, err) + } + } + return options, nil } diff --git a/runtime/v2/runc/manager/manager_linux.go b/runtime/v2/runc/manager/manager_linux.go index 3c5d8054c..8699573ab 100644 --- a/runtime/v2/runc/manager/manager_linux.go +++ b/runtime/v2/runc/manager/manager_linux.go @@ -20,7 +20,6 @@ import ( "context" "encoding/json" "fmt" - "io" "os" "path/filepath" goruntime "runtime" @@ -35,13 +34,10 @@ import ( "github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/pkg/process" "github.com/containerd/containerd/pkg/schedcore" - "github.com/containerd/containerd/protobuf/proto" - ptypes "github.com/containerd/containerd/protobuf/types" "github.com/containerd/containerd/runtime/v2/runc" "github.com/containerd/containerd/runtime/v2/runc/options" "github.com/containerd/containerd/runtime/v2/shim" runcC "github.com/containerd/go-runc" - "github.com/containerd/typeurl" exec "golang.org/x/sys/execabs" "golang.org/x/sys/unix" ) @@ -200,39 +196,29 @@ func (manager) Start(ctx context.Context, id string, opts shim.StartOpts) (_ str }() // make sure to wait after start go cmd.Wait() - if data, err := io.ReadAll(os.Stdin); err == nil { - if len(data) > 0 { - var any ptypes.Any - if err := proto.Unmarshal(data, &any); err != nil { - return "", err - } - v, err := typeurl.UnmarshalAny(&any) - if err != nil { - return "", err - } - if opts, ok := v.(*options.Options); ok { - if opts.ShimCgroup != "" { - if cgroups.Mode() == cgroups.Unified { - cg, err := cgroupsv2.Load(opts.ShimCgroup) - if err != nil { - return "", fmt.Errorf("failed to load cgroup %s: %w", opts.ShimCgroup, err) - } - if err := cg.AddProc(uint64(cmd.Process.Pid)); err != nil { - return "", fmt.Errorf("failed to join cgroup %s: %w", opts.ShimCgroup, err) - } - } else { - cg, err := cgroup1.Load(cgroup1.StaticPath(opts.ShimCgroup)) - if err != nil { - return "", fmt.Errorf("failed to load cgroup %s: %w", opts.ShimCgroup, err) - } - if err := cg.AddProc(uint64(cmd.Process.Pid)); err != nil { - return "", fmt.Errorf("failed to join cgroup %s: %w", opts.ShimCgroup, err) - } - } + + if opts, err := shim.ReadRuntimeOptions[*options.Options](os.Stdin); err == nil { + if opts.ShimCgroup != "" { + if cgroups.Mode() == cgroups.Unified { + cg, err := cgroupsv2.Load(opts.ShimCgroup) + if err != nil { + return "", fmt.Errorf("failed to load cgroup %s: %w", opts.ShimCgroup, err) + } + if err := cg.AddProc(uint64(cmd.Process.Pid)); err != nil { + return "", fmt.Errorf("failed to join cgroup %s: %w", opts.ShimCgroup, err) + } + } else { + cg, err := cgroup1.Load(cgroup1.StaticPath(opts.ShimCgroup)) + if err != nil { + return "", fmt.Errorf("failed to load cgroup %s: %w", opts.ShimCgroup, err) + } + if err := cg.AddProc(uint64(cmd.Process.Pid)); err != nil { + return "", fmt.Errorf("failed to join cgroup %s: %w", opts.ShimCgroup, err) } } } } + if err := shim.AdjustOOMScore(cmd.Process.Pid); err != nil { return "", fmt.Errorf("failed to adjust OOM score for shim: %w", err) } diff --git a/runtime/v2/shim/util.go b/runtime/v2/shim/util.go index d1cd47946..34d0fb33e 100644 --- a/runtime/v2/shim/util.go +++ b/runtime/v2/shim/util.go @@ -21,16 +21,20 @@ import ( "context" "errors" "fmt" + "io" "net" "os" "path/filepath" "strings" "time" + "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/protobuf/proto" "github.com/containerd/containerd/protobuf/types" + ptypes "github.com/containerd/containerd/protobuf/types" "github.com/containerd/ttrpc" + "github.com/containerd/typeurl" exec "golang.org/x/sys/execabs" ) @@ -169,6 +173,41 @@ func ReadAddress(path string) (string, error) { return string(data), nil } +// ReadRuntimeOptions reads config bytes from io.Reader and unmarshals it into the provided type. +// The type must be registered with typeurl. +// +// The function will return ErrNotFound, if the config is not provided. +// And ErrInvalidArgument, if unable to cast the config to the provided type T. +func ReadRuntimeOptions[T any](reader io.Reader) (T, error) { + var config T + + data, err := io.ReadAll(reader) + if err != nil { + return config, fmt.Errorf("failed to read config bytes from stdin: %w", err) + } + + if len(data) == 0 { + return config, errdefs.ErrNotFound + } + + var any ptypes.Any + if err := proto.Unmarshal(data, &any); err != nil { + return config, err + } + + v, err := typeurl.UnmarshalAny(&any) + if err != nil { + return config, err + } + + config, ok := v.(T) + if !ok { + return config, fmt.Errorf("invalid type %T: %w", v, errdefs.ErrInvalidArgument) + } + + return config, nil +} + // chainUnaryServerInterceptors creates a single ttrpc server interceptor from // a chain of many interceptors executed from first to last. func chainUnaryServerInterceptors(interceptors ...ttrpc.UnaryServerInterceptor) ttrpc.UnaryServerInterceptor {