Merge pull request #125982 from harche/compressible_reserved

Set only compressible resources on system and kube reserved cgroup slices
This commit is contained in:
Kubernetes Prow Robot 2024-10-04 04:08:27 +01:00 committed by GitHub
commit c923a61ddd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 184 additions and 35 deletions

View File

@ -498,7 +498,7 @@ func AddKubeletConfigFlags(mainfs *pflag.FlagSet, c *kubeletconfig.KubeletConfig
// Node Allocatable Flags // Node Allocatable Flags
fs.Var(cliflag.NewMapStringString(&c.SystemReserved), "system-reserved", "A set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=500Mi,ephemeral-storage=1Gi,pid=1000) pairs that describe resources reserved for non-kubernetes components. Currently only cpu, memory, pid and local ephemeral storage for root file system are supported. See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ for more detail. [default=none]") fs.Var(cliflag.NewMapStringString(&c.SystemReserved), "system-reserved", "A set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=500Mi,ephemeral-storage=1Gi,pid=1000) pairs that describe resources reserved for non-kubernetes components. Currently only cpu, memory, pid and local ephemeral storage for root file system are supported. See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ for more detail. [default=none]")
fs.Var(cliflag.NewMapStringString(&c.KubeReserved), "kube-reserved", "A set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=500Mi,ephemeral-storage=1Gi,pid=1000) pairs that describe resources reserved for kubernetes system components. Currently only cpu, memory, pid and local ephemeral storage for root file system are supported. See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ for more detail. [default=none]") fs.Var(cliflag.NewMapStringString(&c.KubeReserved), "kube-reserved", "A set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=500Mi,ephemeral-storage=1Gi,pid=1000) pairs that describe resources reserved for kubernetes system components. Currently only cpu, memory, pid and local ephemeral storage for root file system are supported. See https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ for more detail. [default=none]")
fs.StringSliceVar(&c.EnforceNodeAllocatable, "enforce-node-allocatable", c.EnforceNodeAllocatable, "A comma separated list of levels of node allocatable enforcement to be enforced by kubelet. Acceptable options are 'none', 'pods', 'system-reserved', and 'kube-reserved'. If the latter two options are specified, '--system-reserved-cgroup' and '--kube-reserved-cgroup' must also be set, respectively. If 'none' is specified, no additional options should be set. See https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/ for more details.") fs.StringSliceVar(&c.EnforceNodeAllocatable, "enforce-node-allocatable", c.EnforceNodeAllocatable, "A comma separated list of levels of node allocatable enforcement to be enforced by kubelet. Acceptable options are 'none', 'pods', 'system-reserved', 'system-reserved-compressible', 'kube-reserved' and 'kube-reserved-compressible'. If any of the latter four options are specified, '--system-reserved-cgroup' and '--kube-reserved-cgroup' must also be set, respectively. If 'none' is specified, no additional options should be set. See https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/ for more details.")
fs.StringVar(&c.SystemReservedCgroup, "system-reserved-cgroup", c.SystemReservedCgroup, "Absolute name of the top level cgroup that is used to manage non-kubernetes components for which compute resources were reserved via '--system-reserved' flag. Ex. '/system-reserved'. [default='']") fs.StringVar(&c.SystemReservedCgroup, "system-reserved-cgroup", c.SystemReservedCgroup, "Absolute name of the top level cgroup that is used to manage non-kubernetes components for which compute resources were reserved via '--system-reserved' flag. Ex. '/system-reserved'. [default='']")
fs.StringVar(&c.KubeReservedCgroup, "kube-reserved-cgroup", c.KubeReservedCgroup, "Absolute name of the top level cgroup that is used to manage kubernetes components for which compute resources were reserved via '--kube-reserved' flag. Ex. '/kube-reserved'. [default='']") fs.StringVar(&c.KubeReservedCgroup, "kube-reserved-cgroup", c.KubeReservedCgroup, "Absolute name of the top level cgroup that is used to manage kubernetes components for which compute resources were reserved via '--kube-reserved' flag. Ex. '/kube-reserved'. [default='']")
logsapi.AddFlags(&c.Logging, fs) logsapi.AddFlags(&c.Logging, fs)

View File

@ -801,6 +801,7 @@ func run(ctx context.Context, s *options.KubeletServer, kubeDeps *kubelet.Depend
if err != nil { if err != nil {
return fmt.Errorf("--system-reserved value failed to parse: %w", err) return fmt.Errorf("--system-reserved value failed to parse: %w", err)
} }
var hardEvictionThresholds []evictionapi.Threshold var hardEvictionThresholds []evictionapi.Threshold
// If the user requested to ignore eviction thresholds, then do not set valid values for hardEvictionThresholds here. // If the user requested to ignore eviction thresholds, then do not set valid values for hardEvictionThresholds here.
if !s.ExperimentalNodeAllocatableIgnoreEvictionThreshold { if !s.ExperimentalNodeAllocatableIgnoreEvictionThreshold {

View File

@ -203,6 +203,26 @@ func ValidateKubeletConfiguration(kc *kubeletconfig.KubeletConfiguration, featur
allErrors = append(allErrors, fmt.Errorf("invalid configuration: memorySwap.swapBehavior cannot be set when NodeSwap feature flag is disabled")) allErrors = append(allErrors, fmt.Errorf("invalid configuration: memorySwap.swapBehavior cannot be set when NodeSwap feature flag is disabled"))
} }
// Check for mutually exclusive keys before the main validation loop
reservedKeys := map[string]bool{
kubetypes.SystemReservedEnforcementKey: false,
kubetypes.SystemReservedCompressibleEnforcementKey: false,
kubetypes.KubeReservedEnforcementKey: false,
kubetypes.KubeReservedCompressibleEnforcementKey: false,
}
for _, val := range kc.EnforceNodeAllocatable {
reservedKeys[val] = true
}
if reservedKeys[kubetypes.SystemReservedCompressibleEnforcementKey] && reservedKeys[kubetypes.SystemReservedEnforcementKey] {
allErrors = append(allErrors, fmt.Errorf("invalid configuration: both %q and %q cannot be specified together in enforceNodeAllocatable (--enforce-node-allocatable)", kubetypes.SystemReservedEnforcementKey, kubetypes.SystemReservedCompressibleEnforcementKey))
}
if reservedKeys[kubetypes.KubeReservedCompressibleEnforcementKey] && reservedKeys[kubetypes.KubeReservedEnforcementKey] {
allErrors = append(allErrors, fmt.Errorf("invalid configuration: both %q and %q cannot be specified together in enforceNodeAllocatable (--enforce-node-allocatable)", kubetypes.KubeReservedEnforcementKey, kubetypes.KubeReservedCompressibleEnforcementKey))
}
uniqueEnforcements := sets.Set[string]{} uniqueEnforcements := sets.Set[string]{}
for _, val := range kc.EnforceNodeAllocatable { for _, val := range kc.EnforceNodeAllocatable {
if uniqueEnforcements.Has(val) { if uniqueEnforcements.Has(val) {
@ -213,13 +233,13 @@ func ValidateKubeletConfiguration(kc *kubeletconfig.KubeletConfiguration, featur
switch val { switch val {
case kubetypes.NodeAllocatableEnforcementKey: case kubetypes.NodeAllocatableEnforcementKey:
case kubetypes.SystemReservedEnforcementKey: case kubetypes.SystemReservedEnforcementKey, kubetypes.SystemReservedCompressibleEnforcementKey:
if kc.SystemReservedCgroup == "" { if kc.SystemReservedCgroup == "" {
allErrors = append(allErrors, fmt.Errorf("invalid configuration: systemReservedCgroup (--system-reserved-cgroup) must be specified when %q contained in enforceNodeAllocatable (--enforce-node-allocatable)", kubetypes.SystemReservedEnforcementKey)) allErrors = append(allErrors, fmt.Errorf("invalid configuration: systemReservedCgroup (--system-reserved-cgroup) must be specified when %q or %q included in enforceNodeAllocatable (--enforce-node-allocatable)", kubetypes.SystemReservedEnforcementKey, kubetypes.SystemReservedCompressibleEnforcementKey))
} }
case kubetypes.KubeReservedEnforcementKey: case kubetypes.KubeReservedEnforcementKey, kubetypes.KubeReservedCompressibleEnforcementKey:
if kc.KubeReservedCgroup == "" { if kc.KubeReservedCgroup == "" {
allErrors = append(allErrors, fmt.Errorf("invalid configuration: kubeReservedCgroup (--kube-reserved-cgroup) must be specified when %q contained in enforceNodeAllocatable (--enforce-node-allocatable)", kubetypes.KubeReservedEnforcementKey)) allErrors = append(allErrors, fmt.Errorf("invalid configuration: kubeReservedCgroup (--kube-reserved-cgroup) must be specified when %q or %q included in enforceNodeAllocatable (--enforce-node-allocatable)", kubetypes.KubeReservedEnforcementKey, kubetypes.KubeReservedCompressibleEnforcementKey))
} }
case kubetypes.NodeAllocatableNoneKey: case kubetypes.NodeAllocatableNoneKey:
if len(kc.EnforceNodeAllocatable) > 1 { if len(kc.EnforceNodeAllocatable) > 1 {
@ -228,8 +248,9 @@ func ValidateKubeletConfiguration(kc *kubeletconfig.KubeletConfiguration, featur
// skip all further checks when this is explicitly "none" // skip all further checks when this is explicitly "none"
continue continue
default: default:
allErrors = append(allErrors, fmt.Errorf("invalid configuration: option %q specified for enforceNodeAllocatable (--enforce-node-allocatable). Valid options are %q, %q, %q, or %q", allErrors = append(allErrors, fmt.Errorf("invalid configuration: option %q specified for enforceNodeAllocatable (--enforce-node-allocatable). Valid options are %q, %q, %q, %q, %q or %q",
val, kubetypes.NodeAllocatableEnforcementKey, kubetypes.SystemReservedEnforcementKey, kubetypes.KubeReservedEnforcementKey, kubetypes.NodeAllocatableNoneKey)) val, kubetypes.NodeAllocatableEnforcementKey, kubetypes.SystemReservedEnforcementKey, kubetypes.SystemReservedCompressibleEnforcementKey,
kubetypes.KubeReservedEnforcementKey, kubetypes.KubeReservedCompressibleEnforcementKey, kubetypes.NodeAllocatableNoneKey))
continue continue
} }

View File

@ -383,7 +383,30 @@ func TestValidateKubeletConfiguration(t *testing.T) {
conf.SystemReservedCgroup = "" conf.SystemReservedCgroup = ""
return conf return conf
}, },
errMsg: "invalid configuration: systemReservedCgroup (--system-reserved-cgroup) must be specified when \"system-reserved\" contained in enforceNodeAllocatable (--enforce-node-allocatable)", errMsg: "invalid configuration: systemReservedCgroup (--system-reserved-cgroup) must be specified when \"system-reserved\" or \"system-reserved-compressible\" included in enforceNodeAllocatable (--enforce-node-allocatable)",
}, {
name: "specify SystemReservedCompressibleEnforcementKey without specifying SystemReservedCgroup",
configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
conf.EnforceNodeAllocatable = []string{kubetypes.SystemReservedCompressibleEnforcementKey}
conf.SystemReservedCgroup = ""
return conf
},
errMsg: "invalid configuration: systemReservedCgroup (--system-reserved-cgroup) must be specified when \"system-reserved\" or \"system-reserved-compressible\" included in enforceNodeAllocatable (--enforce-node-allocatable)",
}, {
name: "specify SystemReservedCompressibleEnforcementKey with SystemReservedEnforcementKey",
configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
conf.EnforceNodeAllocatable = []string{kubetypes.SystemReservedCompressibleEnforcementKey, kubetypes.SystemReservedEnforcementKey}
return conf
},
errMsg: "invalid configuration: both \"system-reserved\" and \"system-reserved-compressible\" cannot be specified together in enforceNodeAllocatable (--enforce-node-allocatable)",
}, {
name: "specify KubeReservedCompressibleEnforcementKey without specifying KubeReservedCgroup",
configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
conf.EnforceNodeAllocatable = []string{kubetypes.KubeReservedCompressibleEnforcementKey}
conf.KubeReservedCgroup = ""
return conf
},
errMsg: "invalid configuration: kubeReservedCgroup (--kube-reserved-cgroup) must be specified when \"kube-reserved\" or \"kube-reserved-compressible\" included in enforceNodeAllocatable (--enforce-node-allocatable)",
}, { }, {
name: "specify KubeReservedEnforcementKey without specifying KubeReservedCgroup", name: "specify KubeReservedEnforcementKey without specifying KubeReservedCgroup",
configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration { configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
@ -391,7 +414,14 @@ func TestValidateKubeletConfiguration(t *testing.T) {
conf.KubeReservedCgroup = "" conf.KubeReservedCgroup = ""
return conf return conf
}, },
errMsg: "invalid configuration: kubeReservedCgroup (--kube-reserved-cgroup) must be specified when \"kube-reserved\" contained in enforceNodeAllocatable (--enforce-node-allocatable)", errMsg: "invalid configuration: kubeReservedCgroup (--kube-reserved-cgroup) must be specified when \"kube-reserved\" or \"kube-reserved-compressible\" included in enforceNodeAllocatable (--enforce-node-allocatable)",
}, {
name: "specify KubeReservedCompressibleEnforcementKey with KubeReservedEnforcementKey",
configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
conf.EnforceNodeAllocatable = []string{kubetypes.KubeReservedCompressibleEnforcementKey, kubetypes.KubeReservedEnforcementKey}
return conf
},
errMsg: "invalid configuration: both \"kube-reserved\" and \"kube-reserved-compressible\" cannot be specified together in enforceNodeAllocatable (--enforce-node-allocatable)",
}, { }, {
name: "specify NodeAllocatableNoneKey with additional enforcements", name: "specify NodeAllocatableNoneKey with additional enforcements",
configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration { configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
@ -412,7 +442,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
conf.EnforceNodeAllocatable = []string{"invalid-enforce-node-allocatable"} conf.EnforceNodeAllocatable = []string{"invalid-enforce-node-allocatable"}
return conf return conf
}, },
errMsg: "invalid configuration: option \"invalid-enforce-node-allocatable\" specified for enforceNodeAllocatable (--enforce-node-allocatable). Valid options are \"pods\", \"system-reserved\", \"kube-reserved\", or \"none\"", errMsg: "invalid configuration: option \"invalid-enforce-node-allocatable\" specified for enforceNodeAllocatable (--enforce-node-allocatable). Valid options are \"pods\", \"system-reserved\", \"system-reserved-compressible\", \"kube-reserved\", \"kube-reserved-compressible\" or \"none\"",
}, { }, {
name: "invalid HairpinMode", name: "invalid HairpinMode",
configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration { configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {

View File

@ -53,7 +53,7 @@ func (cm *containerManagerImpl) createNodeAllocatableCgroups() error {
cgroupConfig := &CgroupConfig{ cgroupConfig := &CgroupConfig{
Name: cm.cgroupRoot, Name: cm.cgroupRoot,
// The default limits for cpu shares can be very low which can lead to CPU starvation for pods. // The default limits for cpu shares can be very low which can lead to CPU starvation for pods.
ResourceParameters: getCgroupConfig(nodeAllocatable), ResourceParameters: getCgroupConfig(nodeAllocatable, false),
} }
if cm.cgroupManager.Exists(cgroupConfig.Name) { if cm.cgroupManager.Exists(cgroupConfig.Name) {
return nil return nil
@ -81,7 +81,7 @@ func (cm *containerManagerImpl) enforceNodeAllocatableCgroups() error {
cgroupConfig := &CgroupConfig{ cgroupConfig := &CgroupConfig{
Name: cm.cgroupRoot, Name: cm.cgroupRoot,
ResourceParameters: getCgroupConfig(nodeAllocatable), ResourceParameters: getCgroupConfig(nodeAllocatable, false),
} }
// Using ObjectReference for events as the node maybe not cached; refer to #42701 for detail. // Using ObjectReference for events as the node maybe not cached; refer to #42701 for detail.
@ -110,7 +110,7 @@ func (cm *containerManagerImpl) enforceNodeAllocatableCgroups() error {
// Now apply kube reserved and system reserved limits if required. // Now apply kube reserved and system reserved limits if required.
if nc.EnforceNodeAllocatable.Has(kubetypes.SystemReservedEnforcementKey) { if nc.EnforceNodeAllocatable.Has(kubetypes.SystemReservedEnforcementKey) {
klog.V(2).InfoS("Enforcing system reserved on cgroup", "cgroupName", nc.SystemReservedCgroupName, "limits", nc.SystemReserved) klog.V(2).InfoS("Enforcing system reserved on cgroup", "cgroupName", nc.SystemReservedCgroupName, "limits", nc.SystemReserved)
if err := enforceExistingCgroup(cm.cgroupManager, cm.cgroupManager.CgroupName(nc.SystemReservedCgroupName), nc.SystemReserved); err != nil { if err := enforceExistingCgroup(cm.cgroupManager, cm.cgroupManager.CgroupName(nc.SystemReservedCgroupName), nc.SystemReserved, false); err != nil {
message := fmt.Sprintf("Failed to enforce System Reserved Cgroup Limits on %q: %v", nc.SystemReservedCgroupName, err) message := fmt.Sprintf("Failed to enforce System Reserved Cgroup Limits on %q: %v", nc.SystemReservedCgroupName, err)
cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message) cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message)
return errors.New(message) return errors.New(message)
@ -119,19 +119,40 @@ func (cm *containerManagerImpl) enforceNodeAllocatableCgroups() error {
} }
if nc.EnforceNodeAllocatable.Has(kubetypes.KubeReservedEnforcementKey) { if nc.EnforceNodeAllocatable.Has(kubetypes.KubeReservedEnforcementKey) {
klog.V(2).InfoS("Enforcing kube reserved on cgroup", "cgroupName", nc.KubeReservedCgroupName, "limits", nc.KubeReserved) klog.V(2).InfoS("Enforcing kube reserved on cgroup", "cgroupName", nc.KubeReservedCgroupName, "limits", nc.KubeReserved)
if err := enforceExistingCgroup(cm.cgroupManager, cm.cgroupManager.CgroupName(nc.KubeReservedCgroupName), nc.KubeReserved); err != nil { if err := enforceExistingCgroup(cm.cgroupManager, cm.cgroupManager.CgroupName(nc.KubeReservedCgroupName), nc.KubeReserved, false); err != nil {
message := fmt.Sprintf("Failed to enforce Kube Reserved Cgroup Limits on %q: %v", nc.KubeReservedCgroupName, err) message := fmt.Sprintf("Failed to enforce Kube Reserved Cgroup Limits on %q: %v", nc.KubeReservedCgroupName, err)
cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message) cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message)
return errors.New(message) return errors.New(message)
} }
cm.recorder.Eventf(nodeRef, v1.EventTypeNormal, events.SuccessfulNodeAllocatableEnforcement, "Updated limits on kube reserved cgroup %v", nc.KubeReservedCgroupName) cm.recorder.Eventf(nodeRef, v1.EventTypeNormal, events.SuccessfulNodeAllocatableEnforcement, "Updated limits on kube reserved cgroup %v", nc.KubeReservedCgroupName)
} }
if nc.EnforceNodeAllocatable.Has(kubetypes.SystemReservedCompressibleEnforcementKey) {
klog.V(2).InfoS("Enforcing system reserved compressible on cgroup", "cgroupName", nc.SystemReservedCgroupName, "limits", nc.SystemReserved)
if err := enforceExistingCgroup(cm.cgroupManager, cm.cgroupManager.CgroupName(nc.SystemReservedCgroupName), nc.SystemReserved, true); err != nil {
message := fmt.Sprintf("Failed to enforce System Reserved Compressible Cgroup Limits on %q: %v", nc.SystemReservedCgroupName, err)
cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message)
return errors.New(message)
}
cm.recorder.Eventf(nodeRef, v1.EventTypeNormal, events.SuccessfulNodeAllocatableEnforcement, "Updated limits on system reserved cgroup %v", nc.SystemReservedCgroupName)
}
if nc.EnforceNodeAllocatable.Has(kubetypes.KubeReservedCompressibleEnforcementKey) {
klog.V(2).InfoS("Enforcing kube reserved compressible on cgroup", "cgroupName", nc.KubeReservedCgroupName, "limits", nc.KubeReserved)
if err := enforceExistingCgroup(cm.cgroupManager, cm.cgroupManager.CgroupName(nc.KubeReservedCgroupName), nc.KubeReserved, true); err != nil {
message := fmt.Sprintf("Failed to enforce Kube Reserved Compressible Cgroup Limits on %q: %v", nc.KubeReservedCgroupName, err)
cm.recorder.Event(nodeRef, v1.EventTypeWarning, events.FailedNodeAllocatableEnforcement, message)
return errors.New(message)
}
cm.recorder.Eventf(nodeRef, v1.EventTypeNormal, events.SuccessfulNodeAllocatableEnforcement, "Updated limits on kube reserved cgroup %v", nc.KubeReservedCgroupName)
}
return nil return nil
} }
// enforceExistingCgroup updates the limits `rl` on existing cgroup `cName` using `cgroupManager` interface. // enforceExistingCgroup updates the limits `rl` on existing cgroup `cName` using `cgroupManager` interface.
func enforceExistingCgroup(cgroupManager CgroupManager, cName CgroupName, rl v1.ResourceList) error { func enforceExistingCgroup(cgroupManager CgroupManager, cName CgroupName, rl v1.ResourceList, compressibleResources bool) error {
rp := getCgroupConfig(rl) rp := getCgroupConfig(rl, compressibleResources)
if rp == nil { if rp == nil {
return fmt.Errorf("%q cgroup is not configured properly", cName) return fmt.Errorf("%q cgroup is not configured properly", cName)
} }
@ -162,27 +183,39 @@ func enforceExistingCgroup(cgroupManager CgroupManager, cName CgroupName, rl v1.
} }
// getCgroupConfig returns a ResourceConfig object that can be used to create or update cgroups via CgroupManager interface. // getCgroupConfig returns a ResourceConfig object that can be used to create or update cgroups via CgroupManager interface.
func getCgroupConfig(rl v1.ResourceList) *ResourceConfig { func getCgroupConfig(rl v1.ResourceList, compressibleResourcesOnly bool) *ResourceConfig {
// TODO(vishh): Set CPU Quota if necessary. // TODO(vishh): Set CPU Quota if necessary.
if rl == nil { if rl == nil {
return nil return nil
} }
var rc ResourceConfig var rc ResourceConfig
if q, exists := rl[v1.ResourceMemory]; exists {
// Memory is defined in bytes. setCompressibleResources := func() {
val := q.Value()
rc.Memory = &val
}
if q, exists := rl[v1.ResourceCPU]; exists { if q, exists := rl[v1.ResourceCPU]; exists {
// CPU is defined in milli-cores. // CPU is defined in milli-cores.
val := MilliCPUToShares(q.MilliValue()) val := MilliCPUToShares(q.MilliValue())
rc.CPUShares = &val rc.CPUShares = &val
} }
}
// Only return compressible resources
if compressibleResourcesOnly {
setCompressibleResources()
} else {
if q, exists := rl[v1.ResourceMemory]; exists {
// Memory is defined in bytes.
val := q.Value()
rc.Memory = &val
}
setCompressibleResources()
if q, exists := rl[pidlimit.PIDs]; exists { if q, exists := rl[pidlimit.PIDs]; exists {
val := q.Value() val := q.Value()
rc.PidsLimit = &val rc.PidsLimit = &val
} }
rc.HugePageLimit = HugePageLimits(rl) rc.HugePageLimit = HugePageLimits(rl)
}
return &rc return &rc
} }

View File

@ -23,7 +23,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api" evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api"
) )
@ -401,3 +401,65 @@ func getEphemeralStorageResourceList(storage string) v1.ResourceList {
} }
return res return res
} }
func TestGetCgroupConfig(t *testing.T) {
cases := []struct {
name string
resourceList v1.ResourceList
compressibleResources bool
checks func(*ResourceConfig, *testing.T)
}{
{
name: "Nil resource list",
resourceList: nil,
compressibleResources: false,
checks: func(actual *ResourceConfig, t *testing.T) {
assert.Nil(t, actual)
},
},
{
name: "Compressible resources only",
resourceList: v1.ResourceList{
v1.ResourceCPU: resource.MustParse("100m"),
v1.ResourceMemory: resource.MustParse("200Mi"),
},
compressibleResources: true,
checks: func(actual *ResourceConfig, t *testing.T) {
assert.NotNil(t, actual.CPUShares)
assert.Nil(t, actual.Memory)
assert.Nil(t, actual.PidsLimit)
assert.Nil(t, actual.HugePageLimit)
},
},
{
name: "Memory only",
resourceList: v1.ResourceList{
v1.ResourceMemory: resource.MustParse("200Mi"),
},
compressibleResources: false,
checks: func(actual *ResourceConfig, t *testing.T) {
assert.NotNil(t, actual.Memory)
assert.Nil(t, actual.CPUShares)
},
},
{
name: "Memory and CPU without compressible resources",
resourceList: v1.ResourceList{
v1.ResourceCPU: resource.MustParse("100m"),
v1.ResourceMemory: resource.MustParse("200Mi"),
},
compressibleResources: false,
checks: func(actual *ResourceConfig, t *testing.T) {
assert.NotNil(t, actual.Memory)
assert.NotNil(t, actual.CPUShares)
},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
actual := getCgroupConfig(tc.resourceList, tc.compressibleResources)
tc.checks(actual, t)
})
}
}

View File

@ -25,7 +25,9 @@ const (
const ( const (
NodeAllocatableEnforcementKey = "pods" NodeAllocatableEnforcementKey = "pods"
SystemReservedEnforcementKey = "system-reserved" SystemReservedEnforcementKey = "system-reserved"
SystemReservedCompressibleEnforcementKey = "system-reserved-compressible"
KubeReservedEnforcementKey = "kube-reserved" KubeReservedEnforcementKey = "kube-reserved"
KubeReservedCompressibleEnforcementKey = "kube-reserved-compressible"
NodeAllocatableNoneKey = "none" NodeAllocatableNoneKey = "none"
) )