@@ -16,21 +16,23 @@ type CNSIPAMPoolMonitor struct {
1616 pendingRelease bool
1717
1818 cachedNNC nnc.NodeNetworkConfig
19+ updatingIpsNotInUseCount int
1920 scalarUnits nnc.Scaler
2021
21- cns cns.HTTPService
22+ httpService cns.HTTPService
2223 rc requestcontroller.RequestController
2324 MinimumFreeIps int64
2425 MaximumFreeIps int64
2526
2627 mu sync.RWMutex
2728}
2829
29- func NewCNSIPAMPoolMonitor (cns cns.HTTPService , rc requestcontroller.RequestController ) * CNSIPAMPoolMonitor {
30+ func NewCNSIPAMPoolMonitor (httpService cns.HTTPService , rc requestcontroller.RequestController ) * CNSIPAMPoolMonitor {
31+ logger .Printf ("NewCNSIPAMPoolMonitor: Create IPAM Pool Monitor" )
3032 return & CNSIPAMPoolMonitor {
31- pendingRelease : false ,
32- cns : cns ,
33- rc : rc ,
33+ pendingRelease : false ,
34+ httpService : httpService ,
35+ rc : rc ,
3436 }
3537}
3638
@@ -52,7 +54,7 @@ func (pm *CNSIPAMPoolMonitor) Start(ctx context.Context, poolMonitorRefreshMilli
5254 for {
5355 select {
5456 case <- ctx .Done ():
55- return fmt .Errorf ("CNS IPAM Pool Monitor received cancellation signal" )
57+ return fmt .Errorf ("[ipam-pool-monitor] CNS IPAM Pool Monitor received cancellation signal" )
5658 case <- ticker .C :
5759 err := pm .Reconcile ()
5860 if err != nil {
@@ -63,14 +65,14 @@ func (pm *CNSIPAMPoolMonitor) Start(ctx context.Context, poolMonitorRefreshMilli
6365}
6466
6567func (pm * CNSIPAMPoolMonitor ) Reconcile () error {
66- cnsPodIPConfigCount := len (pm .cns .GetPodIPConfigState ())
67- pendingProgramCount := len (pm .cns .GetPendingProgramIPConfigs ()) // TODO: add pending program count to real cns
68- allocatedPodIPCount := len (pm .cns .GetAllocatedIPConfigs ())
69- pendingReleaseIPCount := len (pm .cns .GetPendingReleaseIPConfigs ())
70- availableIPConfigCount := len (pm .cns .GetAvailableIPConfigs ()) // TODO: add pending allocation count to real cns
68+ cnsPodIPConfigCount := len (pm .httpService .GetPodIPConfigState ())
69+ pendingProgramCount := len (pm .httpService .GetPendingProgramIPConfigs ()) // TODO: add pending program count to real cns
70+ allocatedPodIPCount := len (pm .httpService .GetAllocatedIPConfigs ())
71+ pendingReleaseIPCount := len (pm .httpService .GetPendingReleaseIPConfigs ())
72+ availableIPConfigCount := len (pm .httpService .GetAvailableIPConfigs ()) // TODO: add pending allocation count to real cns
7173 freeIPConfigCount := pm .cachedNNC .Spec .RequestedIPCount - int64 (allocatedPodIPCount )
7274
73- msg := fmt .Sprintf ("Pool Size: %v, Goal Size: %v, BatchSize: %v, MinFree: %v, MaxFree:%v, Allocated: %v, Available: %v, Pending Release: %v, Free: %v, Pending Program: %v" ,
75+ msg := fmt .Sprintf ("[ipam-pool-monitor] Pool Size: %v, Goal Size: %v, BatchSize: %v, MinFree: %v, MaxFree:%v, Allocated: %v, Available: %v, Pending Release: %v, Free: %v, Pending Program: %v" ,
7476 cnsPodIPConfigCount , pm .cachedNNC .Spec .RequestedIPCount , pm .scalarUnits .BatchSize , pm .MinimumFreeIps , pm .MaximumFreeIps , allocatedPodIPCount , availableIPConfigCount , pendingReleaseIPCount , freeIPConfigCount , pendingProgramCount )
7577
7678 switch {
@@ -82,7 +84,7 @@ func (pm *CNSIPAMPoolMonitor) Reconcile() error {
8284 // pod count is decreasing
8385 case freeIPConfigCount > pm .MaximumFreeIps :
8486 logger .Printf ("[ipam-pool-monitor] Decreasing pool size...%s " , msg )
85- return pm .decreasePoolSize ()
87+ return pm .decreasePoolSize (pendingReleaseIPCount )
8688
8789 // CRD has reconciled CNS state, and target spec is now the same size as the state
8890 // free to remove the IP's from the CRD
@@ -100,8 +102,8 @@ func (pm *CNSIPAMPoolMonitor) Reconcile() error {
100102}
101103
102104func (pm * CNSIPAMPoolMonitor ) increasePoolSize () error {
103- pm .mu .Lock ()
104105 defer pm .mu .Unlock ()
106+ pm .mu .Lock ()
105107
106108 var err error
107109 var tempNNCSpec nnc.NodeNetworkConfigSpec
@@ -111,58 +113,79 @@ func (pm *CNSIPAMPoolMonitor) increasePoolSize() error {
111113 }
112114
113115 tempNNCSpec .RequestedIPCount += pm .scalarUnits .BatchSize
114- logger .Printf ("[ipam-pool-monitor] Increasing pool size, Current Pool Size: %v, Updated Requested IP Count: %v, Pods with IP's:%v, ToBeDeleted Count: %v" , len (pm .cns .GetPodIPConfigState ()), tempNNCSpec .RequestedIPCount , len (pm .cns .GetAllocatedIPConfigs ()), len (tempNNCSpec .IPsNotInUse ))
116+ logger .Printf ("[ipam-pool-monitor] Increasing pool size, Current Pool Size: %v, Updated Requested IP Count: %v, Pods with IP's:%v, ToBeDeleted Count: %v" , len (pm .httpService .GetPodIPConfigState ()), tempNNCSpec .RequestedIPCount , len (pm .httpService .GetAllocatedIPConfigs ()), len (tempNNCSpec .IPsNotInUse ))
115117
116118 err = pm .rc .UpdateCRDSpec (context .Background (), tempNNCSpec )
117119 if err != nil {
118120 // caller will retry to update the CRD again
119121 return err
120122 }
121123
124+ logger .Printf ("[ipam-pool-monitor] Increasing pool size: UpdateCRDSpec succeeded for spec %+v" , tempNNCSpec )
122125 // save the updated state to cachedSpec
123126 pm .cachedNNC .Spec = tempNNCSpec
124127 return nil
125128}
126129
127- func (pm * CNSIPAMPoolMonitor ) decreasePoolSize () error {
128- pm .mu .Lock ()
130+ func (pm * CNSIPAMPoolMonitor ) decreasePoolSize (existingPendingReleaseIPCount int ) error {
129131 defer pm .mu .Unlock ()
132+ pm .mu .Lock ()
130133
131134 // mark n number of IP's as pending
132- pendingIpAddresses , err := pm .cns .MarkIPAsPendingRelease (int (pm .scalarUnits .BatchSize ))
133- if err != nil {
134- return err
135- }
135+ var err error
136+ var newIpsMarkedAsPending bool
137+ var pendingIpAddresses map [string ]cns.IPConfigurationStatus
138+ if pm .updatingIpsNotInUseCount == 0 ||
139+ pm .updatingIpsNotInUseCount < existingPendingReleaseIPCount {
140+ logger .Printf ("[ipam-pool-monitor] Marking IPs as PendingRelease, ipsToBeReleasedCount %d" , int (pm .scalarUnits .BatchSize ))
141+ pendingIpAddresses , err = pm .httpService .MarkIPAsPendingRelease (int (pm .scalarUnits .BatchSize ))
142+ if err != nil {
143+ return err
144+ }
136145
137- totalIpsSetForRelease := len ( pendingIpAddresses )
138- logger . Printf ( "[ipam-pool-monitor] Releasing IPCount in this batch %d" , totalIpsSetForRelease )
146+ newIpsMarkedAsPending = true
147+ }
139148
140149 var tempNNCSpec nnc.NodeNetworkConfigSpec
141150 tempNNCSpec , err = pm .createNNCSpecForCRD (false )
142151 if err != nil {
143152 return err
144153 }
145154
146- tempNNCSpec .RequestedIPCount -= int64 (totalIpsSetForRelease )
147- logger .Printf ("[ipam-pool-monitor] Decreasing pool size, Current Pool Size: %v, Requested IP Count: %v, Pods with IP's: %v, ToBeDeleted Count: %v" , len (pm .cns .GetPodIPConfigState ()), tempNNCSpec .RequestedIPCount , len (pm .cns .GetAllocatedIPConfigs ()), len (tempNNCSpec .IPsNotInUse ))
155+ if newIpsMarkedAsPending {
156+ // cache the updatingPendingRelease so that we dont re-set new IPs to PendingRelease in case UpdateCRD call fails
157+ pm .updatingIpsNotInUseCount = len (tempNNCSpec .IPsNotInUse )
158+ }
159+
160+ logger .Printf ("[ipam-pool-monitor] Releasing IPCount in this batch %d, updatingPendingIpsNotInUse count %d" , len (pendingIpAddresses ), pm .updatingIpsNotInUseCount )
161+
162+ tempNNCSpec .RequestedIPCount -= int64 (len (pendingIpAddresses ))
163+ logger .Printf ("[ipam-pool-monitor] Decreasing pool size, Current Pool Size: %v, Requested IP Count: %v, Pods with IP's: %v, ToBeDeleted Count: %v" , len (pm .httpService .GetPodIPConfigState ()), tempNNCSpec .RequestedIPCount , len (pm .httpService .GetAllocatedIPConfigs ()), len (tempNNCSpec .IPsNotInUse ))
148164
149165 err = pm .rc .UpdateCRDSpec (context .Background (), tempNNCSpec )
150166 if err != nil {
151167 // caller will retry to update the CRD again
152168 return err
153169 }
154170
171+ logger .Printf ("[ipam-pool-monitor] Decreasing pool size: UpdateCRDSpec succeeded for spec %+v" , tempNNCSpec )
172+
155173 // save the updated state to cachedSpec
156174 pm .cachedNNC .Spec = tempNNCSpec
157175 pm .pendingRelease = true
176+
177+ // clear the updatingPendingIpsNotInUse, as we have Updated the CRD
178+ logger .Printf ("[ipam-pool-monitor] cleaning the updatingPendingIpsNotInUse, existing length %d" , pm .updatingIpsNotInUseCount )
179+ pm .updatingIpsNotInUseCount = 0
180+
158181 return nil
159182}
160183
161184// if cns pending ip release map is empty, request controller has already reconciled the CNS state,
162185// so we can remove it from our cache and remove the IP's from the CRD
163186func (pm * CNSIPAMPoolMonitor ) cleanPendingRelease () error {
164- pm .mu .Lock ()
165187 defer pm .mu .Unlock ()
188+ pm .mu .Lock ()
166189
167190 var err error
168191 var tempNNCSpec nnc.NodeNetworkConfigSpec
@@ -177,6 +200,9 @@ func (pm *CNSIPAMPoolMonitor) cleanPendingRelease() error {
177200 return err
178201 }
179202
203+ logger .Printf ("[ipam-pool-monitor] cleanPendingRelease: UpdateCRDSpec succeeded for spec %+v" , tempNNCSpec )
204+
205+
180206 // save the updated state to cachedSpec
181207 pm .cachedNNC .Spec = tempNNCSpec
182208 pm .pendingRelease = false
@@ -197,7 +223,7 @@ func (pm *CNSIPAMPoolMonitor) createNNCSpecForCRD(resetNotInUseList bool) (nnc.N
197223 spec .IPsNotInUse = make ([]string , 0 )
198224 } else {
199225 // Get All Pending IPs from CNS and populate it again.
200- pendingIps := pm .cns .GetPendingReleaseIPConfigs ()
226+ pendingIps := pm .httpService .GetPendingReleaseIPConfigs ()
201227 for _ , pendingIp := range pendingIps {
202228 spec .IPsNotInUse = append (spec .IPsNotInUse , pendingIp .ID )
203229 }
@@ -208,14 +234,18 @@ func (pm *CNSIPAMPoolMonitor) createNNCSpecForCRD(resetNotInUseList bool) (nnc.N
208234
209235// UpdatePoolLimitsTransacted called by request controller on reconcile to set the batch size limits
210236func (pm * CNSIPAMPoolMonitor ) Update (scalar nnc.Scaler , spec nnc.NodeNetworkConfigSpec ) error {
211- pm .mu .Lock ()
212237 defer pm .mu .Unlock ()
238+ pm .mu .Lock ()
239+
213240 pm .scalarUnits = scalar
214241
215242 pm .MinimumFreeIps = int64 (float64 (pm .scalarUnits .BatchSize ) * (float64 (pm .scalarUnits .RequestThresholdPercent ) / 100 ))
216243 pm .MaximumFreeIps = int64 (float64 (pm .scalarUnits .BatchSize ) * (float64 (pm .scalarUnits .ReleaseThresholdPercent ) / 100 ))
217244
218245 pm .cachedNNC .Spec = spec
219246
247+ logger .Printf ("[ipam-pool-monitor] Update spec %+v, pm.MinimumFreeIps %d, pm.MaximumFreeIps %d" ,
248+ pm .cachedNNC .Spec , pm .MinimumFreeIps , pm .MaximumFreeIps )
249+
220250 return nil
221251}
0 commit comments