2017-10-12 07:36:39 +08: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 (
"net"
"time"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
coreinformers "k8s.io/client-go/informers/core/v1"
2022-08-06 03:24:18 +08:00
networkinginformers "k8s.io/client-go/informers/networking/v1alpha1"
2017-10-12 07:36:39 +08:00
clientset "k8s.io/client-go/kubernetes"
2022-08-06 03:24:18 +08:00
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
2017-10-12 07:36:39 +08:00
corelisters "k8s.io/client-go/listers/core/v1"
2022-08-06 03:24:18 +08:00
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record"
2018-09-06 06:58:22 +08:00
cloudprovider "k8s.io/cloud-provider"
2022-07-27 22:30:40 +08:00
controllersmetrics "k8s.io/component-base/metrics/prometheus/controllers"
2022-08-06 03:24:18 +08:00
"k8s.io/klog/v2"
2017-10-12 07:36:39 +08:00
"k8s.io/kubernetes/pkg/controller/nodeipam/ipam"
)
const (
// ipamResyncInterval is the amount of time between when the cloud and node
// CIDR range assignments are synchronized.
ipamResyncInterval = 30 * time . Second
// ipamMaxBackoff is the maximum backoff for retrying synchronization of a
// given in the error state.
ipamMaxBackoff = 10 * time . Second
// ipamInitialRetry is the initial retry interval for retrying synchronization of a
// given in the error state.
ipamInitialBackoff = 250 * time . Millisecond
)
// Controller is the controller that manages node ipam state.
type Controller struct {
2018-04-24 10:01:01 +08:00
allocatorType ipam . CIDRAllocatorType
2017-10-12 07:36:39 +08:00
2019-08-20 04:53:18 +08:00
cloud cloudprovider . Interface
clusterCIDRs [ ] * net . IPNet
serviceCIDR * net . IPNet
secondaryServiceCIDR * net . IPNet
kubeClient clientset . Interface
2017-10-12 07:36:39 +08:00
// Method for easy mocking in unittest.
lookupIP func ( host string ) ( [ ] net . IP , error )
nodeLister corelisters . NodeLister
nodeInformerSynced cache . InformerSynced
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 (
nodeInformer coreinformers . NodeInformer ,
2022-08-06 03:24:18 +08:00
clusterCIDRInformer networkinginformers . ClusterCIDRInformer ,
2017-10-12 07:36:39 +08:00
cloud cloudprovider . Interface ,
kubeClient clientset . Interface ,
2019-06-12 00:04:50 +08:00
clusterCIDRs [ ] * net . IPNet ,
2017-10-12 07:36:39 +08:00
serviceCIDR * net . IPNet ,
2019-08-20 04:53:18 +08:00
secondaryServiceCIDR * net . IPNet ,
2019-07-10 05:47:01 +08:00
nodeCIDRMaskSizes [ ] int ,
2017-10-12 07:36:39 +08:00
allocatorType ipam . CIDRAllocatorType ) ( * Controller , error ) {
if kubeClient == nil {
2018-11-10 02:49:10 +08:00
klog . Fatalf ( "kubeClient is nil when starting Controller" )
2017-10-12 07:36:39 +08:00
}
eventBroadcaster := record . NewBroadcaster ( )
2020-06-09 11:01:45 +08:00
eventBroadcaster . StartStructuredLogging ( 0 )
2017-10-12 07:36:39 +08:00
2018-11-10 02:49:10 +08:00
klog . Infof ( "Sending events to api server." )
2017-10-12 07:36:39 +08:00
eventBroadcaster . StartRecordingToSink (
& v1core . EventSinkImpl {
2018-03-29 20:24:26 +08:00
Interface : kubeClient . CoreV1 ( ) . Events ( "" ) ,
2017-10-12 07:36:39 +08:00
} )
2019-06-12 00:04:50 +08:00
// Cloud CIDR allocator does not rely on clusterCIDR or nodeCIDRMaskSize for allocation.
2018-09-22 04:22:29 +08:00
if allocatorType != ipam . CloudAllocatorType {
2019-06-12 00:04:50 +08:00
if len ( clusterCIDRs ) == 0 {
2019-02-09 09:33:31 +08:00
klog . Fatal ( "Controller: Must specify --cluster-cidr if --allocate-node-cidrs is set" )
}
2019-06-12 00:04:50 +08:00
2019-07-10 05:47:01 +08:00
for idx , cidr := range clusterCIDRs {
2019-06-12 00:04:50 +08:00
mask := cidr . Mask
2019-07-10 05:47:01 +08:00
if maskSize , _ := mask . Size ( ) ; maskSize > nodeCIDRMaskSizes [ idx ] {
klog . Fatal ( "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-12 00:04:50 +08:00
}
2018-09-22 04:22:29 +08:00
}
2017-10-12 07:36:39 +08:00
}
ic := & Controller {
2019-08-20 04:53:18 +08:00
cloud : cloud ,
kubeClient : kubeClient ,
lookupIP : net . LookupIP ,
clusterCIDRs : clusterCIDRs ,
serviceCIDR : serviceCIDR ,
secondaryServiceCIDR : secondaryServiceCIDR ,
allocatorType : allocatorType ,
2017-10-12 07:36:39 +08:00
}
// TODO: Abstract this check into a generic controller manager should run method.
2018-04-24 10:01:01 +08:00
if ic . allocatorType == ipam . IPAMFromClusterAllocatorType || ic . allocatorType == ipam . IPAMFromCloudAllocatorType {
2019-07-10 05:47:01 +08:00
startLegacyIPAM ( ic , nodeInformer , cloud , kubeClient , clusterCIDRs , serviceCIDR , nodeCIDRMaskSizes )
2018-04-24 10:01:01 +08:00
} else {
var err error
2019-07-10 05:47:01 +08:00
allocatorParams := ipam . CIDRAllocatorParams {
ClusterCIDRs : clusterCIDRs ,
ServiceCIDR : ic . serviceCIDR ,
SecondaryServiceCIDR : ic . secondaryServiceCIDR ,
NodeCIDRMaskSizes : nodeCIDRMaskSizes ,
}
2022-08-06 03:24:18 +08:00
ic . cidrAllocator , err = ipam . New ( kubeClient , cloud , nodeInformer , clusterCIDRInformer , ic . allocatorType , allocatorParams )
2018-04-24 10:01:01 +08:00
if err != nil {
return nil , err
2017-10-12 07:36:39 +08: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.
func ( nc * Controller ) Run ( stopCh <- chan struct { } ) {
defer utilruntime . HandleCrash ( )
2018-11-10 02:49:10 +08:00
klog . Infof ( "Starting ipam controller" )
defer klog . Infof ( "Shutting down ipam controller" )
2017-10-12 07:36:39 +08:00
2019-08-17 03:15:53 +08:00
if ! cache . WaitForNamedCacheSync ( "node" , stopCh , nc . nodeInformerSynced ) {
2017-10-12 07:36:39 +08:00
return
}
2018-04-24 10:01:01 +08:00
if nc . allocatorType != ipam . IPAMFromClusterAllocatorType && nc . allocatorType != ipam . IPAMFromCloudAllocatorType {
go nc . cidrAllocator . Run ( stopCh )
2017-10-12 07:36:39 +08:00
}
<- stopCh
}
2022-07-27 22:30:40 +08:00
// RunWithMetrics is a wrapper for Run that also tracks starting and stopping of the nodeipam controller with additional metric
func ( nc * Controller ) RunWithMetrics ( stopCh <- chan struct { } , controllerManagerMetrics * controllersmetrics . ControllerManagerMetrics ) {
controllerManagerMetrics . ControllerStarted ( "nodeipam" )
defer controllerManagerMetrics . ControllerStopped ( "nodeipam" )
nc . Run ( stopCh )
}