mirror of
https://github.com/k3s-io/k3s.git
synced 2024-06-07 19:41:36 +00:00
Improve handling of comounted cpu,cpuacct controllers (#2911)
* Improve handling of comounted cpu,cpuacct controllers Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
This commit is contained in:
parent
41fd27ab56
commit
e06119729b
@ -184,14 +184,11 @@ func addFeatureGate(current, new string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func checkCgroups() (kubeletRoot, runtimeRoot string, hasCFS, hasPIDs bool) {
|
func checkCgroups() (kubeletRoot, runtimeRoot string, hasCFS, hasPIDs bool) {
|
||||||
f, err := os.Open("/proc/self/cgroup")
|
cgroupsModeV2 := cgroups.Mode() == cgroups.Unified
|
||||||
if err != nil {
|
|
||||||
return "", "", false, false
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
v2 := cgroups.Mode() == cgroups.Unified
|
// For Unified (v2) cgroups we can directly check to see what controllers are mounted
|
||||||
if v2 {
|
// under the unified hierarchy.
|
||||||
|
if cgroupsModeV2 {
|
||||||
m, err := cgroupsv2.LoadManager("/sys/fs/cgroup", "/")
|
m, err := cgroupsv2.LoadManager("/sys/fs/cgroup", "/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", false, false
|
return "", "", false, false
|
||||||
@ -200,33 +197,35 @@ func checkCgroups() (kubeletRoot, runtimeRoot string, hasCFS, hasPIDs bool) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", false, false
|
return "", "", false, false
|
||||||
}
|
}
|
||||||
for _, c := range controllers {
|
// Intentionally using an expressionless switch to match the logic below
|
||||||
switch c {
|
for _, controller := range controllers {
|
||||||
case "cpu":
|
switch {
|
||||||
|
case controller == "cpu":
|
||||||
hasCFS = true
|
hasCFS = true
|
||||||
case "pids":
|
case controller == "pids":
|
||||||
hasPIDs = true
|
hasPIDs = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f, err := os.Open("/proc/self/cgroup")
|
||||||
|
if err != nil {
|
||||||
|
return "", "", false, false
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
scan := bufio.NewScanner(f)
|
scan := bufio.NewScanner(f)
|
||||||
for scan.Scan() {
|
for scan.Scan() {
|
||||||
parts := strings.Split(scan.Text(), ":")
|
parts := strings.Split(scan.Text(), ":")
|
||||||
if len(parts) < 3 {
|
if len(parts) < 3 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
systems := strings.Split(parts[1], ",")
|
controllers := strings.Split(parts[1], ",")
|
||||||
// when v2, systems = {""} (only contains a single empty string)
|
// For v1 or hybrid, controller can be a single value {"blkio"}, or a comounted set {"cpu","cpuacct"}
|
||||||
for _, system := range systems {
|
// For v2, controllers = {""} (only contains a single empty string)
|
||||||
if system == "pids" {
|
for _, controller := range controllers {
|
||||||
hasPIDs = true
|
switch {
|
||||||
} else if system == "cpu" {
|
case controller == "name=systemd" || cgroupsModeV2:
|
||||||
p := filepath.Join("/sys/fs/cgroup", parts[1], parts[2], "cpu.cfs_period_us")
|
|
||||||
if _, err := os.Stat(p); err == nil {
|
|
||||||
hasCFS = true
|
|
||||||
}
|
|
||||||
} else if system == "name=systemd" || v2 {
|
|
||||||
// If we detect that we are running under a `.scope` unit with systemd
|
// If we detect that we are running under a `.scope` unit with systemd
|
||||||
// we can assume we are being directly invoked from the command line
|
// we can assume we are being directly invoked from the command line
|
||||||
// and thus need to set our kubelet root to something out of the context
|
// and thus need to set our kubelet root to something out of the context
|
||||||
@ -240,10 +239,23 @@ func checkCgroups() (kubeletRoot, runtimeRoot string, hasCFS, hasPIDs bool) {
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
kubeletRoot = "/" + version.Program
|
kubeletRoot = "/" + version.Program
|
||||||
}
|
}
|
||||||
|
case controller == "cpu":
|
||||||
|
// It is common for this to show up multiple times in /sys/fs/cgroup if the controllers are comounted:
|
||||||
|
// as "cpu" and "cpuacct", symlinked to the actual hierarchy at "cpu,cpuacct". Unfortunately the order
|
||||||
|
// listed in /proc/self/cgroups may not be the same order used in /sys/fs/cgroup, so this check
|
||||||
|
// can fail if we use the comma-separated name. Instead, we check for the controller using the symlink.
|
||||||
|
p := filepath.Join("/sys/fs/cgroup", controller, parts[2], "cpu.cfs_period_us")
|
||||||
|
if _, err := os.Stat(p); err == nil {
|
||||||
|
hasCFS = true
|
||||||
|
}
|
||||||
|
case controller == "pids":
|
||||||
|
hasPIDs = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're running with v1 and didn't find a scope assigned by systemd, we need to create our own root cgroup to avoid
|
||||||
|
// just inheriting from the parent process. The kubelet will take care of moving us into it when we start it up later.
|
||||||
if kubeletRoot == "" {
|
if kubeletRoot == "" {
|
||||||
// Examine process ID 1 to see if there is a cgroup assigned to it.
|
// Examine process ID 1 to see if there is a cgroup assigned to it.
|
||||||
// When we are not in a container, process 1 is likely to be systemd or some other service manager.
|
// When we are not in a container, process 1 is likely to be systemd or some other service manager.
|
||||||
@ -261,10 +273,12 @@ func checkCgroups() (kubeletRoot, runtimeRoot string, hasCFS, hasPIDs bool) {
|
|||||||
if len(parts) < 3 {
|
if len(parts) < 3 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
systems := strings.Split(parts[1], ",")
|
controllers := strings.Split(parts[1], ",")
|
||||||
// when v2, systems = {""} (only contains a single empty string)
|
// For v1 or hybrid, controller can be a single value {"blkio"}, or a comounted set {"cpu","cpuacct"}
|
||||||
for _, system := range systems {
|
// For v2, controllers = {""} (only contains a single empty string)
|
||||||
if system == "name=systemd" || v2 {
|
for _, controller := range controllers {
|
||||||
|
switch {
|
||||||
|
case controller == "name=systemd" || cgroupsModeV2:
|
||||||
last := parts[len(parts)-1]
|
last := parts[len(parts)-1]
|
||||||
if last != "/" && last != "/init.scope" {
|
if last != "/" && last != "/init.scope" {
|
||||||
kubeletRoot = "/" + version.Program
|
kubeletRoot = "/" + version.Program
|
||||||
|
Loading…
Reference in New Issue
Block a user