github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/cloud/pkg/edgecontroller/manager/pod.go (about)

     1  package manager
     2  
     3  import (
     4  	"reflect"
     5  	"sync"
     6  
     7  	"k8s.io/api/core/v1"
     8  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
     9  	"k8s.io/apimachinery/pkg/fields"
    10  	"k8s.io/apimachinery/pkg/watch"
    11  	"k8s.io/client-go/kubernetes"
    12  	"k8s.io/client-go/tools/cache"
    13  	"k8s.io/klog"
    14  
    15  	"github.com/kubeedge/kubeedge/cloud/pkg/edgecontroller/config"
    16  )
    17  
    18  // CachePod is the struct save pod data for check pod is really changed
    19  type CachePod struct {
    20  	metav1.ObjectMeta
    21  	Spec v1.PodSpec
    22  }
    23  
    24  // PodManager is a manager watch pod change event
    25  type PodManager struct {
    26  	// events from watch kubernetes api server
    27  	realEvents chan watch.Event
    28  
    29  	// events merged
    30  	mergedEvents chan watch.Event
    31  
    32  	// pods, key is UID, value is *v1.Pod
    33  	pods sync.Map
    34  }
    35  
    36  func (pm *PodManager) isPodUpdated(old *CachePod, new *v1.Pod) bool {
    37  	// does not care fields
    38  	old.ObjectMeta.ResourceVersion = new.ObjectMeta.ResourceVersion
    39  	old.ObjectMeta.Generation = new.ObjectMeta.Generation
    40  
    41  	// return true if ObjectMeta or Spec changed, else false
    42  	return !reflect.DeepEqual(old.ObjectMeta, new.ObjectMeta) || !reflect.DeepEqual(old.Spec, new.Spec)
    43  }
    44  
    45  func (pm *PodManager) merge() {
    46  	for re := range pm.realEvents {
    47  		pod := re.Object.(*v1.Pod)
    48  		switch re.Type {
    49  		case watch.Added:
    50  			pm.pods.Store(pod.UID, &CachePod{ObjectMeta: pod.ObjectMeta, Spec: pod.Spec})
    51  			if pod.DeletionTimestamp == nil {
    52  				pm.mergedEvents <- re
    53  			} else {
    54  				re.Type = watch.Modified
    55  				pm.mergedEvents <- re
    56  			}
    57  		case watch.Deleted:
    58  			pm.pods.Delete(pod.UID)
    59  			pm.mergedEvents <- re
    60  		case watch.Modified:
    61  			value, ok := pm.pods.Load(pod.UID)
    62  			pm.pods.Store(pod.UID, &CachePod{ObjectMeta: pod.ObjectMeta, Spec: pod.Spec})
    63  			if ok {
    64  				cachedPod := value.(*CachePod)
    65  				if pm.isPodUpdated(cachedPod, pod) {
    66  					pm.mergedEvents <- re
    67  				}
    68  			} else {
    69  				pm.mergedEvents <- re
    70  			}
    71  		default:
    72  			klog.Warningf("event type: %s unsupported", re.Type)
    73  		}
    74  	}
    75  }
    76  
    77  // Events return a channel, can receive all pod event
    78  func (pm *PodManager) Events() chan watch.Event {
    79  	return pm.mergedEvents
    80  }
    81  
    82  // NewPodManager create PodManager from config
    83  func NewPodManager(kubeClient *kubernetes.Clientset, namespace, nodeName string) (*PodManager, error) {
    84  	var lw *cache.ListWatch
    85  	if "" == nodeName {
    86  		lw = cache.NewListWatchFromClient(kubeClient.CoreV1().RESTClient(), "pods", namespace, fields.Everything())
    87  	} else {
    88  		selector := fields.OneTermEqualSelector("spec.nodeName", nodeName)
    89  		lw = cache.NewListWatchFromClient(kubeClient.CoreV1().RESTClient(), "pods", namespace, selector)
    90  	}
    91  	realEvents := make(chan watch.Event, config.Config.Buffer.PodEvent)
    92  	mergedEvents := make(chan watch.Event, config.Config.Buffer.PodEvent)
    93  	rh := NewCommonResourceEventHandler(realEvents)
    94  	si := cache.NewSharedInformer(lw, &v1.Pod{}, 0)
    95  	si.AddEventHandler(rh)
    96  
    97  	pm := &PodManager{realEvents: realEvents, mergedEvents: mergedEvents}
    98  
    99  	stopNever := make(chan struct{})
   100  	go si.Run(stopNever)
   101  	go pm.merge()
   102  
   103  	return pm, nil
   104  }