...

Source file src/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/cidr_allocator.go

Documentation: k8s.io/kubernetes/pkg/controller/nodeipam/ipam

     1  /*
     2  Copyright 2016 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package ipam
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"net"
    23  	"time"
    24  
    25  	"k8s.io/kubernetes/pkg/controller/nodeipam/ipam/cidrset"
    26  
    27  	v1 "k8s.io/api/core/v1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/fields"
    30  	"k8s.io/apimachinery/pkg/labels"
    31  	"k8s.io/apimachinery/pkg/util/wait"
    32  	informers "k8s.io/client-go/informers/core/v1"
    33  	clientset "k8s.io/client-go/kubernetes"
    34  	cloudprovider "k8s.io/cloud-provider"
    35  	"k8s.io/klog/v2"
    36  )
    37  
    38  // CIDRAllocatorType is the type of the allocator to use.
    39  type CIDRAllocatorType string
    40  
    41  const (
    42  	// RangeAllocatorType is the allocator that uses an internal CIDR
    43  	// range allocator to do node CIDR range allocations.
    44  	RangeAllocatorType CIDRAllocatorType = "RangeAllocator"
    45  	// CloudAllocatorType is the allocator that uses cloud platform
    46  	// support to do node CIDR range allocations.
    47  	CloudAllocatorType CIDRAllocatorType = "CloudAllocator"
    48  	// IPAMFromClusterAllocatorType uses the ipam controller sync'ing the node
    49  	// CIDR range allocations from the cluster to the cloud.
    50  	IPAMFromClusterAllocatorType = "IPAMFromCluster"
    51  	// IPAMFromCloudAllocatorType uses the ipam controller sync'ing the node
    52  	// CIDR range allocations from the cloud to the cluster.
    53  	IPAMFromCloudAllocatorType = "IPAMFromCloud"
    54  )
    55  
    56  // TODO: figure out the good setting for those constants.
    57  const (
    58  	// The amount of time the nodecontroller polls on the list nodes endpoint.
    59  	apiserverStartupGracePeriod = 10 * time.Minute
    60  
    61  	// The no. of NodeSpec updates NC can process concurrently.
    62  	cidrUpdateWorkers = 30
    63  
    64  	// The max no. of NodeSpec updates that can be enqueued.
    65  	cidrUpdateQueueSize = 5000
    66  
    67  	// cidrUpdateRetries is the no. of times a NodeSpec update will be retried before dropping it.
    68  	cidrUpdateRetries = 3
    69  
    70  	// updateRetryTimeout is the time to wait before requeing a failed node for retry
    71  	updateRetryTimeout = 250 * time.Millisecond
    72  
    73  	// maxUpdateRetryTimeout is the maximum amount of time between timeouts.
    74  	maxUpdateRetryTimeout = 5 * time.Second
    75  
    76  	// updateMaxRetries is the max retries for a failed node
    77  	updateMaxRetries = 10
    78  )
    79  
    80  // nodePollInterval is used in listing node
    81  // This is a variable instead of a const to enable testing.
    82  var nodePollInterval = 10 * time.Second
    83  
    84  // CIDRAllocator is an interface implemented by things that know how
    85  // to allocate/occupy/recycle CIDR for nodes.
    86  type CIDRAllocator interface {
    87  	// AllocateOrOccupyCIDR looks at the given node, assigns it a valid
    88  	// CIDR if it doesn't currently have one or mark the CIDR as used if
    89  	// the node already have one.
    90  	AllocateOrOccupyCIDR(logger klog.Logger, node *v1.Node) error
    91  	// ReleaseCIDR releases the CIDR of the removed node.
    92  	ReleaseCIDR(logger klog.Logger, node *v1.Node) error
    93  	// Run starts all the working logic of the allocator.
    94  	Run(ctx context.Context)
    95  }
    96  
    97  // CIDRAllocatorParams is parameters that's required for creating new
    98  // cidr range allocator.
    99  type CIDRAllocatorParams struct {
   100  	// ClusterCIDRs is list of cluster cidrs.
   101  	ClusterCIDRs []*net.IPNet
   102  	// ServiceCIDR is primary service cidr for cluster.
   103  	ServiceCIDR *net.IPNet
   104  	// SecondaryServiceCIDR is secondary service cidr for cluster.
   105  	SecondaryServiceCIDR *net.IPNet
   106  	// NodeCIDRMaskSizes is list of node cidr mask sizes.
   107  	NodeCIDRMaskSizes []int
   108  }
   109  
   110  // CIDRs are reserved, then node resource is patched with them.
   111  // nodeReservedCIDRs holds the reservation info for a node.
   112  type nodeReservedCIDRs struct {
   113  	allocatedCIDRs []*net.IPNet
   114  	nodeName       string
   115  }
   116  
   117  // New creates a new CIDR range allocator.
   118  func New(ctx context.Context, kubeClient clientset.Interface, cloud cloudprovider.Interface, nodeInformer informers.NodeInformer, allocatorType CIDRAllocatorType, allocatorParams CIDRAllocatorParams) (CIDRAllocator, error) {
   119  	logger := klog.FromContext(ctx)
   120  	nodeList, err := listNodes(logger, kubeClient)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  
   125  	switch allocatorType {
   126  	case RangeAllocatorType:
   127  		return NewCIDRRangeAllocator(ctx, kubeClient, nodeInformer, allocatorParams, nodeList)
   128  	case CloudAllocatorType:
   129  		return NewCloudCIDRAllocator(ctx, kubeClient, cloud, nodeInformer)
   130  	default:
   131  		return nil, fmt.Errorf("invalid CIDR allocator type: %v", allocatorType)
   132  	}
   133  }
   134  
   135  func listNodes(logger klog.Logger, kubeClient clientset.Interface) (*v1.NodeList, error) {
   136  	var nodeList *v1.NodeList
   137  	// We must poll because apiserver might not be up. This error causes
   138  	// controller manager to restart.
   139  	if pollErr := wait.Poll(nodePollInterval, apiserverStartupGracePeriod, func() (bool, error) {
   140  		var err error
   141  		nodeList, err = kubeClient.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{
   142  			FieldSelector: fields.Everything().String(),
   143  			LabelSelector: labels.Everything().String(),
   144  		})
   145  		if err != nil {
   146  			logger.Error(err, "Failed to list all nodes")
   147  			return false, nil
   148  		}
   149  		return true, nil
   150  	}); pollErr != nil {
   151  		return nil, fmt.Errorf("failed to list all nodes in %v, cannot proceed without updating CIDR map",
   152  			apiserverStartupGracePeriod)
   153  	}
   154  	return nodeList, nil
   155  }
   156  
   157  // ipnetToStringList converts a slice of net.IPNet into a list of CIDR in string format
   158  func ipnetToStringList(inCIDRs []*net.IPNet) []string {
   159  	outCIDRs := make([]string, len(inCIDRs))
   160  	for idx, inCIDR := range inCIDRs {
   161  		outCIDRs[idx] = inCIDR.String()
   162  	}
   163  	return outCIDRs
   164  }
   165  
   166  // occupyServiceCIDR removes the service CIDR range from the cluster CIDR if it
   167  // intersects.
   168  func occupyServiceCIDR(set *cidrset.CidrSet, clusterCIDR, serviceCIDR *net.IPNet) error {
   169  	if clusterCIDR.Contains(serviceCIDR.IP) || serviceCIDR.Contains(clusterCIDR.IP) {
   170  		if err := set.Occupy(serviceCIDR); err != nil {
   171  			return err
   172  		}
   173  	}
   174  	return nil
   175  }
   176  

View as plain text