Skip to content

Commit ca26b91

Browse files
committed
add max pods, simplify warm IP pool management
1 parent babd43f commit ca26b91

File tree

4 files changed

+202
-169
lines changed

4 files changed

+202
-169
lines changed

pkg/ipamd/datastore/data_store.go

+3-8
Original file line numberDiff line numberDiff line change
@@ -841,8 +841,7 @@ func (ds *DataStore) GetEFAENIs() map[string]bool {
841841
return ret
842842
}
843843

844-
// IsRequiredForWarmIPTarget determines if this ENI has warm IPs that are required to fulfill whatever WARM_IP_TARGET is
845-
// set to.
844+
// IsRequiredForWarmIPTarget determines if this ENI has warm IPs that are required to fulfill whatever WARM_IP_TARGET is set to.
846845
func (ds *DataStore) isRequiredForWarmIPTarget(warmIPTarget int, eni *ENI) bool {
847846
otherWarmIPs := 0
848847
for _, other := range ds.eniPool {
@@ -863,8 +862,7 @@ func (ds *DataStore) isRequiredForWarmIPTarget(warmIPTarget int, eni *ENI) bool
863862
return otherWarmIPs < warmIPTarget
864863
}
865864

866-
// IsRequiredForMinimumIPTarget determines if this ENI is necessary to fulfill whatever MINIMUM_IP_TARGET is
867-
// set to.
865+
// IsRequiredForMinimumIPTarget determines if this ENI is necessary to fulfill whatever MINIMUM_IP_TARGET is set to.
868866
func (ds *DataStore) isRequiredForMinimumIPTarget(minimumIPTarget int, eni *ENI) bool {
869867
otherIPs := 0
870868
for _, other := range ds.eniPool {
@@ -885,8 +883,7 @@ func (ds *DataStore) isRequiredForMinimumIPTarget(minimumIPTarget int, eni *ENI)
885883
return otherIPs < minimumIPTarget
886884
}
887885

888-
// IsRequiredForWarmPrefixTarget determines if this ENI is necessary to fulfill whatever WARM_PREFIX_TARGET is
889-
// set to.
886+
// IsRequiredForWarmPrefixTarget determines if this ENI is necessary to fulfill whatever WARM_PREFIX_TARGET is set to.
890887
func (ds *DataStore) isRequiredForWarmPrefixTarget(warmPrefixTarget int, eni *ENI) bool {
891888
freePrefixes := 0
892889
for _, other := range ds.eniPool {
@@ -1007,7 +1004,6 @@ func (ds *DataStore) RemoveUnusedENIFromStore(warmIPTarget, minimumIPTarget, war
10071004
}
10081005

10091006
removableENI := deletableENI.ID
1010-
10111007
for _, availableCidr := range ds.eniPool[removableENI].AvailableIPv4Cidrs {
10121008
ds.total -= availableCidr.Size()
10131009
if availableCidr.IsPrefix {
@@ -1277,7 +1273,6 @@ func (ds *DataStore) GetFreePrefixes() int {
12771273
freePrefixes++
12781274
}
12791275
}
1280-
12811276
}
12821277
return freePrefixes
12831278
}

pkg/ipamd/datastore/data_store_test.go

+56-21
Original file line numberDiff line numberDiff line change
@@ -1024,63 +1024,98 @@ func TestWarmENIInteractions(t *testing.T) {
10241024
_ = ds.AddENI("eni-2", 2, false, false, false)
10251025
_ = ds.AddENI("eni-3", 3, false, false, false)
10261026

1027+
// Add an IP address to ENI 1 and assign it to a pod
10271028
ipv4Addr := net.IPNet{IP: net.ParseIP("1.1.1.1"), Mask: net.IPv4Mask(255, 255, 255, 255)}
10281029
_ = ds.AddIPv4CidrToStore("eni-1", ipv4Addr, false)
10291030
key1 := IPAMKey{"net0", "sandbox-1", "eth0"}
10301031
_, _, err := ds.AssignPodIPv4Address(key1, IPAMMetadata{K8SPodNamespace: "default", K8SPodName: "sample-pod-1"})
10311032
assert.NoError(t, err)
10321033

1034+
// Add another IP address to ENI 1 and assign a pod
10331035
ipv4Addr = net.IPNet{IP: net.ParseIP("1.1.1.2"), Mask: net.IPv4Mask(255, 255, 255, 255)}
10341036
_ = ds.AddIPv4CidrToStore("eni-1", ipv4Addr, false)
10351037
key2 := IPAMKey{"net0", "sandbox-2", "eth0"}
10361038
_, _, err = ds.AssignPodIPv4Address(key2, IPAMMetadata{K8SPodNamespace: "default", K8SPodName: "sample-pod-2"})
10371039
assert.NoError(t, err)
10381040

1041+
// Add two IP addresses to ENI 2 and one IP address to ENI 3
10391042
ipv4Addr = net.IPNet{IP: net.ParseIP("1.1.2.1"), Mask: net.IPv4Mask(255, 255, 255, 255)}
10401043
_ = ds.AddIPv4CidrToStore("eni-2", ipv4Addr, false)
10411044
ipv4Addr = net.IPNet{IP: net.ParseIP("1.1.2.2"), Mask: net.IPv4Mask(255, 255, 255, 255)}
10421045
_ = ds.AddIPv4CidrToStore("eni-2", ipv4Addr, false)
10431046
ipv4Addr = net.IPNet{IP: net.ParseIP("1.1.3.1"), Mask: net.IPv4Mask(255, 255, 255, 255)}
10441047
_ = ds.AddIPv4CidrToStore("eni-3", ipv4Addr, false)
10451048

1046-
noWarmIPTarget := 0
1047-
10481049
ds.eniPool["eni-2"].createTime = time.Time{}
10491050
ds.eniPool["eni-3"].createTime = time.Time{}
10501051

1051-
// We have three ENIs, 5 IPs and two pods on ENI 1. Each ENI can handle two pods.
1052+
// We have 3 ENIs, 5 IPs and 2 pods on ENI 1.
1053+
// ENI 1: 2 IPs allocated, 2 IPs in use
1054+
// ENI 2: 2 IPs allocated, 0 IPs in use
1055+
// ENI 3: 1 IP allocated, 0 IPs in use
1056+
// => 3 free IPs
10521057
// We should not be able to remove any ENIs if either warmIPTarget >= 3 or minimumWarmIPTarget >= 5
1058+
1059+
// WARM IP TARGET=3, MINIMUM_IP_TARGET=1 => no ENI should be removed
10531060
eni := ds.RemoveUnusedENIFromStore(3, 1, 0)
10541061
assert.Equal(t, "", eni)
1055-
// Should not be able to free this ENI because we want at least 5 IPs, which requires at least three ENIs
1062+
1063+
// WARM IP TARGET=1, MINIMUM_IP_TARGET=5 => no ENI should be removed
10561064
eni = ds.RemoveUnusedENIFromStore(1, 5, 0)
10571065
assert.Equal(t, "", eni)
1058-
// Should be able to free an ENI because both warmIPTarget and minimumWarmIPTarget are both effectively 4
1066+
1067+
// WARM IP TARGET=2, MINIMUM_IP_TARGET=4 => ENI 3 should be removed as we only need 2 free IPs, which ENI 2 has
10591068
removedEni := ds.RemoveUnusedENIFromStore(2, 4, 0)
1060-
assert.Contains(t, []string{"eni-2", "eni-3"}, removedEni)
1069+
assert.Equal(t, "eni-3", removedEni)
10611070

1062-
// Should not be able to free an ENI because minimumWarmIPTarget requires at least two ENIs and no warm IP target
1063-
eni = ds.RemoveUnusedENIFromStore(noWarmIPTarget, 3, 0)
1064-
assert.Equal(t, "", eni)
1065-
// Should be able to free an ENI because one ENI can provide a minimum count of 2 IPs
1066-
secondRemovedEni := ds.RemoveUnusedENIFromStore(noWarmIPTarget, 2, 0)
1067-
assert.Contains(t, []string{"eni-2", "eni-3"}, secondRemovedEni)
1071+
// We have 2 ENIs, 4 IPs and 2 pods on ENI 1.
1072+
// ENI 1: 2 IPs allocated, 2 IPs in use
1073+
// ENI 2: 2 IPs allocated, 0 IPs in use
1074+
// => 2 free IPs
10681075

1069-
assert.NotEqual(t, removedEni, secondRemovedEni, "The two removed ENIs should not be the same ENI.")
1076+
// WARM IP TARGET=0, MINIMUM_IP_TARGET=3 => no ENI should be removed
1077+
eni = ds.RemoveUnusedENIFromStore(0, 3, 0)
1078+
assert.Equal(t, "", eni)
10701079

1071-
_ = ds.AddENI("eni-4", 3, false, true, false)
1072-
_ = ds.AddENI("eni-5", 3, false, false, true)
1080+
// WARM IP TARGET=0, MINIMUM_IP_TARGET=2 => ENI 2 should be removed as ENI 1 covers the requirements
1081+
removedEni = ds.RemoveUnusedENIFromStore(0, 2, 0)
1082+
assert.Contains(t, "eni-2", removedEni)
10731083

1084+
// Add 2 more ENIs to the datastore and add 1 IP address to each of them
1085+
ds.AddENI("eni-4", 4, false, true, false) // trunk ENI
1086+
ds.AddENI("eni-5", 5, false, false, true) // EFA ENI
10741087
ipv4Addr = net.IPNet{IP: net.ParseIP("1.1.4.1"), Mask: net.IPv4Mask(255, 255, 255, 255)}
1075-
_ = ds.AddIPv4CidrToStore("eni-4", ipv4Addr, false)
1088+
ds.AddIPv4CidrToStore("eni-4", ipv4Addr, false)
10761089
ipv4Addr = net.IPNet{IP: net.ParseIP("1.1.5.1"), Mask: net.IPv4Mask(255, 255, 255, 255)}
1077-
_ = ds.AddIPv4CidrToStore("eni-5", ipv4Addr, false)
1078-
1090+
ds.AddIPv4CidrToStore("eni-5", ipv4Addr, false)
10791091
ds.eniPool["eni-4"].createTime = time.Time{}
10801092
ds.eniPool["eni-5"].createTime = time.Time{}
1081-
thirdRemovedEni := ds.RemoveUnusedENIFromStore(noWarmIPTarget, 2, 0)
1082-
// None of the others can be removed...
1083-
assert.Equal(t, "", thirdRemovedEni)
1093+
1094+
// We have 3 ENIs, 4 IPs and 2 pods on ENI 1.
1095+
// ENI 1: 2 IPs allocated, 2 IPs in use
1096+
// ENI 4: 1 IPs allocated, 0 IPs in use
1097+
// ENI 5: 1 IPs allocated, 0 IPs in use
1098+
// => 2 free IPs
1099+
1100+
// WARM IP TARGET=0, MINIMUM_IP_TARGET=2 => no ENI can be removed because ENI 4 is a trunk ENI and ENI 5 is an EFA ENI
1101+
removedEni = ds.RemoveUnusedENIFromStore(0, 2, 0)
1102+
assert.Equal(t, "", removedEni)
1103+
assert.Equal(t, 3, ds.GetENIs())
1104+
1105+
// Add 1 more normal ENI to the datastore
1106+
ds.AddENI("eni-6", 6, false, false, false) // trunk ENI
1107+
ds.eniPool["eni-6"].createTime = time.Time{}
1108+
1109+
// We have 4 ENIs, 4 IPs and 2 pods on ENI 1.
1110+
// ENI 1: 2 IPs allocated, 2 IPs in use
1111+
// ENI 4: 1 IPs allocated, 0 IPs in use
1112+
// ENI 5: 1 IPs allocated, 0 IPs in use
1113+
// ENI 6: 0 IPs allocated, 0 IPs in use
1114+
// => 2 free IPs
1115+
1116+
// WARM IP TARGET=0, MINIMUM_IP_TARGET=2 => ENI 6 can be removed
1117+
removedEni = ds.RemoveUnusedENIFromStore(0, 2, 0)
1118+
assert.Equal(t, "eni-6", removedEni)
10841119
assert.Equal(t, 3, ds.GetENIs())
10851120
}
10861121

0 commit comments

Comments
 (0)