mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	kubelet/cm: GetResourceStats -> MemoryUsage
Commit cc50aa9dfb introduced GetResourceStats, a method which collected
all the statistics from various cgroup controllers, only to discard all
of the info collected except a single value (memory usage).
While one may argue that this method can potentially be used from other
places, this did not happen since it was added 4+ years ago.
Let's streamline this code and only collect what we need, i.e. memory
usage. Rename the method accordingly.
While at it, fix pkg/kubelet/cm/cgroup_manager_unsupported.go to not
instantiate a new error every time a method is called.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
			
			
This commit is contained in:
		@@ -17,6 +17,7 @@ limitations under the License.
 | 
				
			|||||||
package cm
 | 
					package cm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
@@ -29,6 +30,7 @@ import (
 | 
				
			|||||||
	libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
 | 
						libcontainercgroups "github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
	cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
 | 
						cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
 | 
				
			||||||
	cgroupfs2 "github.com/opencontainers/runc/libcontainer/cgroups/fs2"
 | 
						cgroupfs2 "github.com/opencontainers/runc/libcontainer/cgroups/fs2"
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
 | 
				
			||||||
	cgroupsystemd "github.com/opencontainers/runc/libcontainer/cgroups/systemd"
 | 
						cgroupsystemd "github.com/opencontainers/runc/libcontainer/cgroups/systemd"
 | 
				
			||||||
	libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs"
 | 
						libcontainerconfigs "github.com/opencontainers/runc/libcontainer/configs"
 | 
				
			||||||
	libcontainerdevices "github.com/opencontainers/runc/libcontainer/devices"
 | 
						libcontainerdevices "github.com/opencontainers/runc/libcontainer/devices"
 | 
				
			||||||
@@ -330,27 +332,6 @@ func (m *cgroupManagerImpl) Destroy(cgroupConfig *CgroupConfig) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type subsystem interface {
 | 
					 | 
				
			||||||
	// Name returns the name of the subsystem.
 | 
					 | 
				
			||||||
	Name() string
 | 
					 | 
				
			||||||
	// Set the cgroup represented by cgroup.
 | 
					 | 
				
			||||||
	Set(path string, cgroup *libcontainerconfigs.Resources) error
 | 
					 | 
				
			||||||
	// GetStats returns the statistics associated with the cgroup
 | 
					 | 
				
			||||||
	GetStats(path string, stats *libcontainercgroups.Stats) error
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// getSupportedSubsystems returns a map of subsystem and if it must be mounted for the kubelet to function.
 | 
					 | 
				
			||||||
func getSupportedSubsystems() map[subsystem]bool {
 | 
					 | 
				
			||||||
	supportedSubsystems := map[subsystem]bool{
 | 
					 | 
				
			||||||
		&cgroupfs.MemoryGroup{}: true,
 | 
					 | 
				
			||||||
		&cgroupfs.CpuGroup{}:    true,
 | 
					 | 
				
			||||||
		&cgroupfs.PidsGroup{}:   true,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// not all hosts support hugetlb cgroup, and in the absent of hugetlb, we will fail silently by reporting no capacity.
 | 
					 | 
				
			||||||
	supportedSubsystems[&cgroupfs.HugetlbGroup{}] = false
 | 
					 | 
				
			||||||
	return supportedSubsystems
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// getCpuWeight converts from the range [2, 262144] to [1, 10000]
 | 
					// getCpuWeight converts from the range [2, 262144] to [1, 10000]
 | 
				
			||||||
func getCpuWeight(cpuShares *uint64) uint64 {
 | 
					func getCpuWeight(cpuShares *uint64) uint64 {
 | 
				
			||||||
	if cpuShares == nil {
 | 
						if cpuShares == nil {
 | 
				
			||||||
@@ -620,53 +601,21 @@ func (m *cgroupManagerImpl) ReduceCPULimits(cgroupName CgroupName) error {
 | 
				
			|||||||
	return m.Update(containerConfig)
 | 
						return m.Update(containerConfig)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getStatsSupportedSubsystems(cgroupPaths map[string]string) (*libcontainercgroups.Stats, error) {
 | 
					// MemoryUsage returns the current memory usage of the specified cgroup,
 | 
				
			||||||
	stats := libcontainercgroups.NewStats()
 | 
					// as read from cgroupfs.
 | 
				
			||||||
	for sys, required := range getSupportedSubsystems() {
 | 
					func (m *cgroupManagerImpl) MemoryUsage(name CgroupName) (int64, error) {
 | 
				
			||||||
		if _, ok := cgroupPaths[sys.Name()]; !ok {
 | 
						var path, file string
 | 
				
			||||||
			if required {
 | 
					 | 
				
			||||||
				return nil, fmt.Errorf("failed to find subsystem mount for required subsystem: %v", sys.Name())
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// the cgroup is not mounted, but its not required so continue...
 | 
					 | 
				
			||||||
			klog.V(6).InfoS("Unable to find subsystem mount for optional subsystem", "subsystemName", sys.Name())
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if err := sys.GetStats(cgroupPaths[sys.Name()], stats); err != nil {
 | 
					 | 
				
			||||||
			return nil, fmt.Errorf("failed to get stats for supported subsystems : %v", err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return stats, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func toResourceStats(stats *libcontainercgroups.Stats) *ResourceStats {
 | 
					 | 
				
			||||||
	return &ResourceStats{
 | 
					 | 
				
			||||||
		MemoryStats: &MemoryStats{
 | 
					 | 
				
			||||||
			Usage: int64(stats.MemoryStats.Usage.Usage),
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Get sets the ResourceParameters of the specified cgroup as read from the cgroup fs
 | 
					 | 
				
			||||||
func (m *cgroupManagerImpl) GetResourceStats(name CgroupName) (*ResourceStats, error) {
 | 
					 | 
				
			||||||
	var err error
 | 
					 | 
				
			||||||
	var stats *libcontainercgroups.Stats
 | 
					 | 
				
			||||||
	if libcontainercgroups.IsCgroup2UnifiedMode() {
 | 
						if libcontainercgroups.IsCgroup2UnifiedMode() {
 | 
				
			||||||
		cgroupPath := m.buildCgroupUnifiedPath(name)
 | 
							path = m.buildCgroupUnifiedPath(name)
 | 
				
			||||||
		manager, err := cgroupfs2.NewManager(nil, cgroupPath, false)
 | 
							file = "memory.current"
 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, fmt.Errorf("failed to create cgroup v2 manager: %v", err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		stats, err = manager.GetStats()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, fmt.Errorf("failed to get stats for cgroup %v: %v", name, err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		cgroupPaths := m.buildCgroupPaths(name)
 | 
							mp, ok := m.subsystems.MountPoints["memory"]
 | 
				
			||||||
		stats, err = getStatsSupportedSubsystems(cgroupPaths)
 | 
							if !ok { // should not happen
 | 
				
			||||||
		if err != nil {
 | 
								return -1, errors.New("no cgroup v1 mountpoint for memory controller found")
 | 
				
			||||||
			return nil, fmt.Errorf("failed to get stats supported cgroup subsystems for cgroup %v: %v", name, err)
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							path = mp + "/" + m.Name(name)
 | 
				
			||||||
 | 
							file = "memory.usage_in_bytes"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return toResourceStats(stats), nil
 | 
						val, err := fscommon.GetCgroupParamUint(path, file)
 | 
				
			||||||
 | 
						return int64(val), err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,10 +18,12 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package cm
 | 
					package cm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "fmt"
 | 
					import "errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type unsupportedCgroupManager struct{}
 | 
					type unsupportedCgroupManager struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var errNotSupported = errors.New("Cgroup Manager is not supported in this build")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Make sure that unsupportedCgroupManager implements the CgroupManager interface
 | 
					// Make sure that unsupportedCgroupManager implements the CgroupManager interface
 | 
				
			||||||
var _ CgroupManager = &unsupportedCgroupManager{}
 | 
					var _ CgroupManager = &unsupportedCgroupManager{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,11 +53,11 @@ func (m *unsupportedCgroupManager) Update(_ *CgroupConfig) error {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *unsupportedCgroupManager) Create(_ *CgroupConfig) error {
 | 
					func (m *unsupportedCgroupManager) Create(_ *CgroupConfig) error {
 | 
				
			||||||
	return fmt.Errorf("Cgroup Manager is not supported in this build")
 | 
						return errNotSupported
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *unsupportedCgroupManager) GetResourceStats(name CgroupName) (*ResourceStats, error) {
 | 
					func (m *unsupportedCgroupManager) MemoryUsage(_ CgroupName) (int64, error) {
 | 
				
			||||||
	return nil, fmt.Errorf("Cgroup Manager is not supported in this build")
 | 
						return -1, errNotSupported
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *unsupportedCgroupManager) Pids(_ CgroupName) []int {
 | 
					func (m *unsupportedCgroupManager) Pids(_ CgroupName) []int {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,7 +28,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	units "github.com/docker/go-units"
 | 
						units "github.com/docker/go-units"
 | 
				
			||||||
	cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
 | 
						cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
 | 
				
			||||||
	"k8s.io/api/core/v1"
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
						utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/api/v1/resource"
 | 
						"k8s.io/kubernetes/pkg/api/v1/resource"
 | 
				
			||||||
	v1qos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos"
 | 
						v1qos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos"
 | 
				
			||||||
@@ -247,12 +247,11 @@ func (m *qosContainerManagerImpl) retrySetMemoryReserve(configs map[v1.PodQOSCla
 | 
				
			|||||||
	// Attempt to set the limit near the current usage to put pressure
 | 
						// Attempt to set the limit near the current usage to put pressure
 | 
				
			||||||
	// on the cgroup and prevent further growth.
 | 
						// on the cgroup and prevent further growth.
 | 
				
			||||||
	for qos, config := range configs {
 | 
						for qos, config := range configs {
 | 
				
			||||||
		stats, err := m.cgroupManager.GetResourceStats(config.Name)
 | 
							usage, err := m.cgroupManager.MemoryUsage(config.Name)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			klog.V(2).InfoS("Failed to get resource stats", "err", err)
 | 
								klog.V(2).InfoS("Failed to get resource stats", "err", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		usage := stats.MemoryStats.Usage
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Because there is no good way to determine of the original Update()
 | 
							// Because there is no good way to determine of the original Update()
 | 
				
			||||||
		// on the memory resource was successful, we determine failure of the
 | 
							// on the memory resource was successful, we determine failure of the
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@ limitations under the License.
 | 
				
			|||||||
package cm
 | 
					package cm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"k8s.io/api/core/v1"
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/types"
 | 
						"k8s.io/apimachinery/pkg/types"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -53,18 +53,6 @@ type CgroupConfig struct {
 | 
				
			|||||||
	ResourceParameters *ResourceConfig
 | 
						ResourceParameters *ResourceConfig
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MemoryStats holds the on-demand statistics from the memory cgroup
 | 
					 | 
				
			||||||
type MemoryStats struct {
 | 
					 | 
				
			||||||
	// Memory usage (in bytes).
 | 
					 | 
				
			||||||
	Usage int64
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ResourceStats holds on-demand statistics from various cgroup subsystems
 | 
					 | 
				
			||||||
type ResourceStats struct {
 | 
					 | 
				
			||||||
	// Memory statistics.
 | 
					 | 
				
			||||||
	MemoryStats *MemoryStats
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// CgroupManager allows for cgroup management.
 | 
					// CgroupManager allows for cgroup management.
 | 
				
			||||||
// Supports Cgroup Creation ,Deletion and Updates.
 | 
					// Supports Cgroup Creation ,Deletion and Updates.
 | 
				
			||||||
type CgroupManager interface {
 | 
					type CgroupManager interface {
 | 
				
			||||||
@@ -90,8 +78,8 @@ type CgroupManager interface {
 | 
				
			|||||||
	Pids(name CgroupName) []int
 | 
						Pids(name CgroupName) []int
 | 
				
			||||||
	// ReduceCPULimits reduces the CPU CFS values to the minimum amount of shares.
 | 
						// ReduceCPULimits reduces the CPU CFS values to the minimum amount of shares.
 | 
				
			||||||
	ReduceCPULimits(cgroupName CgroupName) error
 | 
						ReduceCPULimits(cgroupName CgroupName) error
 | 
				
			||||||
	// GetResourceStats returns statistics of the specified cgroup as read from the cgroup fs.
 | 
						// MemoryUsage returns current memory usage of the specified cgroup, as read from the cgroupfs.
 | 
				
			||||||
	GetResourceStats(name CgroupName) (*ResourceStats, error)
 | 
						MemoryUsage(name CgroupName) (int64, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// QOSContainersInfo stores the names of containers per qos
 | 
					// QOSContainersInfo stores the names of containers per qos
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user