options.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package options
  14. import (
  15. "fmt"
  16. "math/rand"
  17. "net"
  18. "time"
  19. v1 "k8s.io/api/core/v1"
  20. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  21. utilerrors "k8s.io/apimachinery/pkg/util/errors"
  22. apiserveroptions "k8s.io/apiserver/pkg/server/options"
  23. utilfeature "k8s.io/apiserver/pkg/util/feature"
  24. "k8s.io/client-go/informers"
  25. clientset "k8s.io/client-go/kubernetes"
  26. v1core "k8s.io/client-go/kubernetes/typed/core/v1"
  27. restclient "k8s.io/client-go/rest"
  28. "k8s.io/client-go/tools/clientcmd"
  29. "k8s.io/client-go/tools/record"
  30. cliflag "k8s.io/component-base/cli/flag"
  31. "k8s.io/klog"
  32. ccmconfig "k8s.io/kubernetes/cmd/cloud-controller-manager/app/apis/config"
  33. ccmconfigscheme "k8s.io/kubernetes/cmd/cloud-controller-manager/app/apis/config/scheme"
  34. ccmconfigv1alpha1 "k8s.io/kubernetes/cmd/cloud-controller-manager/app/apis/config/v1alpha1"
  35. cloudcontrollerconfig "k8s.io/kubernetes/cmd/cloud-controller-manager/app/config"
  36. cmoptions "k8s.io/kubernetes/cmd/controller-manager/app/options"
  37. "k8s.io/kubernetes/pkg/api/legacyscheme"
  38. "k8s.io/kubernetes/pkg/controller"
  39. "k8s.io/kubernetes/pkg/master/ports"
  40. // add the kubernetes feature gates
  41. _ "k8s.io/kubernetes/pkg/features"
  42. )
  43. const (
  44. // CloudControllerManagerUserAgent is the userAgent name when starting cloud-controller managers.
  45. CloudControllerManagerUserAgent = "cloud-controller-manager"
  46. // DefaultInsecureCloudControllerManagerPort is the default insecure cloud-controller manager port.
  47. DefaultInsecureCloudControllerManagerPort = 0
  48. )
  49. // CloudControllerManagerOptions is the main context object for the controller manager.
  50. type CloudControllerManagerOptions struct {
  51. Generic *cmoptions.GenericControllerManagerConfigurationOptions
  52. KubeCloudShared *cmoptions.KubeCloudSharedOptions
  53. ServiceController *cmoptions.ServiceControllerOptions
  54. SecureServing *apiserveroptions.SecureServingOptionsWithLoopback
  55. // TODO: remove insecure serving mode
  56. InsecureServing *apiserveroptions.DeprecatedInsecureServingOptionsWithLoopback
  57. Authentication *apiserveroptions.DelegatingAuthenticationOptions
  58. Authorization *apiserveroptions.DelegatingAuthorizationOptions
  59. Master string
  60. Kubeconfig string
  61. // NodeStatusUpdateFrequency is the frequency at which the controller updates nodes' status
  62. NodeStatusUpdateFrequency metav1.Duration
  63. }
  64. // NewCloudControllerManagerOptions creates a new ExternalCMServer with a default config.
  65. func NewCloudControllerManagerOptions() (*CloudControllerManagerOptions, error) {
  66. componentConfig, err := NewDefaultComponentConfig(DefaultInsecureCloudControllerManagerPort)
  67. if err != nil {
  68. return nil, err
  69. }
  70. s := CloudControllerManagerOptions{
  71. Generic: cmoptions.NewGenericControllerManagerConfigurationOptions(&componentConfig.Generic),
  72. KubeCloudShared: cmoptions.NewKubeCloudSharedOptions(&componentConfig.KubeCloudShared),
  73. ServiceController: &cmoptions.ServiceControllerOptions{
  74. ServiceControllerConfiguration: &componentConfig.ServiceController,
  75. },
  76. SecureServing: apiserveroptions.NewSecureServingOptions().WithLoopback(),
  77. InsecureServing: (&apiserveroptions.DeprecatedInsecureServingOptions{
  78. BindAddress: net.ParseIP(componentConfig.Generic.Address),
  79. BindPort: int(componentConfig.Generic.Port),
  80. BindNetwork: "tcp",
  81. }).WithLoopback(),
  82. Authentication: apiserveroptions.NewDelegatingAuthenticationOptions(),
  83. Authorization: apiserveroptions.NewDelegatingAuthorizationOptions(),
  84. NodeStatusUpdateFrequency: componentConfig.NodeStatusUpdateFrequency,
  85. }
  86. s.Authentication.RemoteKubeConfigFileOptional = true
  87. s.Authorization.RemoteKubeConfigFileOptional = true
  88. s.Authorization.AlwaysAllowPaths = []string{"/healthz"}
  89. // Set the PairName but leave certificate directory blank to generate in-memory by default
  90. s.SecureServing.ServerCert.CertDirectory = ""
  91. s.SecureServing.ServerCert.PairName = "cloud-controller-manager"
  92. s.SecureServing.BindPort = ports.CloudControllerManagerPort
  93. return &s, nil
  94. }
  95. // NewDefaultComponentConfig returns cloud-controller manager configuration object.
  96. func NewDefaultComponentConfig(insecurePort int32) (*ccmconfig.CloudControllerManagerConfiguration, error) {
  97. versioned := &ccmconfigv1alpha1.CloudControllerManagerConfiguration{}
  98. ccmconfigscheme.Scheme.Default(versioned)
  99. internal := &ccmconfig.CloudControllerManagerConfiguration{}
  100. if err := ccmconfigscheme.Scheme.Convert(versioned, internal, nil); err != nil {
  101. return nil, err
  102. }
  103. internal.Generic.Port = insecurePort
  104. return internal, nil
  105. }
  106. // Flags returns flags for a specific APIServer by section name
  107. func (o *CloudControllerManagerOptions) Flags(allControllers, disabledByDefaultControllers []string) cliflag.NamedFlagSets {
  108. fss := cliflag.NamedFlagSets{}
  109. o.Generic.AddFlags(&fss, allControllers, disabledByDefaultControllers)
  110. o.KubeCloudShared.AddFlags(fss.FlagSet("generic"))
  111. o.ServiceController.AddFlags(fss.FlagSet("service controller"))
  112. o.SecureServing.AddFlags(fss.FlagSet("secure serving"))
  113. o.InsecureServing.AddUnqualifiedFlags(fss.FlagSet("insecure serving"))
  114. o.Authentication.AddFlags(fss.FlagSet("authentication"))
  115. o.Authorization.AddFlags(fss.FlagSet("authorization"))
  116. fs := fss.FlagSet("misc")
  117. fs.StringVar(&o.Master, "master", o.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig).")
  118. fs.StringVar(&o.Kubeconfig, "kubeconfig", o.Kubeconfig, "Path to kubeconfig file with authorization and master location information.")
  119. fs.DurationVar(&o.NodeStatusUpdateFrequency.Duration, "node-status-update-frequency", o.NodeStatusUpdateFrequency.Duration, "Specifies how often the controller updates nodes' status.")
  120. utilfeature.DefaultMutableFeatureGate.AddFlag(fss.FlagSet("generic"))
  121. return fss
  122. }
  123. // ApplyTo fills up cloud controller manager config with options.
  124. func (o *CloudControllerManagerOptions) ApplyTo(c *cloudcontrollerconfig.Config, userAgent string) error {
  125. var err error
  126. if err = o.Generic.ApplyTo(&c.ComponentConfig.Generic); err != nil {
  127. return err
  128. }
  129. if err = o.KubeCloudShared.ApplyTo(&c.ComponentConfig.KubeCloudShared); err != nil {
  130. return err
  131. }
  132. if err = o.ServiceController.ApplyTo(&c.ComponentConfig.ServiceController); err != nil {
  133. return err
  134. }
  135. if err = o.InsecureServing.ApplyTo(&c.InsecureServing, &c.LoopbackClientConfig); err != nil {
  136. return err
  137. }
  138. if err = o.SecureServing.ApplyTo(&c.SecureServing, &c.LoopbackClientConfig); err != nil {
  139. return err
  140. }
  141. if o.SecureServing.BindPort != 0 || o.SecureServing.Listener != nil {
  142. if err = o.Authentication.ApplyTo(&c.Authentication, c.SecureServing, nil); err != nil {
  143. return err
  144. }
  145. if err = o.Authorization.ApplyTo(&c.Authorization); err != nil {
  146. return err
  147. }
  148. }
  149. c.Kubeconfig, err = clientcmd.BuildConfigFromFlags(o.Master, o.Kubeconfig)
  150. if err != nil {
  151. return err
  152. }
  153. c.Kubeconfig.ContentConfig.ContentType = o.Generic.ClientConnection.ContentType
  154. c.Kubeconfig.QPS = o.Generic.ClientConnection.QPS
  155. c.Kubeconfig.Burst = int(o.Generic.ClientConnection.Burst)
  156. c.Client, err = clientset.NewForConfig(restclient.AddUserAgent(c.Kubeconfig, userAgent))
  157. if err != nil {
  158. return err
  159. }
  160. c.LeaderElectionClient = clientset.NewForConfigOrDie(restclient.AddUserAgent(c.Kubeconfig, "leader-election"))
  161. c.EventRecorder = createRecorder(c.Client, userAgent)
  162. rootClientBuilder := controller.SimpleControllerClientBuilder{
  163. ClientConfig: c.Kubeconfig,
  164. }
  165. if c.ComponentConfig.KubeCloudShared.UseServiceAccountCredentials {
  166. c.ClientBuilder = controller.SAControllerClientBuilder{
  167. ClientConfig: restclient.AnonymousClientConfig(c.Kubeconfig),
  168. CoreClient: c.Client.CoreV1(),
  169. AuthenticationClient: c.Client.AuthenticationV1(),
  170. Namespace: metav1.NamespaceSystem,
  171. }
  172. } else {
  173. c.ClientBuilder = rootClientBuilder
  174. }
  175. c.VersionedClient = rootClientBuilder.ClientOrDie("shared-informers")
  176. c.SharedInformers = informers.NewSharedInformerFactory(c.VersionedClient, resyncPeriod(c)())
  177. // sync back to component config
  178. // TODO: find more elegant way than syncing back the values.
  179. c.ComponentConfig.Generic.Port = int32(o.InsecureServing.BindPort)
  180. c.ComponentConfig.Generic.Address = o.InsecureServing.BindAddress.String()
  181. c.ComponentConfig.NodeStatusUpdateFrequency = o.NodeStatusUpdateFrequency
  182. return nil
  183. }
  184. // Validate is used to validate config before launching the cloud controller manager
  185. func (o *CloudControllerManagerOptions) Validate(allControllers, disabledByDefaultControllers []string) error {
  186. errors := []error{}
  187. errors = append(errors, o.Generic.Validate(allControllers, disabledByDefaultControllers)...)
  188. errors = append(errors, o.KubeCloudShared.Validate()...)
  189. errors = append(errors, o.ServiceController.Validate()...)
  190. errors = append(errors, o.SecureServing.Validate()...)
  191. errors = append(errors, o.InsecureServing.Validate()...)
  192. errors = append(errors, o.Authentication.Validate()...)
  193. errors = append(errors, o.Authorization.Validate()...)
  194. if len(o.KubeCloudShared.CloudProvider.Name) == 0 {
  195. errors = append(errors, fmt.Errorf("--cloud-provider cannot be empty"))
  196. }
  197. return utilerrors.NewAggregate(errors)
  198. }
  199. // resyncPeriod computes the time interval a shared informer waits before resyncing with the api server
  200. func resyncPeriod(c *cloudcontrollerconfig.Config) func() time.Duration {
  201. return func() time.Duration {
  202. factor := rand.Float64() + 1
  203. return time.Duration(float64(c.ComponentConfig.Generic.MinResyncPeriod.Nanoseconds()) * factor)
  204. }
  205. }
  206. // Config return a cloud controller manager config objective
  207. func (o *CloudControllerManagerOptions) Config(allControllers, disabledByDefaultControllers []string) (*cloudcontrollerconfig.Config, error) {
  208. if err := o.Validate(allControllers, disabledByDefaultControllers); err != nil {
  209. return nil, err
  210. }
  211. if err := o.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost", nil, []net.IP{net.ParseIP("127.0.0.1")}); err != nil {
  212. return nil, fmt.Errorf("error creating self-signed certificates: %v", err)
  213. }
  214. c := &cloudcontrollerconfig.Config{}
  215. if err := o.ApplyTo(c, CloudControllerManagerUserAgent); err != nil {
  216. return nil, err
  217. }
  218. return c, nil
  219. }
  220. func createRecorder(kubeClient clientset.Interface, userAgent string) record.EventRecorder {
  221. eventBroadcaster := record.NewBroadcaster()
  222. eventBroadcaster.StartLogging(klog.Infof)
  223. eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")})
  224. // TODO: remove dependence on the legacyscheme
  225. return eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: userAgent})
  226. }