Skip to content

Commit 3598972

Browse files
committed
Add Windows secondary IP mode configurable options for managing IP address allocation #443
1 parent 020d23a commit 3598972

File tree

14 files changed

+816
-151
lines changed

14 files changed

+816
-151
lines changed

controllers/core/configmap_controller.go

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ type ConfigMapReconciler struct {
4646
Condition condition.Conditions
4747
curWinIPAMEnabledCond bool
4848
curWinPrefixDelegationEnabledCond bool
49-
curWinPDWarmIPTarget int
50-
curWinPDMinIPTarget int
49+
curWinWarmIPTarget int
50+
curWinMinIPTarget int
5151
curWinPDWarmPrefixTarget int
5252
Context context.Context
5353
}
@@ -116,21 +116,34 @@ func (r *ConfigMapReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
116116
isPrefixFlagUpdated = true
117117
}
118118

119-
// Check if configurations for Windows prefix delegation have changed
120-
var isPDConfigUpdated bool
121-
warmIPTarget, minIPTarget, warmPrefixTarget := config.ParseWinPDTargets(r.Log, configmap)
122-
if r.curWinPDWarmIPTarget != warmIPTarget || r.curWinPDMinIPTarget != minIPTarget || r.curWinPDWarmPrefixTarget != warmPrefixTarget {
123-
r.curWinPDWarmIPTarget = warmIPTarget
124-
r.curWinPDMinIPTarget = minIPTarget
125-
r.curWinPDWarmPrefixTarget = warmPrefixTarget
126-
logger.Info("updated PD configs from configmap", config.WarmIPTarget, r.curWinPDWarmIPTarget,
127-
config.MinimumIPTarget, r.curWinPDMinIPTarget, config.WarmPrefixTarget, r.curWinPDWarmPrefixTarget)
119+
// Check if Windows IP target configurations in ConfigMap have changed
120+
var isWinIPConfigsUpdated bool
128121

129-
isPDConfigUpdated = true
122+
warmIPTarget, minIPTarget, warmPrefixTarget, isPDEnabled := config.ParseWinIPTargetConfigs(r.Log, configmap)
123+
var winMinIPTargetUpdated = r.curWinMinIPTarget != minIPTarget
124+
var winWarmIPTargetUpdated = r.curWinWarmIPTarget != warmIPTarget
125+
var winPDWarmPrefixTargetUpdated = r.curWinPDWarmPrefixTarget != warmPrefixTarget
126+
if winWarmIPTargetUpdated || winMinIPTargetUpdated {
127+
r.curWinWarmIPTarget = warmIPTarget
128+
r.curWinMinIPTarget = minIPTarget
129+
r.curWinPDWarmPrefixTarget = warmPrefixTarget
130+
isWinIPConfigsUpdated = true
131+
}
132+
if isPDEnabled && winPDWarmPrefixTargetUpdated {
133+
isWinIPConfigsUpdated = true
134+
}
135+
if isWinIPConfigsUpdated {
136+
logger.Info(
137+
"Detected update in Windows IP configuration parameter values in ConfigMap",
138+
config.WinWarmIPTarget, r.curWinWarmIPTarget,
139+
config.WinMinimumIPTarget, r.curWinMinIPTarget,
140+
config.WinWarmPrefixTarget, r.curWinPDWarmPrefixTarget,
141+
config.EnableWindowsPrefixDelegationKey, isPDEnabled,
142+
)
130143
}
131144

132-
// Flag is updated, update all nodes
133-
if isIPAMFlagUpdated || isPrefixFlagUpdated || isPDConfigUpdated {
145+
var nodesRequireUpdate = isIPAMFlagUpdated || isPrefixFlagUpdated || isWinIPConfigsUpdated
146+
if nodesRequireUpdate {
134147
err := UpdateNodesOnConfigMapChanges(r.K8sAPI, r.NodeManager)
135148
if err != nil {
136149
// Error in updating nodes

controllers/core/configmap_controller_test.go

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,9 @@ package controllers
1616
import (
1717
"context"
1818
"errors"
19+
"strconv"
1920
"testing"
2021

21-
mock_condition "github.com/aws/amazon-vpc-resource-controller-k8s/mocks/amazon-vcp-resource-controller-k8s/pkg/condition"
22-
mock_k8s "github.com/aws/amazon-vpc-resource-controller-k8s/mocks/amazon-vcp-resource-controller-k8s/pkg/k8s"
23-
mock_node "github.com/aws/amazon-vpc-resource-controller-k8s/mocks/amazon-vcp-resource-controller-k8s/pkg/node"
24-
mock_manager "github.com/aws/amazon-vpc-resource-controller-k8s/mocks/amazon-vcp-resource-controller-k8s/pkg/node/manager"
25-
"github.com/aws/amazon-vpc-resource-controller-k8s/pkg/config"
26-
cooldown "github.com/aws/amazon-vpc-resource-controller-k8s/pkg/provider/branch/cooldown"
2722
"github.com/golang/mock/gomock"
2823
"github.com/stretchr/testify/assert"
2924
corev1 "k8s.io/api/core/v1"
@@ -35,18 +30,35 @@ import (
3530
fakeClient "sigs.k8s.io/controller-runtime/pkg/client/fake"
3631
"sigs.k8s.io/controller-runtime/pkg/log/zap"
3732
"sigs.k8s.io/controller-runtime/pkg/reconcile"
33+
34+
mock_condition "github.com/aws/amazon-vpc-resource-controller-k8s/mocks/amazon-vcp-resource-controller-k8s/pkg/condition"
35+
mock_k8s "github.com/aws/amazon-vpc-resource-controller-k8s/mocks/amazon-vcp-resource-controller-k8s/pkg/k8s"
36+
mock_node "github.com/aws/amazon-vpc-resource-controller-k8s/mocks/amazon-vcp-resource-controller-k8s/pkg/node"
37+
mock_manager "github.com/aws/amazon-vpc-resource-controller-k8s/mocks/amazon-vcp-resource-controller-k8s/pkg/node/manager"
38+
"github.com/aws/amazon-vpc-resource-controller-k8s/pkg/config"
39+
cooldown "github.com/aws/amazon-vpc-resource-controller-k8s/pkg/provider/branch/cooldown"
3840
)
3941

4042
var (
4143
mockConfigMap = &corev1.ConfigMap{
4244
TypeMeta: metav1.TypeMeta{},
4345
ObjectMeta: metav1.ObjectMeta{Name: config.VpcCniConfigMapName, Namespace: config.KubeSystemNamespace},
44-
Data: map[string]string{config.EnableWindowsIPAMKey: "true", config.EnableWindowsPrefixDelegationKey: "true"},
46+
Data: map[string]string{
47+
config.EnableWindowsIPAMKey: "true",
48+
config.EnableWindowsPrefixDelegationKey: "true",
49+
config.WinMinimumIPTarget: strconv.Itoa(config.IPv4DefaultWinMinIPTarget),
50+
config.WinWarmIPTarget: strconv.Itoa(config.IPv4DefaultWinWarmIPTarget),
51+
},
4552
}
4653
mockConfigMapPD = &corev1.ConfigMap{
4754
TypeMeta: metav1.TypeMeta{},
4855
ObjectMeta: metav1.ObjectMeta{Name: config.VpcCniConfigMapName, Namespace: config.KubeSystemNamespace},
49-
Data: map[string]string{config.EnableWindowsIPAMKey: "false", config.EnableWindowsPrefixDelegationKey: "true"},
56+
Data: map[string]string{
57+
config.EnableWindowsIPAMKey: "false",
58+
config.EnableWindowsPrefixDelegationKey: "true",
59+
config.WinMinimumIPTarget: strconv.Itoa(config.IPv4PDDefaultMinIPTargetSize),
60+
config.WinWarmIPTarget: strconv.Itoa(config.IPv4PDDefaultWarmIPTargetSize),
61+
},
5062
}
5163
mockConfigMapReq = reconcile.Request{
5264
NamespacedName: types.NamespacedName{
@@ -89,11 +101,13 @@ func NewConfigMapMock(ctrl *gomock.Controller, mockObjects ...client.Object) Con
89101
return ConfigMapMock{
90102
MockNodeManager: mockNodeManager,
91103
ConfigMapReconciler: &ConfigMapReconciler{
92-
Client: client,
93-
Log: zap.New(),
94-
NodeManager: mockNodeManager,
95-
K8sAPI: mockK8sWrapper,
96-
Condition: mockCondition,
104+
Client: client,
105+
Log: zap.New(),
106+
NodeManager: mockNodeManager,
107+
K8sAPI: mockK8sWrapper,
108+
Condition: mockCondition,
109+
curWinMinIPTarget: config.IPv4DefaultWinMinIPTarget,
110+
curWinWarmIPTarget: config.IPv4DefaultWinWarmIPTarget,
97111
},
98112
MockNode: mockNode,
99113
MockK8sAPI: mockK8sWrapper,

pkg/config/loader.go

Lines changed: 71 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@ const (
2828
// Default Configuration for Pod ENI resource type
2929
PodENIDefaultWorker = 30
3030

31-
// Default Configuration for IPv4 resource type
32-
IPv4DefaultWorker = 2
33-
IPv4DefaultWPSize = 3
34-
IPv4DefaultMaxDev = 1
35-
IPv4DefaultResSize = 0
36-
37-
// Default Configuration for IPv4 prefix resource type
31+
// Default Windows Configuration for IPv4 resource type
32+
IPv4DefaultWinWorkerCount = 2
33+
IPv4DefaultWinWarmIPTarget = 1
34+
IPv4DefaultWinMinIPTarget = 3
35+
IPv4DefaultWinMaxDev = 0
36+
IPv4DefaultWinResSize = 0
37+
38+
// Default Windows Configuration for IPv4 prefix resource type
3839
IPv4PDDefaultWorker = 2
3940
IPv4PDDefaultWPSize = 1
4041
IPv4PDDefaultMaxDev = 0
@@ -70,26 +71,43 @@ func LoadResourceConfig() map[string]ResourceConfig {
7071
func LoadResourceConfigFromConfigMap(log logr.Logger, vpcCniConfigMap *v1.ConfigMap) map[string]ResourceConfig {
7172
resourceConfig := getDefaultResourceConfig()
7273

73-
warmIPTarget, minIPTarget, warmPrefixTarget := ParseWinPDTargets(log, vpcCniConfigMap)
74+
warmIPTarget, minIPTarget, warmPrefixTarget, isPDEnabled := ParseWinIPTargetConfigs(log, vpcCniConfigMap)
7475

7576
// If no PD configuration is set in configMap or none is valid, return default resource config
7677
if warmIPTarget == 0 && minIPTarget == 0 && warmPrefixTarget == 0 {
7778
return resourceConfig
7879
}
7980

80-
resourceConfig[ResourceNameIPAddressFromPrefix].WarmPoolConfig.WarmIPTarget = warmIPTarget
81-
resourceConfig[ResourceNameIPAddressFromPrefix].WarmPoolConfig.MinIPTarget = minIPTarget
82-
resourceConfig[ResourceNameIPAddressFromPrefix].WarmPoolConfig.WarmPrefixTarget = warmPrefixTarget
81+
if isPDEnabled {
82+
resourceConfig[ResourceNameIPAddressFromPrefix].WarmPoolConfig.WarmIPTarget = warmIPTarget
83+
resourceConfig[ResourceNameIPAddressFromPrefix].WarmPoolConfig.MinIPTarget = minIPTarget
84+
resourceConfig[ResourceNameIPAddressFromPrefix].WarmPoolConfig.WarmPrefixTarget = warmPrefixTarget
85+
} else {
86+
resourceConfig[ResourceNameIPAddress].WarmPoolConfig.WarmIPTarget = warmIPTarget
87+
resourceConfig[ResourceNameIPAddress].WarmPoolConfig.MinIPTarget = minIPTarget
88+
resourceConfig[ResourceNameIPAddress].WarmPoolConfig.WarmPrefixTarget = warmPrefixTarget // ignore warm prefix in secondary IP mode
89+
}
8390

8491
return resourceConfig
8592
}
8693

87-
// ParseWinPDTargets parses config map for Windows prefix delegation configurations set by users
88-
func ParseWinPDTargets(log logr.Logger, vpcCniConfigMap *v1.ConfigMap) (warmIPTarget int, minIPTarget int, warmPrefixTarget int) {
94+
// ParseWinIPTargetConfigs parses Windows IP target configuration parameters in the amazon-vpc-cni ConfigMap
95+
func ParseWinIPTargetConfigs(log logr.Logger, vpcCniConfigMap *v1.ConfigMap) (warmIPTarget int, minIPTarget int, warmPrefixTarget int, isPDEnabled bool) {
8996
warmIPTarget, minIPTarget, warmPrefixTarget = 0, 0, 0
9097

9198
if vpcCniConfigMap.Data == nil {
92-
return warmIPTarget, minIPTarget, warmPrefixTarget
99+
log.V(1).Info("No configuration found in ConfigMap, falling back to using secondary IP mode with default values")
100+
isPDEnabled = false
101+
minIPTarget = IPv4DefaultWinMinIPTarget
102+
warmIPTarget = IPv4DefaultWinWarmIPTarget
103+
warmPrefixTarget = 0
104+
return warmIPTarget, minIPTarget, warmPrefixTarget, isPDEnabled
105+
}
106+
107+
isPDEnabled, err := strconv.ParseBool(vpcCniConfigMap.Data[EnableWindowsPrefixDelegationKey])
108+
if err != nil {
109+
log.V(1).Info("Failed to parse prefix delegation flag from ConfigMap, falling back to using secondary IP mode")
110+
isPDEnabled = false
93111
}
94112

95113
warmIPTargetStr, foundWarmIP := vpcCniConfigMap.Data[WarmIPTarget]
@@ -105,36 +123,59 @@ func ParseWinPDTargets(log logr.Logger, vpcCniConfigMap *v1.ConfigMap) (warmIPTa
105123
warmPrefixTargetStr, foundWarmPrefix = vpcCniConfigMap.Data[WinWarmPrefixTarget]
106124
}
107125

108-
// If no configuration is found, return 0
109-
if !foundWarmIP && !foundMinIP && !foundWarmPrefix {
110-
return warmIPTarget, minIPTarget, warmPrefixTarget
111-
}
112-
126+
// Handle the scenario where warm IP target is not configured
113127
if foundWarmIP {
114128
warmIPTargetInt, err := strconv.Atoi(warmIPTargetStr)
115129
if err != nil {
116-
log.Error(err, "failed to parse warm ip target", "warm ip target", warmIPTargetStr)
130+
log.Error(err, "failed to parse warm ip target, defaulting to zero", "warm ip target", warmIPTargetStr)
131+
warmIPTarget = 0
117132
} else {
118133
warmIPTarget = warmIPTargetInt
119134
}
135+
} else {
136+
log.V(1).Info("warm IP configuration not found in ConfigMap, will use default value")
137+
if isPDEnabled {
138+
warmIPTarget = IPv4PDDefaultWarmIPTargetSize
139+
} else {
140+
warmIPTarget = IPv4DefaultWinWarmIPTarget
141+
}
120142
}
143+
144+
// Handle the scenario where minimum IP target is not configured
121145
if foundMinIP {
122146
minIPTargetInt, err := strconv.Atoi(minIPTargetStr)
123147
if err != nil {
124-
log.Error(err, "failed to parse minimum ip target", "minimum ip target", minIPTargetStr)
148+
log.Error(err, "failed to parse minimum ip target, defaulting to zero", "minimum ip target", minIPTargetStr)
149+
minIPTarget = 0
125150
} else {
126151
minIPTarget = minIPTargetInt
127152
}
153+
} else {
154+
log.V(1).Info("minimum IP configuration not found in ConfigMap, will use default value")
155+
if isPDEnabled {
156+
minIPTarget = IPv4PDDefaultMinIPTargetSize
157+
} else {
158+
minIPTarget = IPv4DefaultWinMinIPTarget
159+
}
128160
}
129-
if foundWarmPrefix {
161+
162+
// Handle the scenario where warm prefix target is not configured
163+
if !isPDEnabled && foundWarmPrefix {
164+
log.V(1).Info("warm prefix configuration not supported in secondary IP mode, will ignore warm prefix configuration")
165+
} else if isPDEnabled && foundWarmPrefix {
130166
warmPrefixTargetInt, err := strconv.Atoi(warmPrefixTargetStr)
131167
if err != nil {
132-
log.Error(err, "failed to parse warm prefix target", "warm prefix target", warmPrefixTargetStr)
168+
log.Error(err, "failed to parse warm prefix target, defaulting to zero", "warm prefix target", warmPrefixTargetStr)
169+
warmPrefixTarget = 0
133170
} else {
134171
warmPrefixTarget = warmPrefixTargetInt
135172
}
173+
} else if isPDEnabled && !foundWarmPrefix {
174+
log.V(1).Info("warm prefix configuration not found in ConfigMap, will use default value")
175+
warmPrefixTarget = IPv4PDDefaultWarmPrefixTargetSize
136176
}
137-
return warmIPTarget, minIPTarget, warmPrefixTarget
177+
178+
return warmIPTarget, minIPTarget, warmPrefixTarget, isPDEnabled
138179
}
139180

140181
// getDefaultResourceConfig returns the default Resource Configuration.
@@ -153,13 +194,15 @@ func getDefaultResourceConfig() map[string]ResourceConfig {
153194

154195
// Create default configuration for IPv4 Resource
155196
ipV4WarmPoolConfig := WarmPoolConfig{
156-
DesiredSize: IPv4DefaultWPSize,
157-
MaxDeviation: IPv4DefaultMaxDev,
158-
ReservedSize: IPv4DefaultResSize,
197+
DesiredSize: IPv4DefaultWinWarmIPTarget,
198+
WarmIPTarget: IPv4DefaultWinWarmIPTarget,
199+
MinIPTarget: IPv4DefaultWinMinIPTarget,
200+
MaxDeviation: IPv4DefaultWinMaxDev,
201+
ReservedSize: IPv4DefaultWinResSize,
159202
}
160203
ipV4Config := ResourceConfig{
161204
Name: ResourceNameIPAddress,
162-
WorkerCount: IPv4DefaultWorker,
205+
WorkerCount: IPv4DefaultWinWorkerCount,
163206
SupportedOS: map[string]bool{OSWindows: true, OSLinux: false},
164207
WarmPoolConfig: &ipV4WarmPoolConfig,
165208
}

0 commit comments

Comments
 (0)