memory manager: provide new flag var to parse reserved-memory parameter

The new flag will parse the `--reserved-memory` flag straight forward
to the []kubeletconfig.MemoryReservation variable instead of parsing
it to the middle map representation.

It gives us possibility to get rid of a lot of unneeded code and use the single
presentation for the reserved-memory.

Signed-off-by: Artyom Lukianov <alukiano@redhat.com>
This commit is contained in:
Artyom Lukianov
2020-11-18 00:19:36 +02:00
parent b7cfc40deb
commit 7561a0f96e
12 changed files with 249 additions and 418 deletions

View File

@@ -18,7 +18,6 @@ go_library(
"//cmd/kubelet/app/options:go_default_library",
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/v1/helper:go_default_library",
"//pkg/capabilities:go_default_library",
"//pkg/cloudprovider/providers:go_default_library",
"//pkg/credentialprovider:go_default_library",

View File

@@ -554,5 +554,5 @@ Runtime log sanitization may introduce significant computation overhead and ther
// Memory Manager Flags
fs.StringVar(&c.MemoryManagerPolicy, "memory-manager-policy", c.MemoryManagerPolicy, "Memory Manager policy to use. Possible values: 'none', 'static'. Default: 'none'")
// TODO: once documentation link is available, replace KEP link with the documentation one.
fs.Var(cliflag.NewBracketSeparatedSliceMapStringString(&c.ReservedMemory), "reserved-memory", "A comma separated list of bracket-enclosed configuration for memory manager (e.g. {numa-node=0, type=memory, limit=1Gi}, {numa-node=1, type=memory, limit=1Gi}). The total sum for each memory type should be equal to the sum of kube-reserved, system-reserved and eviction-threshold. See more details under https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/1769-memory-manager#reserved-memory-flag")
fs.Var(&utilflag.ReservedMemoryVar{Value: &c.ReservedMemory}, "reserved-memory", "A comma separated list of memory reservations for NUMA nodes. (e.g. --reserved-memory 0:memory=1Gi,hugepages-1M=2Gi --reserved-memory 1:memory=2Gi). The total sum for each memory type should be equal to the sum of kube-reserved, system-reserved and eviction-threshold. See more details under https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/1769-memory-manager#reserved-memory-flag")
}

View File

@@ -71,7 +71,6 @@ import (
"k8s.io/kubernetes/cmd/kubelet/app/options"
"k8s.io/kubernetes/pkg/api/legacyscheme"
api "k8s.io/kubernetes/pkg/apis/core"
corev1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
"k8s.io/kubernetes/pkg/capabilities"
"k8s.io/kubernetes/pkg/credentialprovider"
"k8s.io/kubernetes/pkg/features"
@@ -689,11 +688,6 @@ func run(ctx context.Context, s *options.KubeletServer, kubeDeps *kubelet.Depend
klog.Infof("After cpu setting is overwritten, KubeReserved=\"%v\", SystemReserved=\"%v\"", s.KubeReserved, s.SystemReserved)
}
reservedMemory, err := parseReservedMemoryConfig(s.ReservedMemory)
if err != nil {
return err
}
kubeReserved, err := parseResourceList(s.KubeReserved)
if err != nil {
return err
@@ -743,7 +737,7 @@ func run(ctx context.Context, s *options.KubeletServer, kubeDeps *kubelet.Depend
ExperimentalCPUManagerPolicy: s.CPUManagerPolicy,
ExperimentalCPUManagerReconcilePeriod: s.CPUManagerReconcilePeriod.Duration,
ExperimentalMemoryManagerPolicy: s.MemoryManagerPolicy,
ExperimentalMemoryManagerReservedMemory: reservedMemory,
ExperimentalMemoryManagerReservedMemory: s.ReservedMemory,
ExperimentalPodPidsLimit: s.PodPidsLimit,
EnforceCPULimits: s.CPUCFSQuota,
CPUCFSQuotaPeriod: s.CPUCFSQuotaPeriod.Duration,
@@ -1305,59 +1299,6 @@ func parseResourceList(m map[string]string) (v1.ResourceList, error) {
return rl, nil
}
func parseReservedMemoryConfig(config []map[string]string) (kubetypes.NUMANodeResources, error) {
if len(config) == 0 {
return nil, nil
}
const (
indexKey = "numa-node"
typeKey = "type"
limitKey = "limit"
)
keys := []string{indexKey, typeKey, limitKey}
// check whether all keys are present
for _, m := range config {
for _, key := range keys {
if _, exist := m[key]; !exist {
return nil, fmt.Errorf("key: %s is missing in given ReservedMemory flag: %v", key, config)
}
}
}
parsed := make(kubetypes.NUMANodeResources, len(config))
for _, m := range config {
idxInString, _ := m[indexKey]
idx, err := strconv.Atoi(idxInString)
if err != nil || idx < 0 {
return nil, fmt.Errorf("NUMA index conversion error for value: \"%s\"", idxInString)
}
typeInString, _ := m[typeKey]
v1Type := v1.ResourceName(typeInString)
if v1Type != v1.ResourceMemory && !corev1helper.IsHugePageResourceName(v1Type) {
return nil, fmt.Errorf("memory type conversion error, unknown type: \"%s\"", typeInString)
}
if corev1helper.IsHugePageResourceName(v1Type) {
if _, err := corev1helper.HugePageSizeFromResourceName(v1Type); err != nil {
return nil, fmt.Errorf("memory type conversion error, unknown type: \"%s\"", typeInString)
}
}
limitInString, _ := m[limitKey]
limit, err := resource.ParseQuantity(limitInString)
if err != nil || limit.Sign() != 1 {
return nil, fmt.Errorf("memory limit conversion error for value \"%s\"", limitInString)
}
parsed[idx] = make(map[v1.ResourceName]resource.Quantity)
parsed[idx][v1Type] = limit
}
return parsed, nil
}
// BootstrapKubeletConfigController constructs and bootstrap a configuration controller
func BootstrapKubeletConfigController(dynamicConfigDir string, transform dynamickubeletconfig.TransformFunc) (*kubeletconfiginternal.KubeletConfiguration, *dynamickubeletconfig.Controller, error) {
if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) {

View File

@@ -61,60 +61,3 @@ func TestValueOfAllocatableResources(t *testing.T) {
}
}
}
func TestValueOfReservedMemoryConfig(t *testing.T) {
testCases := []struct {
config []map[string]string
errorExpected bool
name string
}{
{
config: []map[string]string{{"numa-node": "0", "type": "memory", "limit": "2Gi"}},
errorExpected: false,
name: "Valid resource quantity",
},
{
config: []map[string]string{{"numa-node": "0", "type": "memory", "limit": "2000m"}, {"numa-node": "1", "type": "memory", "limit": "1Gi"}},
errorExpected: false,
name: "Valid resource quantity",
},
{
config: []map[string]string{{"type": "memory", "limit": "2Gi"}},
errorExpected: true,
name: "Missing key",
},
{
config: []map[string]string{{"numa-node": "one", "type": "memory", "limit": "2Gi"}},
errorExpected: true,
name: "Wrong 'numa-node' value",
},
{
config: []map[string]string{{"numa-node": "0", "type": "not-memory", "limit": "2Gi"}},
errorExpected: true,
name: "Wrong 'memory' value",
},
{
config: []map[string]string{{"numa-node": "0", "type": "memory", "limit": "2Gigs"}},
errorExpected: true,
name: "Wrong 'limit' value",
},
{
config: []map[string]string{{"numa-node": "-1", "type": "memory", "limit": "2Gigs"}},
errorExpected: true,
name: "Invalid 'numa-node' number",
},
}
for _, test := range testCases {
_, err := parseReservedMemoryConfig(test.config)
if test.errorExpected {
if err == nil {
t.Errorf("%s: error expected", test.name)
}
} else {
if err != nil {
t.Errorf("%s: unexpected error: %v", test.name, err)
}
}
}
}