diff --git a/go.mod b/go.mod index 054a94197baf..608d97434180 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e github.com/golang/mock v1.4.4 github.com/golang/protobuf v1.5.0 - github.com/google/cadvisor v0.39.0 + github.com/google/cadvisor v0.39.3 github.com/google/go-cmp v0.5.5 github.com/google/gofuzz v1.1.0 github.com/google/uuid v1.1.2 @@ -279,7 +279,7 @@ replace ( github.com/golang/protobuf => github.com/golang/protobuf v1.5.0 github.com/golangplus/testing => github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e github.com/google/btree => github.com/google/btree v1.0.0 - github.com/google/cadvisor => github.com/google/cadvisor v0.39.0 + github.com/google/cadvisor => github.com/google/cadvisor v0.39.3 github.com/google/go-cmp => github.com/google/go-cmp v0.5.5 github.com/google/gofuzz => github.com/google/gofuzz v1.1.0 github.com/google/martian => github.com/google/martian v2.1.0+incompatible diff --git a/go.sum b/go.sum index 02ec9b6842e5..ab32647e8a9b 100644 --- a/go.sum +++ b/go.sum @@ -222,8 +222,8 @@ github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e h1:KhcknUwkWHKZ github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/cadvisor v0.39.0 h1:jai6dmBP9QAYluNGqU18yVUTw6uuyAW0AqtZIjvl8Qg= -github.com/google/cadvisor v0.39.0/go.mod h1:rjQFmK4jPCpxeUdLq9bYhNFFsjgGOtpnDmDeap0+nsw= +github.com/google/cadvisor v0.39.3 h1:Z04WmZQWsdZKxAdtqE8h68zyfpCu9LimRyDg3GOmrbc= +github.com/google/cadvisor v0.39.3/go.mod h1:kN93gpdevu+bpS227TyHVZyCU5bbqCzTj5T9drl34MI= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= diff --git a/vendor/github.com/google/cadvisor/container/common/helpers.go b/vendor/github.com/google/cadvisor/container/common/helpers.go index 4eba4af2c3a4..19241e7937fc 100644 --- a/vendor/github.com/google/cadvisor/container/common/helpers.go +++ b/vendor/github.com/google/cadvisor/container/common/helpers.go @@ -17,9 +17,9 @@ package common import ( "fmt" "io/ioutil" + "math" "os" "path" - "path/filepath" "strconv" "strings" "time" @@ -50,25 +50,6 @@ func DebugInfo(watches map[string][]string) map[string][]string { return out } -// findFileInAncestorDir returns the path to the parent directory that contains the specified file. -// "" is returned if the lookup reaches the limit. -func findFileInAncestorDir(current, file, limit string) (string, error) { - for { - fpath := path.Join(current, file) - _, err := os.Stat(fpath) - if err == nil { - return current, nil - } - if !os.IsNotExist(err) { - return "", err - } - if current == limit { - return "", nil - } - current = filepath.Dir(current) - } -} - var bootTime = func() time.Time { now := time.Now() var sysinfo unix.Sysinfo_t @@ -80,6 +61,10 @@ var bootTime = func() time.Time { }() func GetSpec(cgroupPaths map[string]string, machineInfoFactory info.MachineInfoFactory, hasNetwork, hasFilesystem bool) (info.ContainerSpec, error) { + return getSpecInternal(cgroupPaths, machineInfoFactory, hasNetwork, hasFilesystem, cgroups.IsCgroup2UnifiedMode()) +} + +func getSpecInternal(cgroupPaths map[string]string, machineInfoFactory info.MachineInfoFactory, hasNetwork, hasFilesystem, cgroup2UnifiedMode bool) (info.ContainerSpec, error) { var spec info.ContainerSpec // Assume unified hierarchy containers. @@ -96,7 +81,7 @@ func GetSpec(cgroupPaths map[string]string, machineInfoFactory info.MachineInfoF // Use clone_children/events as a workaround as it isn't usually modified. It is only likely changed // immediately after creating a container. If the directory modified time is lower, we use that. cgroupPathFile := path.Join(cgroupPathDir, "cgroup.clone_children") - if cgroups.IsCgroup2UnifiedMode() { + if cgroup2UnifiedMode { cgroupPathFile = path.Join(cgroupPathDir, "cgroup.events") } fi, err := os.Stat(cgroupPathFile) @@ -122,17 +107,43 @@ func GetSpec(cgroupPaths map[string]string, machineInfoFactory info.MachineInfoF cpuRoot, ok := cgroupPaths["cpu"] if ok { if utils.FileExists(cpuRoot) { - spec.HasCpu = true - spec.Cpu.Limit = readUInt64(cpuRoot, "cpu.shares") - spec.Cpu.Period = readUInt64(cpuRoot, "cpu.cfs_period_us") - quota := readString(cpuRoot, "cpu.cfs_quota_us") - - if quota != "" && quota != "-1" { - val, err := strconv.ParseUint(quota, 10, 64) - if err != nil { - klog.Errorf("GetSpec: Failed to parse CPUQuota from %q: %s", path.Join(cpuRoot, "cpu.cfs_quota_us"), err) - } else { - spec.Cpu.Quota = val + if cgroup2UnifiedMode { + spec.HasCpu = true + + weight := readUInt64(cpuRoot, "cpu.weight") + if weight > 0 { + limit, err := convertCPUWeightToCPULimit(weight) + if err != nil { + klog.Errorf("GetSpec: Failed to read CPULimit from %q: %s", path.Join(cpuRoot, "cpu.weight"), err) + } else { + spec.Cpu.Limit = limit + } + } + max := readString(cpuRoot, "cpu.max") + if max != "" { + splits := strings.SplitN(max, " ", 2) + if len(splits) != 2 { + klog.Errorf("GetSpec: Failed to parse CPUmax from %q", path.Join(cpuRoot, "cpu.max")) + } else { + if splits[0] != "max" { + spec.Cpu.Quota = parseUint64String(splits[0]) + } + spec.Cpu.Period = parseUint64String(splits[1]) + } + } + } else { + spec.HasCpu = true + spec.Cpu.Limit = readUInt64(cpuRoot, "cpu.shares") + spec.Cpu.Period = readUInt64(cpuRoot, "cpu.cfs_period_us") + quota := readString(cpuRoot, "cpu.cfs_quota_us") + + if quota != "" && quota != "-1" { + val, err := strconv.ParseUint(quota, 10, 64) + if err != nil { + klog.Errorf("GetSpec: Failed to parse CPUQuota from %q: %s", path.Join(cpuRoot, "cpu.cfs_quota_us"), err) + } else { + spec.Cpu.Quota = val + } } } } @@ -145,7 +156,7 @@ func GetSpec(cgroupPaths map[string]string, machineInfoFactory info.MachineInfoF if utils.FileExists(cpusetRoot) { spec.HasCpu = true mask := "" - if cgroups.IsCgroup2UnifiedMode() { + if cgroup2UnifiedMode { mask = readString(cpusetRoot, "cpuset.cpus.effective") } else { mask = readString(cpusetRoot, "cpuset.cpus") @@ -157,24 +168,20 @@ func GetSpec(cgroupPaths map[string]string, machineInfoFactory info.MachineInfoF // Memory memoryRoot, ok := cgroupPaths["memory"] if ok { - if !cgroups.IsCgroup2UnifiedMode() { + if cgroup2UnifiedMode { + if utils.FileExists(path.Join(memoryRoot, "memory.max")) { + spec.HasMemory = true + spec.Memory.Reservation = readUInt64(memoryRoot, "memory.high") + spec.Memory.Limit = readUInt64(memoryRoot, "memory.max") + spec.Memory.SwapLimit = readUInt64(memoryRoot, "memory.swap.max") + } + } else { if utils.FileExists(memoryRoot) { spec.HasMemory = true spec.Memory.Limit = readUInt64(memoryRoot, "memory.limit_in_bytes") spec.Memory.SwapLimit = readUInt64(memoryRoot, "memory.memsw.limit_in_bytes") spec.Memory.Reservation = readUInt64(memoryRoot, "memory.soft_limit_in_bytes") } - } else { - memoryRoot, err := findFileInAncestorDir(memoryRoot, "memory.max", "/sys/fs/cgroup") - if err != nil { - return spec, err - } - if memoryRoot != "" { - spec.HasMemory = true - spec.Memory.Reservation = readUInt64(memoryRoot, "memory.high") - spec.Memory.Limit = readUInt64(memoryRoot, "memory.max") - spec.Memory.SwapLimit = readUInt64(memoryRoot, "memory.swap.max") - } } } @@ -199,7 +206,7 @@ func GetSpec(cgroupPaths map[string]string, machineInfoFactory info.MachineInfoF spec.HasFilesystem = hasFilesystem ioControllerName := "blkio" - if cgroups.IsCgroup2UnifiedMode() { + if cgroup2UnifiedMode { ioControllerName = "io" } if blkioRoot, ok := cgroupPaths[ioControllerName]; ok && utils.FileExists(blkioRoot) { @@ -224,9 +231,43 @@ func readString(dirpath string, file string) string { return strings.TrimSpace(string(out)) } +// Convert from [1-10000] to [2-262144] +func convertCPUWeightToCPULimit(weight uint64) (uint64, error) { + const ( + // minWeight is the lowest value possible for cpu.weight + minWeight = 1 + // maxWeight is the highest value possible for cpu.weight + maxWeight = 10000 + ) + if weight < minWeight || weight > maxWeight { + return 0, fmt.Errorf("convertCPUWeightToCPULimit: invalid cpu weight: %v", weight) + } + return 2 + ((weight-1)*262142)/9999, nil +} + +func parseUint64String(strValue string) uint64 { + if strValue == "max" { + return math.MaxUint64 + } + if strValue == "" { + return 0 + } + + val, err := strconv.ParseUint(strValue, 10, 64) + if err != nil { + klog.Errorf("parseUint64String: Failed to parse int %q: %s", strValue, err) + return 0 + } + + return val +} + func readUInt64(dirpath string, file string) uint64 { out := readString(dirpath, file) - if out == "" || out == "max" { + if out == "max" { + return math.MaxUint64 + } + if out == "" { return 0 } diff --git a/vendor/github.com/google/cadvisor/manager/manager.go b/vendor/github.com/google/cadvisor/manager/manager.go index cf6a8a1a1005..6d0f7d6a1ded 100644 --- a/vendor/github.com/google/cadvisor/manager/manager.go +++ b/vendor/github.com/google/cadvisor/manager/manager.go @@ -692,6 +692,10 @@ func (m *manager) GetRequestedContainersInfo(containerName string, options v2.Re for name, data := range containers { info, err := m.containerDataToContainerInfo(data, &query) if err != nil { + if err == memory.ErrDataNotFound { + klog.Warningf("Error getting data for container %s because of race condition", name) + continue + } errs.append(name, "containerDataToContainerInfo", err) } containersMap[name] = info diff --git a/vendor/modules.txt b/vendor/modules.txt index 7afdf9b3b7f0..de8e78fb0c07 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -501,9 +501,9 @@ github.com/golang/protobuf/ptypes/wrappers # github.com/google/btree v1.0.0 => github.com/google/btree v1.0.0 github.com/google/btree # github.com/google/btree => github.com/google/btree v1.0.0 -# github.com/google/cadvisor v0.39.0 => github.com/google/cadvisor v0.39.0 +# github.com/google/cadvisor v0.39.3 => github.com/google/cadvisor v0.39.3 ## explicit -# github.com/google/cadvisor => github.com/google/cadvisor v0.39.0 +# github.com/google/cadvisor => github.com/google/cadvisor v0.39.3 github.com/google/cadvisor/accelerators github.com/google/cadvisor/cache/memory github.com/google/cadvisor/client/v2