in pkg/ipamd/ipamd.go [1361:1480]
func (c *IPAMContext) nodeIPPoolReconcile(ctx context.Context, interval time.Duration) {
// To reduce the number of EC2 API calls, skip reconciliation if IPs were recently added to the datastore.
timeSinceLast := time.Since(c.lastNodeIPPoolAction)
// Make an exception if node needs a trunk ENI and one is not currently attached.
needsTrunkEni := c.enablePodENI && c.dataStore.GetTrunkENI() == ""
if timeSinceLast <= interval && !needsTrunkEni {
return
}
prometheusmetrics.IpamdActionsInprogress.WithLabelValues("nodeIPPoolReconcile").Add(float64(1))
defer prometheusmetrics.IpamdActionsInprogress.WithLabelValues("nodeIPPoolReconcile").Sub(float64(1))
log.Debugf("Reconciling ENI/IP pool info because time since last %v > %v", timeSinceLast, interval)
allENIs, err := c.awsClient.GetAttachedENIs()
if err != nil {
log.Errorf("IP pool reconcile: Failed to get attached ENI info: %v", err.Error())
ipamdErrInc("reconcileFailedGetENIs")
return
}
// We must always have at least the primary ENI of the instance
if allENIs == nil {
log.Error("IP pool reconcile: No ENI found at all in metadata, unable to reconcile")
ipamdErrInc("reconcileFailedGetENIs")
return
}
attachedENIs := c.filterUnmanagedENIs(allENIs)
currentENIs := c.dataStore.GetENIInfos().ENIs
trunkENI := c.dataStore.GetTrunkENI()
// Initialize the set with the known EFA interfaces
efaENIs := c.dataStore.GetEFAENIs()
// Check if a new ENI was added, if so we need to update the tags.
needToUpdateTags := false
for _, attachedENI := range attachedENIs {
if _, ok := currentENIs[attachedENI.ENIID]; !ok {
needToUpdateTags = true
break
}
}
var eniTagMap map[string]awsutils.TagMap
if needToUpdateTags {
log.Debugf("A new ENI added but not by ipamd, updating tags by calling EC2")
metadataResult, err := c.awsClient.DescribeAllENIs()
if err != nil {
log.Warnf("Failed to call EC2 to describe ENIs, aborting reconcile: %v", err)
return
}
if c.enablePodENI && metadataResult.TrunkENI != "" {
log.Debugf("Trunk interface (%s) has been added to the node already.", metadataResult.TrunkENI)
}
// Update trunk ENI
trunkENI = metadataResult.TrunkENI
// Just copy values of the EFA set
efaENIs = metadataResult.EFAENIs
eniTagMap = metadataResult.TagMap
c.setUnmanagedENIs(metadataResult.TagMap)
c.awsClient.SetMultiCardENIs(metadataResult.MultiCardENIIDs)
attachedENIs = c.filterUnmanagedENIs(metadataResult.ENIMetadata)
}
// Mark phase
for _, attachedENI := range attachedENIs {
eniIPPool, eniPrefixPool, err := c.dataStore.GetENICIDRs(attachedENI.ENIID)
if err == nil {
// If the attached ENI is in the data store
log.Debugf("Reconcile existing ENI %s IP pool", attachedENI.ENIID)
// Reconcile IP pool
c.eniIPPoolReconcile(eniIPPool, attachedENI, attachedENI.ENIID)
// If the attached ENI is in the data store
log.Debugf("Reconcile existing ENI %s IP prefixes", attachedENI.ENIID)
// Reconcile IP pool
c.eniPrefixPoolReconcile(eniPrefixPool, attachedENI, attachedENI.ENIID)
// Mark action, remove this ENI from currentENIs map
delete(currentENIs, attachedENI.ENIID)
continue
}
isTrunkENI := attachedENI.ENIID == trunkENI
isEFAENI := efaENIs[attachedENI.ENIID]
if !isTrunkENI && !c.disableENIProvisioning {
if err := c.awsClient.TagENI(attachedENI.ENIID, eniTagMap[attachedENI.ENIID]); err != nil {
log.Errorf("IP pool reconcile: failed to tag managed ENI %v: %v", attachedENI.ENIID, err)
ipamdErrInc("eniReconcileAdd")
continue
}
}
// Add new ENI
log.Debugf("Reconcile and add a new ENI %s", attachedENI)
err = c.setupENI(attachedENI.ENIID, attachedENI, isTrunkENI, isEFAENI)
if err != nil {
log.Errorf("IP pool reconcile: Failed to set up ENI %s network: %v", attachedENI.ENIID, err)
ipamdErrInc("eniReconcileAdd")
// Continue if having trouble with ONLY 1 ENI, instead of bailout here?
continue
}
prometheusmetrics.ReconcileCnt.With(prometheus.Labels{"fn": "eniReconcileAdd"}).Inc()
}
// Sweep phase: since the marked ENI have been removed, the remaining ones needs to be sweeped
for eni := range currentENIs {
log.Infof("Reconcile and delete detached ENI %s", eni)
// Force the delete, since aws local metadata has told us that this ENI is no longer
// attached, so any IPs assigned from this ENI will no longer work.
err = c.dataStore.RemoveENIFromDataStore(eni, true /* force */)
if err != nil {
log.Errorf("IP pool reconcile: Failed to delete ENI during reconcile: %v", err)
ipamdErrInc("eniReconcileDel")
continue
}
delete(c.primaryIP, eni)
prometheusmetrics.ReconcileCnt.With(prometheus.Labels{"fn": "eniReconcileDel"}).Inc()
}
c.lastNodeIPPoolAction = time.Now()
log.Debug("Successfully Reconciled ENI/IP pool")
c.logPoolStats(c.dataStore.GetIPStats(ipV4AddrFamily))
}