Merge pull request #41016 from kolyshkin/cgroup-init
This commit is contained in:
commit
260c26b7be
8 changed files with 92 additions and 114 deletions
|
@ -500,8 +500,8 @@ func verifyPlatformContainerResources(resources *containertypes.Resources, sysIn
|
|||
if resources.NanoCPUs > 0 && resources.CPUQuota > 0 {
|
||||
return warnings, fmt.Errorf("Conflicting options: Nano CPUs and CPU Quota cannot both be set")
|
||||
}
|
||||
if resources.NanoCPUs > 0 && (!sysInfo.CPUCfsPeriod || !sysInfo.CPUCfsQuota) {
|
||||
return warnings, fmt.Errorf("NanoCPUs can not be set, as your kernel does not support CPU cfs period/quota or the cgroup is not mounted")
|
||||
if resources.NanoCPUs > 0 && !sysInfo.CPUCfs {
|
||||
return warnings, fmt.Errorf("NanoCPUs can not be set, as your kernel does not support CPU CFS scheduler or the cgroup is not mounted")
|
||||
}
|
||||
// The highest precision we could get on Linux is 0.001, by setting
|
||||
// cpu.cfs_period_us=1000ms
|
||||
|
@ -518,17 +518,14 @@ func verifyPlatformContainerResources(resources *containertypes.Resources, sysIn
|
|||
warnings = append(warnings, "Your kernel does not support CPU shares or the cgroup is not mounted. Shares discarded.")
|
||||
resources.CPUShares = 0
|
||||
}
|
||||
if resources.CPUPeriod > 0 && !sysInfo.CPUCfsPeriod {
|
||||
warnings = append(warnings, "Your kernel does not support CPU cfs period or the cgroup is not mounted. Period discarded.")
|
||||
if (resources.CPUPeriod != 0 || resources.CPUQuota != 0) && !sysInfo.CPUCfs {
|
||||
warnings = append(warnings, "Your kernel does not support CPU CFS scheduler. CPU period/quota discarded.")
|
||||
resources.CPUPeriod = 0
|
||||
resources.CPUQuota = 0
|
||||
}
|
||||
if resources.CPUPeriod != 0 && (resources.CPUPeriod < 1000 || resources.CPUPeriod > 1000000) {
|
||||
return warnings, fmt.Errorf("CPU cfs period can not be less than 1ms (i.e. 1000) or larger than 1s (i.e. 1000000)")
|
||||
}
|
||||
if resources.CPUQuota > 0 && !sysInfo.CPUCfsQuota {
|
||||
warnings = append(warnings, "Your kernel does not support CPU cfs quota or the cgroup is not mounted. Quota discarded.")
|
||||
resources.CPUQuota = 0
|
||||
}
|
||||
if resources.CPUQuota > 0 && resources.CPUQuota < 1000 {
|
||||
return warnings, fmt.Errorf("CPU cfs quota can not be less than 1ms (i.e. 1000)")
|
||||
}
|
||||
|
@ -1649,51 +1646,32 @@ func setupOOMScoreAdj(score int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (daemon *Daemon) initCgroupsPath(path string) error {
|
||||
func (daemon *Daemon) initCPURtController(mnt, path string) error {
|
||||
if path == "/" || path == "." {
|
||||
return nil
|
||||
}
|
||||
|
||||
if daemon.configStore.CPURealtimePeriod == 0 && daemon.configStore.CPURealtimeRuntime == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if cgroups.IsCgroup2UnifiedMode() {
|
||||
return fmt.Errorf("daemon-scoped cpu-rt-period and cpu-rt-runtime are not implemented for cgroup v2")
|
||||
}
|
||||
|
||||
// Recursively create cgroup to ensure that the system and all parent cgroups have values set
|
||||
// for the period and runtime as this limits what the children can be set to.
|
||||
daemon.initCgroupsPath(filepath.Dir(path))
|
||||
|
||||
mnt, root, err := cgroups.FindCgroupMountpointAndRoot("", "cpu")
|
||||
if err != nil {
|
||||
if err := daemon.initCPURtController(mnt, filepath.Dir(path)); err != nil {
|
||||
return err
|
||||
}
|
||||
// When docker is run inside docker, the root is based of the host cgroup.
|
||||
// Should this be handled in runc/libcontainer/cgroups ?
|
||||
if strings.HasPrefix(root, "/docker/") {
|
||||
root = "/"
|
||||
}
|
||||
|
||||
path = filepath.Join(mnt, root, path)
|
||||
sysInfo := daemon.RawSysInfo(true)
|
||||
if err := maybeCreateCPURealTimeFile(sysInfo.CPURealtimePeriod, daemon.configStore.CPURealtimePeriod, "cpu.rt_period_us", path); err != nil {
|
||||
path = filepath.Join(mnt, path)
|
||||
if err := os.MkdirAll(path, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
return maybeCreateCPURealTimeFile(sysInfo.CPURealtimeRuntime, daemon.configStore.CPURealtimeRuntime, "cpu.rt_runtime_us", path)
|
||||
if err := maybeCreateCPURealTimeFile(daemon.configStore.CPURealtimePeriod, "cpu.rt_period_us", path); err != nil {
|
||||
return err
|
||||
}
|
||||
return maybeCreateCPURealTimeFile(daemon.configStore.CPURealtimeRuntime, "cpu.rt_runtime_us", path)
|
||||
}
|
||||
|
||||
func maybeCreateCPURealTimeFile(sysinfoPresent bool, configValue int64, file string, path string) error {
|
||||
if sysinfoPresent && configValue != 0 {
|
||||
if err := os.MkdirAll(path, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile(filepath.Join(path, file), []byte(strconv.FormatInt(configValue, 10)), 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
func maybeCreateCPURealTimeFile(configValue int64, file string, path string) error {
|
||||
if configValue == 0 {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
return ioutil.WriteFile(filepath.Join(path, file), []byte(strconv.FormatInt(configValue, 10)), 0700)
|
||||
}
|
||||
|
||||
func (daemon *Daemon) setupSeccompProfile() error {
|
||||
|
|
|
@ -30,8 +30,8 @@ func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo)
|
|||
v.KernelMemory = sysInfo.KernelMemory
|
||||
v.KernelMemoryTCP = sysInfo.KernelMemoryTCP
|
||||
v.OomKillDisable = sysInfo.OomKillDisable
|
||||
v.CPUCfsPeriod = sysInfo.CPUCfsPeriod
|
||||
v.CPUCfsQuota = sysInfo.CPUCfsQuota
|
||||
v.CPUCfsPeriod = sysInfo.CPUCfs
|
||||
v.CPUCfsQuota = sysInfo.CPUCfs
|
||||
v.CPUShares = sysInfo.CPUShares
|
||||
v.CPUSet = sysInfo.Cpuset
|
||||
v.PidsLimit = sysInfo.PidsLimit
|
||||
|
|
|
@ -824,15 +824,32 @@ func WithCgroups(daemon *Daemon, c *container.Container) coci.SpecOpts {
|
|||
cgroupsPath = filepath.Join(parent, c.ID)
|
||||
}
|
||||
s.Linux.CgroupsPath = cgroupsPath
|
||||
|
||||
// the rest is only needed for CPU RT controller
|
||||
|
||||
if daemon.configStore.CPURealtimePeriod == 0 && daemon.configStore.CPURealtimeRuntime == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if cgroups.IsCgroup2UnifiedMode() {
|
||||
return errors.New("daemon-scoped cpu-rt-period and cpu-rt-runtime are not implemented for cgroup v2")
|
||||
}
|
||||
|
||||
// FIXME this is very expensive way to check if cpu rt is supported
|
||||
sysInfo := daemon.RawSysInfo(true)
|
||||
if !sysInfo.CPURealtime {
|
||||
return errors.New("daemon-scoped cpu-rt-period and cpu-rt-runtime are not supported by the kernel")
|
||||
}
|
||||
|
||||
p := cgroupsPath
|
||||
if useSystemd {
|
||||
initPath, err := cgroups.GetInitCgroup("cpu")
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "unable to init CPU RT controller")
|
||||
}
|
||||
_, err = cgroups.GetOwnCgroup("cpu")
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "unable to init CPU RT controller")
|
||||
}
|
||||
p = filepath.Join(initPath, s.Linux.CgroupsPath)
|
||||
}
|
||||
|
@ -843,8 +860,19 @@ func WithCgroups(daemon *Daemon, c *container.Container) coci.SpecOpts {
|
|||
parentPath = filepath.Clean("/" + parentPath)
|
||||
}
|
||||
|
||||
if err := daemon.initCgroupsPath(parentPath); err != nil {
|
||||
return fmt.Errorf("linux init cgroups path: %v", err)
|
||||
mnt, root, err := cgroups.FindCgroupMountpointAndRoot("", "cpu")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to init CPU RT controller")
|
||||
}
|
||||
// When docker is run inside docker, the root is based of the host cgroup.
|
||||
// Should this be handled in runc/libcontainer/cgroups ?
|
||||
if strings.HasPrefix(root, "/docker/") {
|
||||
root = "/"
|
||||
}
|
||||
mnt = filepath.Join(mnt, root)
|
||||
|
||||
if err := daemon.initCPURtController(mnt, parentPath); err != nil {
|
||||
return errors.Wrap(err, "unable to init CPU RT controller")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -90,10 +90,8 @@ func applyCPUCgroupInfoV2(info *SysInfo, controllers map[string]struct{}, _ stri
|
|||
return warnings
|
||||
}
|
||||
info.CPUShares = true
|
||||
info.CPUCfsPeriod = true
|
||||
info.CPUCfsQuota = true
|
||||
info.CPURealtimePeriod = false
|
||||
info.CPURealtimeRuntime = false
|
||||
info.CPUCfs = true
|
||||
info.CPURealtime = false
|
||||
return warnings
|
||||
}
|
||||
|
||||
|
|
|
@ -62,17 +62,11 @@ type cgroupCPUInfo struct {
|
|||
// Whether CPU shares is supported or not
|
||||
CPUShares bool
|
||||
|
||||
// Whether CPU CFS(Completely Fair Scheduler) period is supported or not
|
||||
CPUCfsPeriod bool
|
||||
// Whether CPU CFS (Completely Fair Scheduler) is supported
|
||||
CPUCfs bool
|
||||
|
||||
// Whether CPU CFS(Completely Fair Scheduler) quota is supported or not
|
||||
CPUCfsQuota bool
|
||||
|
||||
// Whether CPU real-time period is supported or not
|
||||
CPURealtimePeriod bool
|
||||
|
||||
// Whether CPU real-time runtime is supported or not
|
||||
CPURealtimeRuntime bool
|
||||
// Whether CPU real-time scheduler is supported
|
||||
CPURealtime bool
|
||||
}
|
||||
|
||||
type cgroupBlkioInfo struct {
|
||||
|
|
|
@ -144,27 +144,17 @@ func applyCPUCgroupInfo(info *SysInfo, cgMounts map[string]string) []string {
|
|||
|
||||
info.CPUShares = cgroupEnabled(mountPoint, "cpu.shares")
|
||||
if !info.CPUShares {
|
||||
warnings = append(warnings, "Your kernel does not support cgroup cpu shares")
|
||||
warnings = append(warnings, "Your kernel does not support CPU shares")
|
||||
}
|
||||
|
||||
info.CPUCfsPeriod = cgroupEnabled(mountPoint, "cpu.cfs_period_us")
|
||||
if !info.CPUCfsPeriod {
|
||||
warnings = append(warnings, "Your kernel does not support cgroup cfs period")
|
||||
info.CPUCfs = cgroupEnabled(mountPoint, "cpu.cfs_quota_us")
|
||||
if !info.CPUCfs {
|
||||
warnings = append(warnings, "Your kernel does not support CPU CFS scheduler")
|
||||
}
|
||||
|
||||
info.CPUCfsQuota = cgroupEnabled(mountPoint, "cpu.cfs_quota_us")
|
||||
if !info.CPUCfsQuota {
|
||||
warnings = append(warnings, "Your kernel does not support cgroup cfs quotas")
|
||||
}
|
||||
|
||||
info.CPURealtimePeriod = cgroupEnabled(mountPoint, "cpu.rt_period_us")
|
||||
if !info.CPURealtimePeriod {
|
||||
warnings = append(warnings, "Your kernel does not support cgroup rt period")
|
||||
}
|
||||
|
||||
info.CPURealtimeRuntime = cgroupEnabled(mountPoint, "cpu.rt_runtime_us")
|
||||
if !info.CPURealtimeRuntime {
|
||||
warnings = append(warnings, "Your kernel does not support cgroup rt runtime")
|
||||
info.CPURealtime = cgroupEnabled(mountPoint, "cpu.rt_period_us")
|
||||
if !info.CPURealtime {
|
||||
warnings = append(warnings, "Your kernel does not support CPU realtime scheduler")
|
||||
}
|
||||
|
||||
return warnings
|
||||
|
|
|
@ -240,46 +240,41 @@ func TestDecodeHostConfig(t *testing.T) {
|
|||
|
||||
func TestValidateResources(t *testing.T) {
|
||||
type resourceTest struct {
|
||||
ConfigCPURealtimePeriod int64
|
||||
ConfigCPURealtimeRuntime int64
|
||||
SysInfoCPURealtimePeriod bool
|
||||
SysInfoCPURealtimeRuntime bool
|
||||
ErrorExpected bool
|
||||
FailureMsg string
|
||||
ConfigCPURealtimePeriod int64
|
||||
ConfigCPURealtimeRuntime int64
|
||||
SysInfoCPURealtime bool
|
||||
ErrorExpected bool
|
||||
FailureMsg string
|
||||
}
|
||||
|
||||
tests := []resourceTest{
|
||||
{
|
||||
ConfigCPURealtimePeriod: 1000,
|
||||
ConfigCPURealtimeRuntime: 1000,
|
||||
SysInfoCPURealtimePeriod: true,
|
||||
SysInfoCPURealtimeRuntime: true,
|
||||
ErrorExpected: false,
|
||||
FailureMsg: "Expected valid configuration",
|
||||
ConfigCPURealtimePeriod: 1000,
|
||||
ConfigCPURealtimeRuntime: 1000,
|
||||
SysInfoCPURealtime: true,
|
||||
ErrorExpected: false,
|
||||
FailureMsg: "Expected valid configuration",
|
||||
},
|
||||
{
|
||||
ConfigCPURealtimePeriod: 5000,
|
||||
ConfigCPURealtimeRuntime: 5000,
|
||||
SysInfoCPURealtimePeriod: false,
|
||||
SysInfoCPURealtimeRuntime: true,
|
||||
ErrorExpected: true,
|
||||
FailureMsg: "Expected failure when cpu-rt-period is set but kernel doesn't support it",
|
||||
ConfigCPURealtimePeriod: 5000,
|
||||
ConfigCPURealtimeRuntime: 5000,
|
||||
SysInfoCPURealtime: false,
|
||||
ErrorExpected: true,
|
||||
FailureMsg: "Expected failure when cpu-rt-period is set but kernel doesn't support it",
|
||||
},
|
||||
{
|
||||
ConfigCPURealtimePeriod: 5000,
|
||||
ConfigCPURealtimeRuntime: 5000,
|
||||
SysInfoCPURealtimePeriod: true,
|
||||
SysInfoCPURealtimeRuntime: false,
|
||||
ErrorExpected: true,
|
||||
FailureMsg: "Expected failure when cpu-rt-runtime is set but kernel doesn't support it",
|
||||
ConfigCPURealtimePeriod: 5000,
|
||||
ConfigCPURealtimeRuntime: 5000,
|
||||
SysInfoCPURealtime: false,
|
||||
ErrorExpected: true,
|
||||
FailureMsg: "Expected failure when cpu-rt-runtime is set but kernel doesn't support it",
|
||||
},
|
||||
{
|
||||
ConfigCPURealtimePeriod: 5000,
|
||||
ConfigCPURealtimeRuntime: 10000,
|
||||
SysInfoCPURealtimePeriod: true,
|
||||
SysInfoCPURealtimeRuntime: false,
|
||||
ErrorExpected: true,
|
||||
FailureMsg: "Expected failure when cpu-rt-runtime is greater than cpu-rt-period",
|
||||
ConfigCPURealtimePeriod: 5000,
|
||||
ConfigCPURealtimeRuntime: 10000,
|
||||
SysInfoCPURealtime: true,
|
||||
ErrorExpected: true,
|
||||
FailureMsg: "Expected failure when cpu-rt-runtime is greater than cpu-rt-period",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -289,8 +284,7 @@ func TestValidateResources(t *testing.T) {
|
|||
hc.Resources.CPURealtimeRuntime = rt.ConfigCPURealtimeRuntime
|
||||
|
||||
var si sysinfo.SysInfo
|
||||
si.CPURealtimePeriod = rt.SysInfoCPURealtimePeriod
|
||||
si.CPURealtimeRuntime = rt.SysInfoCPURealtimeRuntime
|
||||
si.CPURealtime = rt.SysInfoCPURealtime
|
||||
|
||||
if err := validateResources(&hc, &si); (err != nil) != rt.ErrorExpected {
|
||||
t.Fatal(rt.FailureMsg, err)
|
||||
|
|
|
@ -85,12 +85,8 @@ func validateResources(hc *container.HostConfig, si *sysinfo.SysInfo) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if hc.Resources.CPURealtimePeriod > 0 && !si.CPURealtimePeriod {
|
||||
return fmt.Errorf("Your kernel does not support cgroup cpu real-time period")
|
||||
}
|
||||
|
||||
if hc.Resources.CPURealtimeRuntime > 0 && !si.CPURealtimeRuntime {
|
||||
return fmt.Errorf("Your kernel does not support cgroup cpu real-time runtime")
|
||||
if (hc.Resources.CPURealtimePeriod != 0 || hc.Resources.CPURealtimeRuntime != 0) && !si.CPURealtime {
|
||||
return fmt.Errorf("Your kernel does not support CPU real-time scheduler")
|
||||
}
|
||||
|
||||
if hc.Resources.CPURealtimePeriod != 0 && hc.Resources.CPURealtimeRuntime != 0 && hc.Resources.CPURealtimeRuntime > hc.Resources.CPURealtimePeriod {
|
||||
|
|
Loading…
Reference in a new issue