mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-26 23:38:31 +00:00
Merge pull request #1514 from fgiudici/port_cgroup_fix
[forwardport] Fixup systemd cgroup handling
This commit is contained in:
commit
3369fc8b4b
@ -54,9 +54,6 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// If set to true, expects cgroupsPath to be of form "slice:prefix:name", otherwise cgroups creation will fail
|
|
||||||
systemdCgroup *bool
|
|
||||||
|
|
||||||
cgroupsLogger = logrus.WithField("source", "virtcontainers/pkg/cgroups")
|
cgroupsLogger = logrus.WithField("source", "virtcontainers/pkg/cgroups")
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -67,18 +64,6 @@ func SetLogger(logger *logrus.Entry) {
|
|||||||
cgroupsLogger = logger.WithFields(fields)
|
cgroupsLogger = logger.WithFields(fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
func EnableSystemdCgroup() {
|
|
||||||
systemd := true
|
|
||||||
systemdCgroup = &systemd
|
|
||||||
}
|
|
||||||
|
|
||||||
func UseSystemdCgroup() bool {
|
|
||||||
if systemdCgroup != nil {
|
|
||||||
return *systemdCgroup
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns the list of devices that a hypervisor may need
|
// returns the list of devices that a hypervisor may need
|
||||||
func hypervisorDevices() []specs.LinuxDeviceCgroup {
|
func hypervisorDevices() []specs.LinuxDeviceCgroup {
|
||||||
devices := []specs.LinuxDeviceCgroup{}
|
devices := []specs.LinuxDeviceCgroup{}
|
||||||
@ -108,7 +93,6 @@ func hypervisorDevices() []specs.LinuxDeviceCgroup {
|
|||||||
// New creates a new CgroupManager
|
// New creates a new CgroupManager
|
||||||
func New(config *Config) (*Manager, error) {
|
func New(config *Config) (*Manager, error) {
|
||||||
var err error
|
var err error
|
||||||
useSystemdCgroup := UseSystemdCgroup()
|
|
||||||
|
|
||||||
devices := config.Resources.Devices
|
devices := config.Resources.Devices
|
||||||
devices = append(devices, hypervisorDevices()...)
|
devices = append(devices, hypervisorDevices()...)
|
||||||
@ -126,6 +110,9 @@ func New(config *Config) (*Manager, error) {
|
|||||||
cgroups := config.Cgroups
|
cgroups := config.Cgroups
|
||||||
cgroupPaths := config.CgroupPaths
|
cgroupPaths := config.CgroupPaths
|
||||||
|
|
||||||
|
// determine if we are utilizing systemd managed cgroups based on the path provided
|
||||||
|
useSystemdCgroup := IsSystemdCgroup(config.CgroupPath)
|
||||||
|
|
||||||
// Create a new cgroup if the current one is nil
|
// Create a new cgroup if the current one is nil
|
||||||
// this cgroups must be saved later
|
// this cgroups must be saved later
|
||||||
if cgroups == nil {
|
if cgroups == nil {
|
||||||
@ -221,7 +208,14 @@ func (m *Manager) moveToParent() error {
|
|||||||
m.Lock()
|
m.Lock()
|
||||||
defer m.Unlock()
|
defer m.Unlock()
|
||||||
for _, cgroupPath := range m.mgr.GetPaths() {
|
for _, cgroupPath := range m.mgr.GetPaths() {
|
||||||
|
|
||||||
pids, err := readPids(cgroupPath)
|
pids, err := readPids(cgroupPath)
|
||||||
|
// possible that the cgroupPath doesn't exist. If so, skip:
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
// The cgroup is not present on the filesystem: no pids to move. The systemd cgroup
|
||||||
|
// manager lists all of the subsystems, including those that are not actually being managed.
|
||||||
|
continue
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -287,7 +281,10 @@ func (m *Manager) GetPaths() map[string]string {
|
|||||||
func (m *Manager) Destroy() error {
|
func (m *Manager) Destroy() error {
|
||||||
// cgroup can't be destroyed if it contains running processes
|
// cgroup can't be destroyed if it contains running processes
|
||||||
if err := m.moveToParent(); err != nil {
|
if err := m.moveToParent(); err != nil {
|
||||||
return fmt.Errorf("Could not move processes into parent cgroup: %v", err)
|
// If the process migration to the parent cgroup fails, then
|
||||||
|
// we expect the Destroy to fail as well. Let's log an error here
|
||||||
|
// and attempt to execute the Destroy still to help cleanup the hosts' FS.
|
||||||
|
m.logger().WithError(err).Error("Could not move processes into parent cgroup")
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Lock()
|
m.Lock()
|
||||||
|
@ -11,34 +11,11 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEnableSystemdCgroup(t *testing.T) {
|
//very very basic test; should be expanded
|
||||||
assert := assert.New(t)
|
|
||||||
|
|
||||||
orgSystemdCgroup := systemdCgroup
|
|
||||||
defer func() {
|
|
||||||
systemdCgroup = orgSystemdCgroup
|
|
||||||
}()
|
|
||||||
|
|
||||||
useSystemdCgroup := UseSystemdCgroup()
|
|
||||||
if systemdCgroup != nil {
|
|
||||||
assert.Equal(*systemdCgroup, useSystemdCgroup)
|
|
||||||
} else {
|
|
||||||
assert.False(useSystemdCgroup)
|
|
||||||
}
|
|
||||||
|
|
||||||
EnableSystemdCgroup()
|
|
||||||
assert.True(UseSystemdCgroup())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNew(t *testing.T) {
|
func TestNew(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
useSystemdCgroup := false
|
|
||||||
orgSystemdCgroup := systemdCgroup
|
|
||||||
defer func() {
|
|
||||||
systemdCgroup = orgSystemdCgroup
|
|
||||||
}()
|
|
||||||
systemdCgroup = &useSystemdCgroup
|
|
||||||
|
|
||||||
|
// create a cgroupfs cgroup manager
|
||||||
c := &Config{
|
c := &Config{
|
||||||
Cgroups: nil,
|
Cgroups: nil,
|
||||||
CgroupPath: "",
|
CgroupPath: "",
|
||||||
@ -48,8 +25,14 @@ func TestNew(t *testing.T) {
|
|||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
assert.NotNil(mgr.mgr)
|
assert.NotNil(mgr.mgr)
|
||||||
|
|
||||||
useSystemdCgroup = true
|
// create a systemd cgroup manager
|
||||||
mgr, err = New(c)
|
s := &Config{
|
||||||
assert.Error(err)
|
Cgroups: nil,
|
||||||
assert.Nil(mgr)
|
CgroupPath: "system.slice:kubepod:container",
|
||||||
|
}
|
||||||
|
|
||||||
|
mgr, err = New(s)
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.NotNil(mgr.mgr)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"strings"
|
||||||
|
|
||||||
"github.com/opencontainers/runc/libcontainer/configs"
|
"github.com/opencontainers/runc/libcontainer/configs"
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
@ -60,13 +60,20 @@ func ValidCgroupPath(path string, systemdCgroup bool) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func IsSystemdCgroup(cgroupPath string) bool {
|
func IsSystemdCgroup(cgroupPath string) bool {
|
||||||
// systemd cgroup path: slice:prefix:name
|
|
||||||
re := regexp.MustCompile(`([[:alnum:]]|\.)+:([[:alnum:]]|\.)+:([[:alnum:]]|\.)+`)
|
|
||||||
found := re.FindStringIndex(cgroupPath)
|
|
||||||
|
|
||||||
// if found string is equal to cgroupPath then
|
// If we are utilizing systemd to manage cgroups, we expect to receive a path
|
||||||
// it's a correct systemd cgroup path.
|
// in the format slice:scopeprefix:name. A typical example would be:
|
||||||
return found != nil && cgroupPath[found[0]:found[1]] == cgroupPath
|
//
|
||||||
|
// system.slice:docker:6b4c4a4d0cc2a12c529dcb13a2b8e438dfb3b2a6af34d548d7d
|
||||||
|
//
|
||||||
|
// Based on this, let's split by the ':' delimiter and verify that the first
|
||||||
|
// section has .slice as a suffix.
|
||||||
|
parts := strings.Split(cgroupPath, ":")
|
||||||
|
if len(parts) == 3 && strings.HasSuffix(parts[0], ".slice") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeviceToCgroupDevice(device string) (*configs.Device, error) {
|
func DeviceToCgroupDevice(device string) (*configs.Device, error) {
|
||||||
|
@ -22,8 +22,8 @@ func TestIsSystemdCgroup(t *testing.T) {
|
|||||||
path string
|
path string
|
||||||
expected bool
|
expected bool
|
||||||
}{
|
}{
|
||||||
{"slice:kata:afhts2e5d4g5s", true},
|
{"foo.slice:kata:afhts2e5d4g5s", true},
|
||||||
{"slice.system:kata:afhts2e5d4g5s", true},
|
{"system.slice:kata:afhts2e5d4g5s", true},
|
||||||
{"/kata/afhts2e5d4g5s", false},
|
{"/kata/afhts2e5d4g5s", false},
|
||||||
{"a:b:c:d", false},
|
{"a:b:c:d", false},
|
||||||
{":::", false},
|
{":::", false},
|
||||||
@ -78,9 +78,9 @@ func TestValidCgroupPath(t *testing.T) {
|
|||||||
{":a:b", true, true},
|
{":a:b", true, true},
|
||||||
{"@:@:@", true, true},
|
{"@:@:@", true, true},
|
||||||
|
|
||||||
// valid system paths
|
// valid systemd paths
|
||||||
{"slice:kata:55555", true, false},
|
{"x.slice:kata:55555", true, false},
|
||||||
{"slice.system:kata:afhts2e5d4g5s", true, false},
|
{"system.slice:kata:afhts2e5d4g5s", true, false},
|
||||||
} {
|
} {
|
||||||
path, err := ValidCgroupPath(t.path, t.systemdCgroup)
|
path, err := ValidCgroupPath(t.path, t.systemdCgroup)
|
||||||
if t.error {
|
if t.error {
|
||||||
|
Loading…
Reference in New Issue
Block a user