Skip to content

Commit a7b5202

Browse files
authored
[NPM] Support pod controller and unit test to improve reliability (#836)
* Junguk cho pod controller support (#1) * code layout to support pod controller in npm * filter events if they do not need to handle and clean up business logic * put lock when it needs to access shared resource use namespace/name as key clean up functions * - use pod key instead of uid. - remove unnecessary error check * use namespace prefix in pod namespace. add log messages to know what events happens. * move event logs with more contexts in needsync func * Put returning an error in a right place * Return if the RV of both pod obj are the same. Proactively start cleaning up pod when the pod is deleted. * first version of podController UT * add ipset management in pod controller unit test * Make methods flexible for ipset store and restore operation * clean up functions and variables Co-authored-by: Junguk Cho <[email protected]> * correct and clean functions and error messages. Return errors from appendNamedPortIpsets function to retry syncPod operation * Check npmPod exists in cleanUpDeletedPod function. Use GetIPSetListFromLabels in syncAddedPod and cleanUpDeletedPod functions. Correct error messages, functions, etc * Clean up podController code. Make podController UT more flexible. * clean up appendNamedPortIpsets to improve readibility * minor update (v1 -> corev1) for consistency * clean up syncPod code to compare last applied states and new pod's states * add validation for casting old pod. correct log message * delete unneeded codes * minor fix: correct comments and removed unneeded variables * add pre-filter codes to avoid unnecessary reconcile process in updatePod event * correct a comment * check workqueue length to validate case where it does not need to reconcile in unit test
1 parent 45c2fca commit a7b5202

File tree

6 files changed

+1059
-1114
lines changed

6 files changed

+1059
-1114
lines changed

npm/ipsm/ipsm.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ type IpsetManager struct {
3232
// Ipset represents one ipset entry.
3333
type Ipset struct {
3434
name string
35-
elements map[string]string // key = ip, value: context associated to the ip like podUid
35+
elements map[string]string // key = ip, value: context associated to the ip like podKey
3636
referCount int
3737
}
3838

@@ -297,16 +297,16 @@ func (ipsMgr *IpsetManager) DeleteSet(setName string) error {
297297
}
298298

299299
// AddToSet inserts an ip to an entry in setMap, and creates/updates the corresponding ipset.
300-
func (ipsMgr *IpsetManager) AddToSet(setName, ip, spec, podUid string) error {
300+
func (ipsMgr *IpsetManager) AddToSet(setName, ip, spec, podKey string) error {
301301
if ipsMgr.Exists(setName, ip, spec) {
302302

303-
// make sure we have updated the podUid in case it gets changed
304-
cachedPodUid := ipsMgr.SetMap[setName].elements[ip]
305-
if cachedPodUid != podUid {
306-
log.Logf("AddToSet: PodOwner has changed for Ip: %s, setName:%s, Old podUid: %s, new PodUid: %s. Replace context with new PodOwner.",
307-
ip, setName, cachedPodUid, podUid)
303+
// make sure we have updated the podKey in case it gets changed
304+
cachedPodKey := ipsMgr.SetMap[setName].elements[ip]
305+
if cachedPodKey != podKey {
306+
log.Logf("AddToSet: PodOwner has changed for Ip: %s, setName:%s, Old podKey: %s, new podKey: %s. Replace context with new PodOwner.",
307+
ip, setName, cachedPodKey, podKey)
308308

309-
ipsMgr.SetMap[setName].elements[ip] = podUid
309+
ipsMgr.SetMap[setName].elements[ip] = podKey
310310
}
311311

312312
return nil
@@ -351,8 +351,8 @@ func (ipsMgr *IpsetManager) AddToSet(setName, ip, spec, podUid string) error {
351351
return err
352352
}
353353

354-
// Stores the podUid as the context for this ip.
355-
ipsMgr.SetMap[setName].elements[ip] = podUid
354+
// Stores the podKey as the context for this ip.
355+
ipsMgr.SetMap[setName].elements[ip] = podKey
356356

357357
metrics.NumIPSetEntries.Inc()
358358
metrics.IncIPSetInventory(setName)
@@ -361,7 +361,7 @@ func (ipsMgr *IpsetManager) AddToSet(setName, ip, spec, podUid string) error {
361361
}
362362

363363
// DeleteFromSet removes an ip from an entry in setMap, and delete/update the corresponding ipset.
364-
func (ipsMgr *IpsetManager) DeleteFromSet(setName, ip, podUid string) error {
364+
func (ipsMgr *IpsetManager) DeleteFromSet(setName, ip, podKey string) error {
365365
ipSet, exists := ipsMgr.SetMap[setName]
366366
if !exists {
367367
log.Logf("ipset with name %s not found", setName)
@@ -380,10 +380,10 @@ func (ipsMgr *IpsetManager) DeleteFromSet(setName, ip, podUid string) error {
380380

381381
if _, exists := ipsMgr.SetMap[setName].elements[ip]; exists {
382382
// in case the IP belongs to a new Pod, then ignore this Delete call as this might be stale
383-
cachedPodUid := ipSet.elements[ip]
384-
if cachedPodUid != podUid {
385-
log.Logf("DeleteFromSet: PodOwner has changed for Ip: %s, setName:%s, Old podUid: %s, new PodUid: %s. Ignore the delete as this is stale update",
386-
ip, setName, cachedPodUid, podUid)
383+
cachedPodKey := ipSet.elements[ip]
384+
if cachedPodKey != podKey {
385+
log.Logf("DeleteFromSet: PodOwner has changed for Ip: %s, setName:%s, Old podKey: %s, new podKey: %s. Ignore the delete as this is stale update",
386+
ip, setName, cachedPodKey, podKey)
387387

388388
return nil
389389
}

npm/npm.go

Lines changed: 10 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,17 @@ type NetworkPolicyManager struct {
4545
sync.Mutex
4646
clientset *kubernetes.Clientset
4747

48-
informerFactory informers.SharedInformerFactory
49-
podInformer coreinformers.PodInformer
48+
informerFactory informers.SharedInformerFactory
49+
podInformer coreinformers.PodInformer
50+
podController *podController
51+
5052
nsInformer coreinformers.NamespaceInformer
5153
npInformer networkinginformers.NetworkPolicyInformer
5254
nameSpaceController *nameSpaceController
5355

5456
NodeName string
5557
NsMap map[string]*Namespace
56-
PodMap map[string]*NpmPod // Key is ns-<nsname>/<podname>/<poduuid>
58+
PodMap map[string]*NpmPod // Key is <nsname>/<podname>
5759
RawNpMap map[string]*networkingv1.NetworkPolicy // Key is ns-<nsname>/<policyname>
5860
ProcessedNpMap map[string]*networkingv1.NetworkPolicy // Key is ns-<nsname>/<podSelectorHash>
5961
isAzureNpmChainCreated bool
@@ -186,6 +188,9 @@ func (npMgr *NetworkPolicyManager) Start(stopCh <-chan struct{}) error {
186188
return fmt.Errorf("Network policy informer failed to sync")
187189
}
188190

191+
// TODO: any dependency among below functions?
192+
// start pod controller after synced
193+
go npMgr.podController.Run(threadness, stopCh)
189194
go npMgr.nameSpaceController.Run(threadness, stopCh)
190195
go npMgr.reconcileChains()
191196
go npMgr.backup()
@@ -261,52 +266,8 @@ func NewNetworkPolicyManager(clientset *kubernetes.Clientset, informerFactory in
261266
metrics.SendErrorLogAndMetric(util.NpmID, "Error: failed to create ipset for namespace %s.", kubeSystemNs)
262267
}
263268

264-
podInformer.Informer().AddEventHandler(
265-
// Pod event handlers
266-
cache.ResourceEventHandlerFuncs{
267-
AddFunc: func(obj interface{}) {
268-
podObj, ok := obj.(*corev1.Pod)
269-
if !ok {
270-
metrics.SendErrorLogAndMetric(util.NpmID, "ADD Pod: Received unexpected object type: %v", obj)
271-
return
272-
}
273-
npMgr.Lock()
274-
npMgr.AddPod(podObj)
275-
npMgr.Unlock()
276-
},
277-
UpdateFunc: func(_, new interface{}) {
278-
newPodObj, ok := new.(*corev1.Pod)
279-
if !ok {
280-
metrics.SendErrorLogAndMetric(util.NpmID, "UPDATE Pod: Received unexpected new object type: %v", newPodObj)
281-
return
282-
}
283-
npMgr.Lock()
284-
npMgr.UpdatePod(newPodObj)
285-
npMgr.Unlock()
286-
},
287-
DeleteFunc: func(obj interface{}) {
288-
// DeleteFunc gets the final state of the resource (if it is known).
289-
// Otherwise, it gets an object of type DeletedFinalStateUnknown.
290-
// This can happen if the watch is closed and misses the delete event and
291-
// the controller doesn't notice the deletion until the subsequent re-list
292-
podObj, ok := obj.(*corev1.Pod)
293-
if !ok {
294-
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
295-
if !ok {
296-
metrics.SendErrorLogAndMetric(util.NpmID, "DELETE Pod: Received unexpected object type: %v", obj)
297-
return
298-
}
299-
if podObj, ok = tombstone.Obj.(*corev1.Pod); !ok {
300-
metrics.SendErrorLogAndMetric(util.NpmID, "DELETE Pod: Received unexpected object type: %v", obj)
301-
return
302-
}
303-
}
304-
npMgr.Lock()
305-
npMgr.DeletePod(podObj)
306-
npMgr.Unlock()
307-
},
308-
},
309-
)
269+
// create pod controller
270+
npMgr.podController = NewPodController(informerFactory.Core().V1().Pods(), clientset, npMgr)
310271

311272
// create NameSpace controller
312273
npMgr.nameSpaceController = NewNameSpaceController(nsInformer, clientset, npMgr)

0 commit comments

Comments
 (0)