pkg/config/loader.go (156 lines of code) (raw):
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
package config
import (
"strconv"
"github.com/go-logr/logr"
v1 "k8s.io/api/core/v1"
)
const (
// TODO: Should we always do this max retry no matter why it fails
// such deleted pods will also be retried 5 times, which could be an issue for large pods loads and high churning rate.
WorkQueueDefaultMaxRetries = 5
// Default Configuration for Pod ENI resource type
PodENIDefaultWorker = 30
// Default Windows Configuration for IPv4 resource type
IPv4DefaultWinWorkerCount = 2
IPv4DefaultWinWarmIPTarget = 3
IPv4DefaultWinMinIPTarget = 3
IPv4DefaultWinMaxDev = 0
IPv4DefaultWinResSize = 0
// Default Windows Configuration for IPv4 prefix resource type
IPv4PDDefaultWorker = 2
IPv4PDDefaultWPSize = 1
IPv4PDDefaultMaxDev = 0
IPv4PDDefaultResSize = 0
IPv4PDDefaultWarmIPTargetSize = 1
IPv4PDDefaultMinIPTargetSize = 3
IPv4PDDefaultWarmPrefixTargetSize = 0
)
// LoadResourceConfig returns the Resource Configuration for all resources managed by the VPC Resource Controller. Currently
// returns the default resource configuration and later can return the configuration from a ConfigMap.
func LoadResourceConfig() map[string]ResourceConfig {
return getDefaultResourceConfig()
}
func LoadResourceConfigFromConfigMap(log logr.Logger, vpcCniConfigMap *v1.ConfigMap) map[string]ResourceConfig {
resourceConfig := getDefaultResourceConfig()
warmIPTarget, minIPTarget, warmPrefixTarget, isPDEnabled := ParseWinIPTargetConfigs(log, vpcCniConfigMap)
// If no PD configuration is set in configMap or none is valid, return default resource config
if warmIPTarget == 0 && minIPTarget == 0 && warmPrefixTarget == 0 {
return resourceConfig
}
if isPDEnabled {
resourceConfig[ResourceNameIPAddressFromPrefix].WarmPoolConfig.WarmIPTarget = warmIPTarget
resourceConfig[ResourceNameIPAddressFromPrefix].WarmPoolConfig.MinIPTarget = minIPTarget
resourceConfig[ResourceNameIPAddressFromPrefix].WarmPoolConfig.WarmPrefixTarget = warmPrefixTarget
} else {
resourceConfig[ResourceNameIPAddress].WarmPoolConfig.WarmIPTarget = warmIPTarget
resourceConfig[ResourceNameIPAddress].WarmPoolConfig.MinIPTarget = minIPTarget
}
return resourceConfig
}
// ParseWinIPTargetConfigs parses Windows IP target configuration parameters in the amazon-vpc-cni ConfigMap
// If all three config parameter values (warm-ip-target, min-ip-target, warm-prefix-target) are 0 or unset, or config map does not exist,
// then default values for warm-ip-target and min-ip-target will be set.
func ParseWinIPTargetConfigs(log logr.Logger, vpcCniConfigMap *v1.ConfigMap) (warmIPTarget int, minIPTarget int, warmPrefixTarget int, isPDEnabled bool) {
if vpcCniConfigMap.Data == nil {
warmIPTarget = IPv4DefaultWinWarmIPTarget
minIPTarget = IPv4DefaultWinMinIPTarget
log.Info(
"No ConfigMap data found, falling back to using default values",
"minIPTarget", minIPTarget,
"warmIPTarget", warmIPTarget,
)
return warmIPTarget, minIPTarget, 0, false
}
isPDEnabled, err := strconv.ParseBool(vpcCniConfigMap.Data[EnableWindowsPrefixDelegationKey])
if err != nil {
log.Info("Could not parse prefix delegation flag from ConfigMap, falling back to using secondary IP mode")
isPDEnabled = false
}
warmIPTargetStr, foundWarmIP := vpcCniConfigMap.Data[WarmIPTarget]
if !foundWarmIP {
warmIPTargetStr, foundWarmIP = vpcCniConfigMap.Data[WinWarmIPTarget]
}
minIPTargetStr, foundMinIP := vpcCniConfigMap.Data[MinimumIPTarget]
if !foundMinIP {
minIPTargetStr, foundMinIP = vpcCniConfigMap.Data[WinMinimumIPTarget]
}
warmPrefixTargetStr, foundWarmPrefix := vpcCniConfigMap.Data[WarmPrefixTarget]
if !foundWarmPrefix {
warmPrefixTargetStr, foundWarmPrefix = vpcCniConfigMap.Data[WinWarmPrefixTarget]
}
// If warm IP target config value is not found, or there is an error parsing it, the value will be set to zero
if foundWarmIP {
warmIPTarget, err = strconv.Atoi(warmIPTargetStr)
if err != nil {
log.Info("Could not parse warm ip target, defaulting to zero", "warm ip target", warmIPTargetStr)
} else if !isPDEnabled && warmIPTarget == 0 {
// Handle secondary IP mode scenario where WarmIPTarget is explicitly configured to zero
// In such a case there must always be 1 warm IP to ensure that the warmpool is never empty
log.Info("Explicitly setting WarmIPTarget zero value not supported in secondary IP mode, will override with 1")
warmIPTarget = 1
}
} else {
log.Info("could not find warm ip target in ConfigMap, defaulting to zero")
warmIPTarget = 0
}
// If min IP target config value is not found, or there is an error parsing it, the value will be set to zero
if foundMinIP {
minIPTarget, err = strconv.Atoi(minIPTargetStr)
if err != nil {
log.Info("Could not parse minimum ip target, defaulting to zero", "minimum ip target", minIPTargetStr)
}
} else {
log.Info("could not find minimum ip target in ConfigMap, defaulting to zero")
minIPTarget = 0
}
warmPrefixTarget = 0
if isPDEnabled && foundWarmPrefix {
warmPrefixTarget, err = strconv.Atoi(warmPrefixTargetStr)
if err != nil {
log.Info("Could not parse warm prefix target, defaulting to zero", "warm prefix target", warmPrefixTargetStr)
}
}
if warmIPTarget == 0 && minIPTarget == 0 {
if isPDEnabled && warmPrefixTarget == 0 {
minIPTarget = IPv4PDDefaultMinIPTargetSize
warmIPTarget = IPv4PDDefaultWarmIPTargetSize
warmPrefixTarget = IPv4PDDefaultWarmPrefixTargetSize
} else if !isPDEnabled {
minIPTarget = IPv4DefaultWinMinIPTarget
warmIPTarget = IPv4DefaultWinWarmIPTarget
}
log.Info(
"Encountered zero values for warm-ip-target, min-ip-target and warm-prefix-target in ConfigMap data, falling back to using default values since on demand IP allocation is not supported",
"minIPTarget", minIPTarget,
"warmIPTarget", warmIPTarget,
"warmPrefixTarget", warmPrefixTarget,
"isPDEnabled", isPDEnabled,
)
}
return warmIPTarget, minIPTarget, warmPrefixTarget, isPDEnabled
}
// getDefaultResourceConfig returns the default Resource Configuration.
func getDefaultResourceConfig() map[string]ResourceConfig {
config := make(map[string]ResourceConfig)
// Create default configuration for Pod ENI Resource
podENIConfig := ResourceConfig{
Name: ResourceNamePodENI,
WorkerCount: PodENIDefaultWorker,
SupportedOS: map[string]bool{OSWindows: false, OSLinux: true},
WarmPoolConfig: nil,
}
config[ResourceNamePodENI] = podENIConfig
// Create default configuration for IPv4 Resource
ipV4WarmPoolConfig := WarmPoolConfig{
DesiredSize: IPv4DefaultWinWarmIPTarget,
WarmIPTarget: IPv4DefaultWinWarmIPTarget,
MinIPTarget: IPv4DefaultWinMinIPTarget,
MaxDeviation: IPv4DefaultWinMaxDev,
ReservedSize: IPv4DefaultWinResSize,
}
ipV4Config := ResourceConfig{
Name: ResourceNameIPAddress,
WorkerCount: IPv4DefaultWinWorkerCount,
SupportedOS: map[string]bool{OSWindows: true, OSLinux: false},
WarmPoolConfig: &ipV4WarmPoolConfig,
}
config[ResourceNameIPAddress] = ipV4Config
// Create default configuration for prefix-deconstructed IPv4 resource pool
prefixIPv4WarmPoolConfig := WarmPoolConfig{
DesiredSize: IPv4PDDefaultWPSize,
MaxDeviation: IPv4PDDefaultMaxDev,
ReservedSize: IPv4PDDefaultResSize,
WarmIPTarget: IPv4PDDefaultWarmIPTargetSize,
MinIPTarget: IPv4PDDefaultMinIPTargetSize,
WarmPrefixTarget: IPv4PDDefaultWarmPrefixTargetSize,
}
prefixIPv4Config := ResourceConfig{
Name: ResourceNameIPAddressFromPrefix,
WorkerCount: IPv4PDDefaultWorker,
SupportedOS: map[string]bool{OSWindows: true, OSLinux: false},
WarmPoolConfig: &prefixIPv4WarmPoolConfig,
}
config[ResourceNameIPAddressFromPrefix] = prefixIPv4Config
return config
}