func NewCIDRRangeAllocator(client clientset.Interface, nodeInformer informers.NodeInformer, allocatorParams CIDRAllocatorParams, nodeList *v1.NodeList) (CIDRAllocator, error) {
	if client == nil {
		klog.Fatalf("kubeClient is nil when starting NodeController")
	}

	eventBroadcaster := record.NewBroadcaster()
	recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cidrAllocator"})
	eventBroadcaster.StartStructuredLogging(0)
	klog.V(0).Infof("Sending events to api server.")
	eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: client.CoreV1().Events("")})

	// create a cidrSet for each cidr we operate on
	// cidrSet are mapped to clusterCIDR by index
	cidrSets := make([]*cidrset.CidrSet, len(allocatorParams.ClusterCIDRs))
	for idx, cidr := range allocatorParams.ClusterCIDRs {
		cidrSet, err := cidrset.NewCIDRSet(cidr, allocatorParams.NodeCIDRMaskSizes[idx])
		if err != nil {
			return nil, err
		}
		cidrSets[idx] = cidrSet
	}

	ra := &rangeAllocator{
		client:                client,
		clusterCIDRs:          allocatorParams.ClusterCIDRs,
		cidrSets:              cidrSets,
		nodeLister:            nodeInformer.Lister(),
		nodesSynced:           nodeInformer.Informer().HasSynced,
		nodeCIDRUpdateChannel: make(chan nodeReservedCIDRs, cidrUpdateQueueSize),
		recorder:              recorder,
		nodesInProcessing:     sets.NewString(),
	}

	if allocatorParams.ServiceCIDR != nil {
		ra.filterOutServiceRange(allocatorParams.ServiceCIDR)
	} else {
		klog.V(0).Info("No Service CIDR provided. Skipping filtering out service addresses.")
	}

	if allocatorParams.SecondaryServiceCIDR != nil {
		ra.filterOutServiceRange(allocatorParams.SecondaryServiceCIDR)
	} else {
		klog.V(0).Info("No Secondary Service CIDR provided. Skipping filtering out secondary service addresses.")
	}

	if nodeList != nil {
		for _, node := range nodeList.Items {
			if len(node.Spec.PodCIDRs) == 0 {
				klog.V(4).Infof("Node %v has no CIDR, ignoring", node.Name)
				continue
			}
			klog.V(4).Infof("Node %v has CIDR %s, occupying it in CIDR map", node.Name, node.Spec.PodCIDR)
			if err := ra.occupyCIDRs(&node); err != nil {
				// This will happen if:
				// 1. We find garbage in the podCIDRs field. Retrying is useless.
				// 2. CIDR out of range: This means a node CIDR has changed.
				// This error will keep crashing controller-manager.
				return nil, err
			}
		}
	}

	nodeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc: nodeutil.CreateAddNodeHandler(ra.AllocateOrOccupyCIDR),
		UpdateFunc: nodeutil.CreateUpdateNodeHandler(func(_, newNode *v1.Node) error {
			// If the PodCIDRs list is not empty we either:
			// - already processed a Node that already had CIDRs after NC restarted
			//   (cidr is marked as used),
			// - already processed a Node successfully and allocated CIDRs for it
			//   (cidr is marked as used),
			// - already processed a Node but we did saw a "timeout" response and
			//   request eventually got through in this case we haven't released
			//   the allocated CIDRs (cidr is still marked as used).
			// There's a possible error here:
			// - NC sees a new Node and assigns CIDRs X,Y.. to it,
			// - Update Node call fails with a timeout,
			// - Node is updated by some other component, NC sees an update and
			//   assigns CIDRs A,B.. to the Node,
			// - Both CIDR X,Y.. and CIDR A,B.. are marked as used in the local cache,
			//   even though Node sees only CIDR A,B..
			// The problem here is that in in-memory cache we see CIDR X,Y.. as marked,
			// which prevents it from being assigned to any new node. The cluster
			// state is correct.
			// Restart of NC fixes the issue.
			if len(newNode.Spec.PodCIDRs) == 0 {
				return ra.AllocateOrOccupyCIDR(newNode)
			}
			return nil
		}),
		DeleteFunc: nodeutil.CreateDeleteNodeHandler(ra.ReleaseCIDR),
	})

	return ra, nil
}
// NewCIDRRangeAllocator returns a CIDRAllocator to allocate CIDRs for node (one from each of clusterCIDRs)
// Caller must ensure subNetMaskSize is not less than cluster CIDR mask size.
// Caller must always pass in a list of existing nodes so the new allocator.
// Caller must ensure that ClusterCIDRs are semantically correct e.g (1 for non DualStack, 2 for DualStack etc..)
// can initialize its CIDR map. NodeList is only nil in testing.
NewCIDRRangeAllocator returns a CIDRAllocator to allocate CIDRs for node (one from each of clusterCIDRs)
Caller must ensure subNetMaskSize is not less than cluster CIDR mask size.
Caller must always pass in a list of existing nodes so the new allocator.
Caller must ensure that ClusterCIDRs are semantically correct e.g (1 for non DualStack, 2 for DualStack etc..)
can initialize its CIDR map. NodeList is only nil in testing.
// NewCIDRRangeAllocator returns a CIDRAllocator to allocate CIDRs for node ( one from each of clusterCIDRs ) // Caller must ensure subNetMaskSize is not less than cluster CIDR mask size . // Caller must always pass in a list of existing nodes so the new allocator . // Caller must ensure that ClusterCIDRs are semantically correct e . g ( 1 for non DualStack 2 for DualStack etc .. ) // can initialize its CIDR map . NodeList is only nil in testing .
func NewCIDRRangeAllocator(client clientset.Interface, nodeInformer informers.NodeInformer, allocatorParams CIDRAllocatorParams, nodeList *v1.NodeList) (CIDRAllocator, error) {
	if client == nil {
		klog.Fatalf("kubeClient is nil when starting NodeController")
	}
	eventBroadcaster := record.NewBroadcaster()
	recorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cidrAllocator"})
	eventBroadcaster.StartStructuredLogging(0)
	klog.V(0).Infof("Sending events to api server.")
	eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: client.CoreV1().Events("")})
	cidrSets := make([]*cidrset.CidrSet, len(allocatorParams.ClusterCIDRs))
	for idx, cidr := range allocatorParams.ClusterCIDRs {
		cidrSet, err := cidrset.NewCIDRSet(cidr, allocatorParams.NodeCIDRMaskSizes[idx])
		if err != nil {
			return nil, err
		}
		cidrSets[idx] = cidrSet
	}
	ra := &rangeAllocator{
		client:                client,
		clusterCIDRs:          allocatorParams.ClusterCIDRs,
		cidrSets:              cidrSets,
		nodeLister:            nodeInformer.Lister(),
		nodesSynced:           nodeInformer.Informer().HasSynced,
		nodeCIDRUpdateChannel: make(chan nodeReservedCIDRs, cidrUpdateQueueSize),
		recorder:              recorder,
		nodesInProcessing:     sets.NewString(),
	}
	if allocatorParams.ServiceCIDR != nil {
		ra.filterOutServiceRange(allocatorParams.ServiceCIDR)
	} else {
		klog.V(0).Info("No Service CIDR provided. Skipping filtering out service addresses.")
	}
	if allocatorParams.SecondaryServiceCIDR != nil {
		ra.filterOutServiceRange(allocatorParams.SecondaryServiceCIDR)
	} else {
		klog.V(0).Info("No Secondary Service CIDR provided. Skipping filtering out secondary service addresses.")
	}
	if nodeList != nil {
		for _, node := range nodeList.Items {
			if len(node.Spec.PodCIDRs) == 0 {
				klog.V(4).Infof("Node %v has no CIDR, ignoring", node.Name)
				continue
			}
			klog.V(4).Infof("Node %v has CIDR %s, occupying it in CIDR map", node.Name, node.Spec.PodCIDR)
			if err := ra.occupyCIDRs(&node); err != nil {
				return nil, err
			}
		}
	}
	nodeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc: nodeutil.CreateAddNodeHandler(ra.AllocateOrOccupyCIDR),
		UpdateFunc: nodeutil.CreateUpdateNodeHandler(func(_, newNode *v1.Node) error {
			if len(newNode.Spec.PodCIDRs) == 0 {
				return ra.AllocateOrOccupyCIDR(newNode)
			}
			return nil
		}),
		DeleteFunc: nodeutil.CreateDeleteNodeHandler(ra.ReleaseCIDR),
	})
	return ra, nil
}
func NewCIDRRangeAllocator ( client clientset . Interface , nodeInformer informers . NodeInformer , allocatorParams CIDRAllocatorParams , nodeList * v1 . NodeList ) ( CIDRAllocator , error ) { if client == nil { klog . Fatalf ( " " ) } eventBroadcaster := record . NewBroadcaster ( ) recorder := eventBroadcaster . NewRecorder ( scheme . Scheme , v1 . EventSource { Component : " " } ) eventBroadcaster . StartStructuredLogging ( 0 ) klog . V ( 0 ) . Infof ( " " ) eventBroadcaster . StartRecordingToSink ( & v1core . EventSinkImpl { Interface : client . CoreV1 ( ) . Events ( " " ) } ) cidrSets := make ( [ ] * cidrset . CidrSet , len ( allocatorParams . ClusterCIDRs ) ) for idx , cidr := range allocatorParams . ClusterCIDRs { cidrSet , err := cidrset . NewCIDRSet ( cidr , allocatorParams . NodeCIDRMaskSizes [ idx ] ) if err != nil { return nil , err } cidrSets [ idx ] = cidrSet } ra := & rangeAllocator { client : client , clusterCIDRs : allocatorParams . ClusterCIDRs , cidrSets : cidrSets , nodeLister : nodeInformer . Lister ( ) , nodesSynced : nodeInformer . Informer ( ) . HasSynced , nodeCIDRUpdateChannel : make ( chan nodeReservedCIDRs , cidrUpdateQueueSize ) , recorder : recorder , nodesInProcessing : sets . NewString ( ) , } if allocatorParams . ServiceCIDR != nil { ra . filterOutServiceRange ( allocatorParams . ServiceCIDR ) } else { klog . V ( 0 ) . Info ( " " ) } if allocatorParams . SecondaryServiceCIDR != nil { ra . filterOutServiceRange ( allocatorParams . SecondaryServiceCIDR ) } else { klog . V ( 0 ) . Info ( " " ) } if nodeList != nil { for _ , node := range nodeList . Items { if len ( node . Spec . PodCIDRs ) == 0 { klog . V ( 4 ) . Infof ( " " , node . Name ) continue } klog . V ( 4 ) . Infof ( " " , node . Name , node . Spec . PodCIDR ) if err := ra . occupyCIDRs ( & node ) ; err != nil { return nil , err } } } nodeInformer . Informer ( ) . AddEventHandler ( cache . ResourceEventHandlerFuncs { AddFunc : nodeutil . CreateAddNodeHandler ( ra . AllocateOrOccupyCIDR ) , UpdateFunc : nodeutil . CreateUpdateNodeHandler ( func ( _ , newNode * v1 . Node ) error { if len ( newNode . Spec . PodCIDRs ) == 0 { return ra . AllocateOrOccupyCIDR ( newNode ) } return nil } ) , DeleteFunc : nodeutil . CreateDeleteNodeHandler ( ra . ReleaseCIDR ) , } ) return ra , nil }
NewCIDRRangeAllocator returns a CIDRAllocator to allocate CIDRs for node (one from each of clusterCIDRs)
Caller must ensure subNetMaskSize is not less than cluster CIDR mask size.
NewCIDRRangeAllocator returns a CIDRAllocator to allocate CIDRs for node ( one from each of clusterCIDRs ) Caller must ensure subNetMaskSize is not less than cluster CIDR mask size .
// create a cidrSet for each cidr we operate on // cidrSet are mapped to clusterCIDR by index // This will happen if: // 1. We find garbage in the podCIDRs field. Retrying is useless. // 2. CIDR out of range: This means a node CIDR has changed. // This error will keep crashing controller-manager. // If the PodCIDRs list is not empty we either: // - already processed a Node that already had CIDRs after NC restarted //   (cidr is marked as used), // - already processed a Node successfully and allocated CIDRs for it //   (cidr is marked as used), // - already processed a Node but we did saw a "timeout" response and //   request eventually got through in this case we haven't released //   the allocated CIDRs (cidr is still marked as used). // There's a possible error here: // - NC sees a new Node and assigns CIDRs X,Y.. to it, // - Update Node call fails with a timeout, // - Node is updated by some other component, NC sees an update and //   assigns CIDRs A,B.. to the Node, // - Both CIDR X,Y.. and CIDR A,B.. are marked as used in the local cache, //   even though Node sees only CIDR A,B.. // The problem here is that in in-memory cache we see CIDR X,Y.. as marked, // which prevents it from being assigned to any new node. The cluster // state is correct. // Restart of NC fixes the issue.