From 5fdf24baca10ebdb192b821b86a6a1c8687bd386 Mon Sep 17 00:00:00 2001 From: Eric Lin Date: Fri, 17 Dec 2021 16:15:28 +0000 Subject: [PATCH] Read number of running processes from /proc/loadavg. Fallback to using sysinfo syscall if failed. Fix kubernetes#107107 --- pkg/kubelet/stats/pidlimit/pidlimit_linux.go | 36 +++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/pkg/kubelet/stats/pidlimit/pidlimit_linux.go b/pkg/kubelet/stats/pidlimit/pidlimit_linux.go index 12141974299ab..1916a0bcf66e8 100644 --- a/pkg/kubelet/stats/pidlimit/pidlimit_linux.go +++ b/pkg/kubelet/stats/pidlimit/pidlimit_linux.go @@ -20,12 +20,14 @@ limitations under the License. package pidlimit import ( + "fmt" "io/ioutil" "strconv" + "strings" "syscall" "time" - "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1" ) @@ -39,12 +41,36 @@ func Stats() (*statsapi.RlimitStats, error) { } } - var info syscall.Sysinfo_t - syscall.Sysinfo(&info) - procs := int64(info.Procs) - rlimit.NumOfRunningProcesses = &procs + // Prefer to read "/proc/loadavg" when possible because sysinfo(2) + // returns truncated number when greater than 65538. See + // https://github.com/kubernetes/kubernetes/issues/107107 + if procs, err := runningTaskCount(); err == nil { + rlimit.NumOfRunningProcesses = &procs + } else { + var info syscall.Sysinfo_t + syscall.Sysinfo(&info) + procs := int64(info.Procs) + rlimit.NumOfRunningProcesses = &procs + } rlimit.Time = v1.NewTime(time.Now()) return rlimit, nil } + +func runningTaskCount() (int64, error) { + // Example: 1.36 3.49 4.53 2/3518 3715089 + bytes, err := ioutil.ReadFile("/proc/loadavg") + if err != nil { + return 0, err + } + fields := strings.Fields(string(bytes)) + if len(fields) < 5 { + return 0, fmt.Errorf("not enough fields in /proc/loadavg") + } + subfields := strings.Split(fields[3], "/") + if len(subfields) != 2 { + return 0, fmt.Errorf("error parsing fourth field of /proc/loadavg") + } + return strconv.ParseInt(subfields[1], 10, 64) +}