diff --git a/cmd/cloud-controller-manager/.import-restrictions b/cmd/cloud-controller-manager/.import-restrictions index 4515e2f7be5..151e8744804 100644 --- a/cmd/cloud-controller-manager/.import-restrictions +++ b/cmd/cloud-controller-manager/.import-restrictions @@ -1,6 +1,8 @@ rules: - selectorRegexp: k8s[.]io/kubernetes allowedPrefixes: + - k8s.io/kubernetes/cmd/kube-controller-manager/app/options + - k8s.io/kubernetes/cmd/kube-controller-manager/app/config - k8s.io/kubernetes/pkg/api/legacyscheme - k8s.io/kubernetes/pkg/api/service - k8s.io/kubernetes/pkg/api/v1/pod @@ -34,4 +36,7 @@ rules: - k8s.io/kubernetes/pkg/util/hash - k8s.io/kubernetes/pkg/util/node - k8s.io/kubernetes/pkg/util/parsers - - k8s.io/kubernetes/pkg/util/taints \ No newline at end of file + - k8s.io/kubernetes/pkg/util/taints + - k8s.io/kubernetes/pkg/proxy/util + - k8s.io/kubernetes/pkg/proxy/util/testing + - k8s.io/kubernetes/pkg/util/sysctl \ No newline at end of file diff --git a/cmd/cloud-controller-manager/main.go b/cmd/cloud-controller-manager/main.go index 8d59739a521..e5373b1e7ca 100644 --- a/cmd/cloud-controller-manager/main.go +++ b/cmd/cloud-controller-manager/main.go @@ -42,6 +42,7 @@ import ( _ "k8s.io/component-base/metrics/prometheus/version" // for version metric registration genericcontrollermanager "k8s.io/controller-manager/app" "k8s.io/klog/v2" + nodeipamcontrolleroptions "k8s.io/kubernetes/cmd/kube-controller-manager/app/options" nodeipamconfig "k8s.io/kubernetes/pkg/controller/nodeipam/config" // For existing cloud providers, the option to import legacy providers is still available. // e.g. _"k8s.io/legacy-cloud-providers/" @@ -60,35 +61,6 @@ func main() { klog.Fatalf("unable to initialize command options: %v", err) } - cloudInitializer := func(config *cloudcontrollerconfig.CompletedConfig) cloudprovider.Interface { - cloudConfigFile := config.ComponentConfig.KubeCloudShared.CloudProvider.CloudConfigFile - // initialize cloud provider with the cloud provider name and config file provided - cloud, err := cloudprovider.InitCloudProvider(cloudProviderName, cloudConfigFile) - if err != nil { - klog.Fatalf("Cloud provider could not be initialized: %v", err) - } - if cloud == nil { - klog.Fatalf("Cloud provider is nil") - } - - if !cloud.HasClusterID() { - if config.ComponentConfig.KubeCloudShared.AllowUntaggedCloud { - klog.Warning("detected a cluster without a ClusterID. A ClusterID will be required in the future. Please tag your cluster to avoid any future issues") - } else { - klog.Fatalf("no ClusterID found. A ClusterID is required for the cloud provider to function properly. This check can be bypassed by setting the allow-untagged-cloud option") - } - } - - // Initialize the cloud provider with a reference to the clientBuilder - cloud.Initialize(config.ClientBuilder, make(chan struct{})) - // Set the informer on the user cloud object - if informerUserCloud, ok := cloud.(cloudprovider.InformerUser); ok { - informerUserCloud.SetInformers(config.SharedInformers) - } - - return cloud - } - controllerInitializers := app.DefaultInitFuncConstructors // Here is an example to remove the controller which is not needed. // e.g. remove the cloud-node-lifecycle controller which current cloud provider does not need. @@ -99,7 +71,7 @@ func main() { // If you do not need additional controller, please ignore. controllerInitializers["nodeipam"] = startNodeIpamControllerWrapper - command := app.NewCloudControllerManagerCommand(ccmOptions, cloudInitializer, controllerInitializers) + command := app.NewCloudControllerManagerCommand(cloudProviderName, ccmOptions, cloudInitializer, controllerInitializers) // TODO: once we switch everything over to Cobra commands, we can go back to calling // utilflag.InitFlags() (by removing its pflag.Parse() call). For now, we have to set the @@ -115,14 +87,46 @@ func main() { } } -func startNodeIpamControllerWrapper(completedConfig *cloudcontrollerconfig.CompletedConfig, cloud cloudprovider.Interface) app.InitFunc { - nodeIPAMConfig := nodeipamconfig.NodeIPAMControllerConfiguration{ - ServiceCIDR: "sample", - SecondaryServiceCIDR: "sample", - NodeCIDRMaskSize: 11, - NodeCIDRMaskSizeIPv4: 11, - NodeCIDRMaskSizeIPv6: 111, +func cloudInitializer(config *cloudcontrollerconfig.CompletedConfig) cloudprovider.Interface { + cloudConfigFile := config.ComponentConfig.KubeCloudShared.CloudProvider.CloudConfigFile + // initialize cloud provider with the cloud provider name and config file provided + cloud, err := cloudprovider.InitCloudProvider(cloudProviderName, cloudConfigFile) + if err != nil { + klog.Fatalf("Cloud provider could not be initialized: %v", err) } + if cloud == nil { + klog.Fatalf("Cloud provider is nil") + } + + if !cloud.HasClusterID() { + if config.ComponentConfig.KubeCloudShared.AllowUntaggedCloud { + klog.Warning("detected a cluster without a ClusterID. A ClusterID will be required in the future. Please tag your cluster to avoid any future issues") + } else { + klog.Fatalf("no ClusterID found. A ClusterID is required for the cloud provider to function properly. This check can be bypassed by setting the allow-untagged-cloud option") + } + } + + // Initialize the cloud provider with a reference to the clientBuilder + cloud.Initialize(config.ClientBuilder, make(chan struct{})) + // Set the informer on the user cloud object + if informerUserCloud, ok := cloud.(cloudprovider.InformerUser); ok { + informerUserCloud.SetInformers(config.SharedInformers) + } + + return cloud +} + +func startNodeIpamControllerWrapper(completedConfig *cloudcontrollerconfig.CompletedConfig, cloud cloudprovider.Interface) app.InitFunc { + fs := pflag.NewFlagSet("fs", pflag.ContinueOnError) + var nodeIPAMControllerOptions nodeipamcontrolleroptions.NodeIPAMControllerOptions + nodeIPAMControllerOptions.AddFlags(fs) + errors := nodeIPAMControllerOptions.Validate() + if len(errors) > 0 { + klog.Fatal("NodeIPAM controller values are not properly.") + } + var nodeIPAMConfig nodeipamconfig.NodeIPAMControllerConfiguration + nodeIPAMControllerOptions.ApplyTo(&nodeIPAMConfig) + return func(ctx genericcontrollermanager.ControllerContext) (http.Handler, bool, error) { return startNodeIpamController(completedConfig, nodeIPAMConfig, ctx, cloud) } diff --git a/staging/src/k8s.io/cloud-provider/app/controllermanager.go b/staging/src/k8s.io/cloud-provider/app/controllermanager.go index 6341213c7b7..58c93bd80e9 100644 --- a/staging/src/k8s.io/cloud-provider/app/controllermanager.go +++ b/staging/src/k8s.io/cloud-provider/app/controllermanager.go @@ -64,7 +64,7 @@ const ( ) // NewCloudControllerManagerCommand creates a *cobra.Command object with default parameters -func NewCloudControllerManagerCommand(s *options.CloudControllerManagerOptions, cloudInitializer InitCloudFunc, initFuncConstructor map[string]InitFuncConstructor) *cobra.Command { +func NewCloudControllerManagerCommand(cloudProviderName string, s *options.CloudControllerManagerOptions, cloudInitializer InitCloudFunc, initFuncConstructor map[string]InitFuncConstructor) *cobra.Command { cmd := &cobra.Command{ Use: "cloud-controller-manager", @@ -72,6 +72,11 @@ func NewCloudControllerManagerCommand(s *options.CloudControllerManagerOptions, the cloud specific control loops shipped with Kubernetes.`, Run: func(cmd *cobra.Command, args []string) { verflag.PrintAndExitIfRequested() + + cloudProviderFlag := cmd.Flags().Lookup("cloud-provider") + if cloudProviderFlag.Value.String() == "" { + cloudProviderFlag.Value.Set(cloudProviderName) + } cliflag.PrintFlags(cmd.Flags()) c, err := s.Config(ControllerNames(initFuncConstructor), ControllersDisabledByDefault.List()) @@ -130,8 +135,6 @@ the cloud specific control loops shipped with Kubernetes.`, return cmd } -type InitCloudFunc func(config *cloudcontrollerconfig.CompletedConfig) cloudprovider.Interface - // Run runs the ExternalCMServer. This should never exit. func Run(c *cloudcontrollerconfig.CompletedConfig, controllerInitializers map[string]InitFunc, stopCh <-chan struct{}) error { // To help debugging, immediately log version @@ -262,11 +265,15 @@ func startControllers(ctx genericcontrollermanager.ControllerContext, c *cloudco select {} } +// InitCloudFunc is used to initialize cloud +type InitCloudFunc func(config *cloudcontrollerconfig.CompletedConfig) cloudprovider.Interface + // InitFunc is used to launch a particular controller. It may run additional "should I activate checks". // Any error returned will cause the controller process to `Fatal` // The bool indicates whether the controller was enabled. type InitFunc func(ctx genericcontrollermanager.ControllerContext) (debuggingHandler http.Handler, enabled bool, err error) +// InitFuncConstructor is used to construct InitFunc type InitFuncConstructor func(completedConfig *cloudcontrollerconfig.CompletedConfig, cloud cloudprovider.Interface) InitFunc // ControllerNames indicate the default controller we are known. @@ -316,6 +323,7 @@ func startRouteControllerWrapper(completedConfig *cloudcontrollerconfig.Complete } } +// DefaultInitFuncConstructors is a map of default named controller groups paired with InitFuncConstructor var DefaultInitFuncConstructors = map[string]InitFuncConstructor{ "cloud-node": StartCloudNodeControllerWrapper, "cloud-node-lifecycle": startCloudNodeLifecycleControllerWrapper, diff --git a/staging/src/k8s.io/cloud-provider/sample/basic_main.go b/staging/src/k8s.io/cloud-provider/sample/basic_main.go index 90f091294e7..50592eb85ca 100644 --- a/staging/src/k8s.io/cloud-provider/sample/basic_main.go +++ b/staging/src/k8s.io/cloud-provider/sample/basic_main.go @@ -18,7 +18,7 @@ limitations under the License. // For an minimal working example, please refer to k8s.io/cloud-provider/sample/basic_main.go // For more details, please refer to k8s.io/kubernetes/cmd/cloud-controller-manager/main.go -package sample +package main import ( "math/rand" @@ -54,36 +54,7 @@ func main() { klog.Fatalf("unable to initialize command options: %v", err) } - cloudInitializer := func(config *config.CompletedConfig) cloudprovider.Interface { - cloudConfigFile := config.ComponentConfig.KubeCloudShared.CloudProvider.CloudConfigFile - // initialize cloud provider with the cloud provider name and config file provided - cloud, err := cloudprovider.InitCloudProvider(sampleCloudProviderName, cloudConfigFile) - if err != nil { - klog.Fatalf("Cloud provider could not be initialized: %v", err) - } - if cloud == nil { - klog.Fatalf("Cloud provider is nil") - } - - if !cloud.HasClusterID() { - if config.ComponentConfig.KubeCloudShared.AllowUntaggedCloud { - klog.Warning("detected a cluster without a ClusterID. A ClusterID will be required in the future. Please tag your cluster to avoid any future issues") - } else { - klog.Fatalf("no ClusterID found. A ClusterID is required for the cloud provider to function properly. This check can be bypassed by setting the allow-untagged-cloud option") - } - } - - // Initialize the cloud provider with a reference to the clientBuilder - cloud.Initialize(config.ClientBuilder, make(chan struct{})) - // Set the informer on the user cloud object - if informerUserCloud, ok := cloud.(cloudprovider.InformerUser); ok { - informerUserCloud.SetInformers(config.SharedInformers) - } - - return cloud - } - - command := app.NewCloudControllerManagerCommand(ccmOptions, cloudInitializer, app.DefaultInitFuncConstructors) + command := app.NewCloudControllerManagerCommand(sampleCloudProviderName, ccmOptions, cloudInitializer, app.DefaultInitFuncConstructors) // TODO: once we switch everything over to Cobra commands, we can go back to calling // utilflag.InitFlags() (by removing its pflag.Parse() call). For now, we have to set the @@ -98,3 +69,32 @@ func main() { os.Exit(1) } } + +func cloudInitializer(config *config.CompletedConfig) cloudprovider.Interface { + cloudConfigFile := config.ComponentConfig.KubeCloudShared.CloudProvider.CloudConfigFile + // initialize cloud provider with the cloud provider name and config file provided + cloud, err := cloudprovider.InitCloudProvider(sampleCloudProviderName, cloudConfigFile) + if err != nil { + klog.Fatalf("Cloud provider could not be initialized: %v", err) + } + if cloud == nil { + klog.Fatalf("Cloud provider is nil") + } + + if !cloud.HasClusterID() { + if config.ComponentConfig.KubeCloudShared.AllowUntaggedCloud { + klog.Warning("detected a cluster without a ClusterID. A ClusterID will be required in the future. Please tag your cluster to avoid any future issues") + } else { + klog.Fatalf("no ClusterID found. A ClusterID is required for the cloud provider to function properly. This check can be bypassed by setting the allow-untagged-cloud option") + } + } + + // Initialize the cloud provider with a reference to the clientBuilder + cloud.Initialize(config.ClientBuilder, make(chan struct{})) + // Set the informer on the user cloud object + if informerUserCloud, ok := cloud.(cloudprovider.InformerUser); ok { + informerUserCloud.SetInformers(config.SharedInformers) + } + + return cloud +}