k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/controller/nodeipam/ipam/cidr_allocator.go (about) 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 // cidrUpdateRetries is the no. of times a NodeSpec update will be retried before dropping it. 65 cidrUpdateRetries = 3 66 ) 67 68 // nodePollInterval is used in listing node 69 var nodePollInterval = 10 * time.Second 70 71 // CIDRAllocator is an interface implemented by things that know how 72 // to allocate/occupy/recycle CIDR for nodes. 73 type CIDRAllocator interface { 74 // AllocateOrOccupyCIDR looks at the given node, assigns it a valid 75 // CIDR if it doesn't currently have one or mark the CIDR as used if 76 // the node already have one. 77 AllocateOrOccupyCIDR(ctx context.Context, node *v1.Node) error 78 // ReleaseCIDR releases the CIDR of the removed node. 79 ReleaseCIDR(logger klog.Logger, node *v1.Node) error 80 // Run starts all the working logic of the allocator. 81 Run(ctx context.Context) 82 } 83 84 // CIDRAllocatorParams is parameters that's required for creating new 85 // cidr range allocator. 86 type CIDRAllocatorParams struct { 87 // ClusterCIDRs is list of cluster cidrs. 88 ClusterCIDRs []*net.IPNet 89 // ServiceCIDR is primary service cidr for cluster. 90 ServiceCIDR *net.IPNet 91 // SecondaryServiceCIDR is secondary service cidr for cluster. 92 SecondaryServiceCIDR *net.IPNet 93 // NodeCIDRMaskSizes is list of node cidr mask sizes. 94 NodeCIDRMaskSizes []int 95 } 96 97 // New creates a new CIDR range allocator. 98 func New(ctx context.Context, kubeClient clientset.Interface, cloud cloudprovider.Interface, nodeInformer informers.NodeInformer, allocatorType CIDRAllocatorType, allocatorParams CIDRAllocatorParams) (CIDRAllocator, error) { 99 nodeList, err := listNodes(ctx, kubeClient) 100 if err != nil { 101 return nil, err 102 } 103 104 switch allocatorType { 105 case RangeAllocatorType: 106 return NewCIDRRangeAllocator(ctx, kubeClient, nodeInformer, allocatorParams, nodeList) 107 default: 108 return nil, fmt.Errorf("invalid CIDR allocator type: %v", allocatorType) 109 } 110 } 111 112 func listNodes(ctx context.Context, kubeClient clientset.Interface) (*v1.NodeList, error) { 113 var nodeList *v1.NodeList 114 logger := klog.FromContext(ctx) 115 116 // We must poll because apiserver might not be up. This error causes 117 // controller manager to restart. 118 if pollErr := wait.PollUntilContextTimeout(ctx, nodePollInterval, apiserverStartupGracePeriod, true, func(ctx context.Context) (bool, error) { 119 var err error 120 nodeList, err = kubeClient.CoreV1().Nodes().List(ctx, metav1.ListOptions{ 121 FieldSelector: fields.Everything().String(), 122 LabelSelector: labels.Everything().String(), 123 }) 124 if err != nil { 125 logger.Error(err, "Failed to list all nodes") 126 return false, nil 127 } 128 return true, nil 129 }); pollErr != nil { 130 return nil, fmt.Errorf("failed to list all nodes in %v, cannot proceed without updating CIDR map", 131 apiserverStartupGracePeriod) 132 } 133 return nodeList, nil 134 } 135 136 // ipnetToStringList converts a slice of net.IPNet into a list of CIDR in string format 137 func ipnetToStringList(inCIDRs []*net.IPNet) []string { 138 outCIDRs := make([]string, len(inCIDRs)) 139 for idx, inCIDR := range inCIDRs { 140 outCIDRs[idx] = inCIDR.String() 141 } 142 return outCIDRs 143 } 144 145 // occupyServiceCIDR removes the service CIDR range from the cluster CIDR if it 146 // intersects. 147 func occupyServiceCIDR(set *cidrset.CidrSet, clusterCIDR, serviceCIDR *net.IPNet) error { 148 if clusterCIDR.Contains(serviceCIDR.IP) || serviceCIDR.Contains(clusterCIDR.IP) { 149 if err := set.Occupy(serviceCIDR); err != nil { 150 return err 151 } 152 } 153 return nil 154 }