2017-10-11 19:36:39 -04:00
/ *
Copyright 2014 The Kubernetes Authors .
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
package nodeipam
import (
2022-09-22 02:37:36 -04:00
"context"
2023-03-02 09:00:47 -05:00
"fmt"
2025-10-27 09:50:46 -04:00
"net"
2017-10-11 19:36:39 -04:00
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
coreinformers "k8s.io/client-go/informers/core/v1"
clientset "k8s.io/client-go/kubernetes"
2022-08-05 15:24:18 -04:00
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
2017-10-11 19:36:39 -04:00
corelisters "k8s.io/client-go/listers/core/v1"
2022-08-05 15:24:18 -04:00
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record"
2018-09-05 18:58:22 -04:00
cloudprovider "k8s.io/cloud-provider"
2022-07-27 10:30:40 -04:00
controllersmetrics "k8s.io/component-base/metrics/prometheus/controllers"
2022-08-05 15:24:18 -04:00
"k8s.io/klog/v2"
2017-10-11 19:36:39 -04:00
"k8s.io/kubernetes/pkg/controller/nodeipam/ipam"
)
2022-11-03 07:44:50 -04:00
// ipamController is an interface abstracting an interface for
2024-06-06 12:18:38 -04:00
// legacy mode.
2022-11-03 07:44:50 -04:00
type ipamController interface {
2022-09-22 02:37:36 -04:00
Run ( ctx context . Context )
2022-11-03 07:44:50 -04:00
}
2017-10-11 19:36:39 -04:00
// Controller is the controller that manages node ipam state.
type Controller struct {
2018-04-23 22:01:01 -04:00
allocatorType ipam . CIDRAllocatorType
2017-10-11 19:36:39 -04:00
2019-08-19 16:53:18 -04:00
cloud cloudprovider . Interface
clusterCIDRs [ ] * net . IPNet
serviceCIDR * net . IPNet
secondaryServiceCIDR * net . IPNet
kubeClient clientset . Interface
2022-10-26 08:51:46 -04:00
eventBroadcaster record . EventBroadcaster
2017-10-11 19:36:39 -04:00
nodeLister corelisters . NodeLister
nodeInformerSynced cache . InformerSynced
2022-11-03 07:44:50 -04:00
legacyIPAM ipamController
2017-10-11 19:36:39 -04:00
cidrAllocator ipam . CIDRAllocator
}
// NewNodeIpamController returns a new node IP Address Management controller to
// sync instances from cloudprovider.
// This method returns an error if it is unable to initialize the CIDR bitmap with
// podCIDRs it has already allocated to nodes. Since we don't allow podCIDR changes
// currently, this should be handled as a fatal error.
func NewNodeIpamController (
2022-09-22 02:37:36 -04:00
ctx context . Context ,
2017-10-11 19:36:39 -04:00
nodeInformer coreinformers . NodeInformer ,
cloud cloudprovider . Interface ,
kubeClient clientset . Interface ,
2019-06-11 12:04:50 -04:00
clusterCIDRs [ ] * net . IPNet ,
2017-10-11 19:36:39 -04:00
serviceCIDR * net . IPNet ,
2019-08-19 16:53:18 -04:00
secondaryServiceCIDR * net . IPNet ,
2019-07-09 17:47:01 -04:00
nodeCIDRMaskSizes [ ] int ,
2017-10-11 19:36:39 -04:00
allocatorType ipam . CIDRAllocatorType ) ( * Controller , error ) {
if kubeClient == nil {
2023-03-02 09:00:47 -05:00
return nil , fmt . Errorf ( "kubeClient is nil when starting Controller" )
2017-10-11 19:36:39 -04:00
}
2019-06-11 12:04:50 -04:00
// Cloud CIDR allocator does not rely on clusterCIDR or nodeCIDRMaskSize for allocation.
2018-09-21 16:22:29 -04:00
if allocatorType != ipam . CloudAllocatorType {
2019-06-11 12:04:50 -04:00
if len ( clusterCIDRs ) == 0 {
2023-03-02 09:00:47 -05:00
return nil , fmt . Errorf ( "Controller: Must specify --cluster-cidr if --allocate-node-cidrs is set" )
2019-02-08 20:33:31 -05:00
}
2019-06-11 12:04:50 -04:00
2019-07-09 17:47:01 -04:00
for idx , cidr := range clusterCIDRs {
2019-06-11 12:04:50 -04:00
mask := cidr . Mask
2019-07-09 17:47:01 -04:00
if maskSize , _ := mask . Size ( ) ; maskSize > nodeCIDRMaskSizes [ idx ] {
2023-03-02 09:00:47 -05:00
return nil , fmt . Errorf ( "Controller: Invalid --cluster-cidr, mask size of cluster CIDR must be less than or equal to --node-cidr-mask-size configured for CIDR family" )
2019-06-11 12:04:50 -04:00
}
2018-09-21 16:22:29 -04:00
}
2017-10-11 19:36:39 -04:00
}
ic := & Controller {
2019-08-19 16:53:18 -04:00
cloud : cloud ,
kubeClient : kubeClient ,
2023-12-13 03:11:08 -05:00
eventBroadcaster : record . NewBroadcaster ( record . WithContext ( ctx ) ) ,
2019-08-19 16:53:18 -04:00
clusterCIDRs : clusterCIDRs ,
serviceCIDR : serviceCIDR ,
secondaryServiceCIDR : secondaryServiceCIDR ,
allocatorType : allocatorType ,
2017-10-11 19:36:39 -04:00
}
// TODO: Abstract this check into a generic controller manager should run method.
2018-04-23 22:01:01 -04:00
if ic . allocatorType == ipam . IPAMFromClusterAllocatorType || ic . allocatorType == ipam . IPAMFromCloudAllocatorType {
2023-03-02 09:00:47 -05:00
var err error
2023-12-13 03:11:08 -05:00
ic . legacyIPAM , err = createLegacyIPAM ( ctx , ic , nodeInformer , cloud , kubeClient , clusterCIDRs , serviceCIDR , nodeCIDRMaskSizes )
2023-03-02 09:00:47 -05:00
if err != nil {
return nil , err
}
2018-04-23 22:01:01 -04:00
} else {
var err error
2019-07-09 17:47:01 -04:00
allocatorParams := ipam . CIDRAllocatorParams {
ClusterCIDRs : clusterCIDRs ,
ServiceCIDR : ic . serviceCIDR ,
SecondaryServiceCIDR : ic . secondaryServiceCIDR ,
NodeCIDRMaskSizes : nodeCIDRMaskSizes ,
}
2023-10-13 17:31:29 -04:00
ic . cidrAllocator , err = ipam . New ( ctx , kubeClient , cloud , nodeInformer , ic . allocatorType , allocatorParams )
2018-04-23 22:01:01 -04:00
if err != nil {
return nil , err
2017-10-11 19:36:39 -04:00
}
}
ic . nodeLister = nodeInformer . Lister ( )
ic . nodeInformerSynced = nodeInformer . Informer ( ) . HasSynced
return ic , nil
}
// Run starts an asynchronous loop that monitors the status of cluster nodes.
2022-09-22 02:37:36 -04:00
func ( nc * Controller ) Run ( ctx context . Context ) {
2025-09-24 02:08:12 -04:00
defer utilruntime . HandleCrashWithContext ( ctx )
2017-10-11 19:36:39 -04:00
2022-10-26 08:51:46 -04:00
// Start event processing pipeline.
2023-12-13 03:11:08 -05:00
nc . eventBroadcaster . StartStructuredLogging ( 3 )
2022-10-26 08:51:46 -04:00
nc . eventBroadcaster . StartRecordingToSink ( & v1core . EventSinkImpl { Interface : nc . kubeClient . CoreV1 ( ) . Events ( "" ) } )
defer nc . eventBroadcaster . Shutdown ( )
2022-09-22 02:37:36 -04:00
klog . FromContext ( ctx ) . Info ( "Starting ipam controller" )
defer klog . FromContext ( ctx ) . Info ( "Shutting down ipam controller" )
2022-10-26 08:51:46 -04:00
2025-09-17 02:48:02 -04:00
if ! cache . WaitForNamedCacheSyncWithContext ( ctx , nc . nodeInformerSynced ) {
2017-10-11 19:36:39 -04:00
return
}
2022-11-03 07:44:50 -04:00
if nc . allocatorType == ipam . IPAMFromClusterAllocatorType || nc . allocatorType == ipam . IPAMFromCloudAllocatorType {
2025-10-27 09:50:46 -04:00
nc . legacyIPAM . Run ( ctx )
2022-11-03 07:44:50 -04:00
} else {
2025-10-27 09:50:46 -04:00
nc . cidrAllocator . Run ( ctx )
2017-10-11 19:36:39 -04:00
}
}
2022-07-27 10:30:40 -04:00
// RunWithMetrics is a wrapper for Run that also tracks starting and stopping of the nodeipam controller with additional metric
2022-09-22 02:37:36 -04:00
func ( nc * Controller ) RunWithMetrics ( ctx context . Context , controllerManagerMetrics * controllersmetrics . ControllerManagerMetrics ) {
2022-07-27 10:30:40 -04:00
controllerManagerMetrics . ControllerStarted ( "nodeipam" )
defer controllerManagerMetrics . ControllerStopped ( "nodeipam" )
2022-09-22 02:37:36 -04:00
nc . Run ( ctx )
2022-07-27 10:30:40 -04:00
}