mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-16 00:16:52 +00:00
sandbox: Join cgroup sandbox on create.
When a new sandbox is created, join to its cgroup path this will create all proxy, shim, etc in the sandbox cgroup. Fixes: #1879 Signed-off-by: Jose Carlos Venegas Munoz <jose.carlos.venegas.munoz@intel.com>
This commit is contained in:
parent
2fcb8bb4d8
commit
074418f56b
@ -75,6 +75,18 @@ func createSandboxFromConfig(ctx context.Context, sandboxConfig SandboxConfig, f
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Move runtime to sandbox cgroup so all process are created there.
|
||||
if s.config.SandboxCgroupOnly {
|
||||
if err := s.setupSandboxCgroupOnly(); err != nil {
|
||||
return nil, err
|
||||
|
||||
}
|
||||
if err := s.joinSandboxCgroup(); err != nil {
|
||||
return nil, err
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup sandbox resources in case of any failure
|
||||
defer func() {
|
||||
if err != nil {
|
||||
|
@ -7,11 +7,13 @@ package virtcontainers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
@ -2069,3 +2071,72 @@ func (s *Sandbox) cpuResources() *specs.LinuxCPU {
|
||||
|
||||
return validCPUResources(cpu)
|
||||
}
|
||||
|
||||
// setupSandboxCgroup creates sandbox cgroups for the sandbox config
|
||||
func (s *Sandbox) setupSandboxCgroupOnly() error {
|
||||
var PodSandboxConfig *ContainerConfig
|
||||
|
||||
if s.config == nil {
|
||||
return fmt.Errorf("Sandbox config is nil")
|
||||
}
|
||||
|
||||
for _, cConfig := range s.config.Containers {
|
||||
if cConfig.Annotations[annotations.ContainerTypeKey] == string(PodSandbox) {
|
||||
PodSandboxConfig = &cConfig
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if PodSandboxConfig == nil {
|
||||
return fmt.Errorf("Failed to find cgroup path for Sandbox: Container of type '%s' not found", PodSandbox)
|
||||
}
|
||||
|
||||
configJSON, ok := PodSandboxConfig.Annotations[annotations.ConfigJSONKey]
|
||||
if !ok {
|
||||
return fmt.Errorf("Could not find json config in annotations for container '%s'", PodSandboxConfig.ID)
|
||||
}
|
||||
|
||||
var spec specs.Spec
|
||||
if err := json.Unmarshal([]byte(configJSON), &spec); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if spec.Linux == nil {
|
||||
// Cgroup path is optional, just skip the setup
|
||||
return nil
|
||||
}
|
||||
validContainerCgroup := utils.ValidCgroupPath(spec.Linux.CgroupsPath)
|
||||
|
||||
// Use the parent cgroup of the container sandbox as the sandbox cgroup
|
||||
|
||||
s.state.CgroupPath = filepath.Join(filepath.Dir(validContainerCgroup), cgroupKataPrefix+"_"+PodSandboxConfig.ID)
|
||||
_, err := cgroupsNewFunc(cgroups.V1, cgroups.StaticPath(s.state.CgroupPath), &specs.LinuxResources{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not create sandbox cgroup in %v: %v", s.state.CgroupPath, err)
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// joinSandboxCgroup adds the runtime PID to the sandbox defined in sandboxes' CgroupPath
|
||||
func (s *Sandbox) joinSandboxCgroup() error {
|
||||
|
||||
if s.state.CgroupPath == "" {
|
||||
// This is an optional value
|
||||
return nil
|
||||
}
|
||||
|
||||
cgroup, err := cgroupsLoadFunc(cgroups.V1, cgroups.StaticPath(s.state.CgroupPath))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not load sandbox cgroup in %v: %v", s.state.CgroupPath, err)
|
||||
}
|
||||
|
||||
s.Logger().WithField("cgroup:", s.state.CgroupPath).Debug("joining to sandbox cgroup")
|
||||
runtimePid := os.Getpid()
|
||||
|
||||
if err := cgroup.Add(cgroups.Process{Pid: runtimePid}); err != nil {
|
||||
return fmt.Errorf("Could not add runtime PID %d to sandbox cgroup: %v", runtimePid, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -1473,3 +1473,97 @@ func TestSandboxExperimentalFeature(t *testing.T) {
|
||||
assert.NotNil(t, exp.Get(testFeature.Name))
|
||||
assert.True(t, sconfig.valid())
|
||||
}
|
||||
|
||||
func TestSandbox_joinSandboxCgroup(t *testing.T) {
|
||||
|
||||
mockValidCgroup := &Sandbox{}
|
||||
mockValidCgroup.state.CgroupPath = "/my/cgroup"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
s *Sandbox
|
||||
wantErr bool
|
||||
}{
|
||||
{"New Config", &Sandbox{}, false},
|
||||
{"Mock cgroup path", mockValidCgroup, false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := tt.s.joinSandboxCgroup(); (err != nil) != tt.wantErr {
|
||||
t.Errorf("Sandbox.joinSandboxCgroup() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSandbox_SetupSandboxCgroupOnly(t *testing.T) {
|
||||
sandboxContainer := ContainerConfig{}
|
||||
sandboxContainer.Annotations = make(map[string]string)
|
||||
sandboxContainer.Annotations[annotations.ContainerTypeKey] = string(PodSandbox)
|
||||
|
||||
emptyJSONLinux := ContainerConfig{}
|
||||
emptyJSONLinux.Annotations = make(map[string]string)
|
||||
emptyJSONLinux.Annotations[annotations.ContainerTypeKey] = string(PodSandbox)
|
||||
emptyJSONLinux.Annotations[annotations.ConfigJSONKey] = "{}"
|
||||
|
||||
successfulContainer := ContainerConfig{}
|
||||
successfulContainer.Annotations = make(map[string]string)
|
||||
successfulContainer.Annotations[annotations.ContainerTypeKey] = string(PodSandbox)
|
||||
successfulContainer.Annotations[annotations.ConfigJSONKey] = "{\"linux\": { \"cgroupsPath\": \"/myRuntime/myContainer\" }}"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
s *Sandbox
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
"New sandbox",
|
||||
&Sandbox{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"New sandbox, new config",
|
||||
&Sandbox{config: &SandboxConfig{}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"sandbox, container no sandbox type",
|
||||
&Sandbox{
|
||||
config: &SandboxConfig{Containers: []ContainerConfig{
|
||||
{},
|
||||
}}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"sandbox, container sandbox type",
|
||||
&Sandbox{
|
||||
config: &SandboxConfig{Containers: []ContainerConfig{
|
||||
sandboxContainer,
|
||||
}}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"sandbox, empty linux json",
|
||||
&Sandbox{
|
||||
config: &SandboxConfig{Containers: []ContainerConfig{
|
||||
emptyJSONLinux,
|
||||
}}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"sandbox, successful config",
|
||||
&Sandbox{
|
||||
config: &SandboxConfig{Containers: []ContainerConfig{
|
||||
successfulContainer,
|
||||
}}},
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := tt.s.setupSandboxCgroupOnly(); (err != nil) != tt.wantErr {
|
||||
t.Errorf("Sandbox.SetupSandboxCgroupOnly() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user