options.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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. s.Generic.LeaderElection.ResourceName = "cloud-controller-manager"
  94. s.Generic.LeaderElection.ResourceNamespace = "kube-system"
  95. return &s, nil
  96. }
  97. // NewDefaultComponentConfig returns cloud-controller manager configuration object.
  98. func NewDefaultComponentConfig(insecurePort int32) (*ccmconfig.CloudControllerManagerConfiguration, error) {
  99. versioned := &ccmconfigv1alpha1.CloudControllerManagerConfiguration{}
  100. ccmconfigscheme.Scheme.Default(versioned)
  101. internal := &ccmconfig.CloudControllerManagerConfiguration{}
  102. if err := ccmconfigscheme.Scheme.Convert(versioned, internal, nil); err != nil {
  103. return nil, err
  104. }
  105. internal.Generic.Port = insecurePort
  106. return internal, nil
  107. }
  108. // Flags returns flags for a specific APIServer by section name
  109. func (o *CloudControllerManagerOptions) Flags(allControllers, disabledByDefaultControllers []string) cliflag.NamedFlagSets {
  110. fss := cliflag.NamedFlagSets{}
  111. o.Generic.AddFlags(&fss, allControllers, disabledByDefaultControllers)
  112. o.KubeCloudShared.AddFlags(fss.FlagSet("generic"))
  113. o.ServiceController.AddFlags(fss.FlagSet("service controller"))
  114. o.SecureServing.AddFlags(fss.FlagSet("secure serving"))
  115. o.InsecureServing.AddUnqualifiedFlags(fss.FlagSet("insecure serving"))
  116. o.Authentication.AddFlags(fss.FlagSet("authentication"))
  117. o.Authorization.AddFlags(fss.FlagSet("authorization"))
  118. fs := fss.FlagSet("misc")
  119. fs.StringVar(&o.Master, "master", o.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig).")
  120. fs.StringVar(&o.Kubeconfig, "kubeconfig", o.Kubeconfig, "Path to kubeconfig file with authorization and master location information.")
  121. fs.DurationVar(&o.NodeStatusUpdateFrequency.Duration, "node-status-update-frequency", o.NodeStatusUpdateFrequency.Duration, "Specifies how often the controller updates nodes' status.")
  122. utilfeature.DefaultMutableFeatureGate.AddFlag(fss.FlagSet("generic"))
  123. return fss
  124. }
  125. // ApplyTo fills up cloud controller manager config with options.
  126. func (o *CloudControllerManagerOptions) ApplyTo(c *cloudcontrollerconfig.Config, userAgent string) error {
  127. var err error
  128. if err = o.Generic.ApplyTo(&c.ComponentConfig.Generic); err != nil {
  129. return err
  130. }
  131. if err = o.KubeCloudShared.ApplyTo(&c.ComponentConfig.KubeCloudShared); err != nil {
  132. return err
  133. }
  134. if err = o.ServiceController.ApplyTo(&c.ComponentConfig.ServiceController); err != nil {
  135. return err
  136. }
  137. if err = o.InsecureServing.ApplyTo(&c.InsecureServing, &c.LoopbackClientConfig); err != nil {
  138. return err
  139. }
  140. if err = o.SecureServing.ApplyTo(&c.SecureServing, &c.LoopbackClientConfig); err != nil {
  141. return err
  142. }
  143. if o.SecureServing.BindPort != 0 || o.SecureServing.Listener != nil {
  144. if err = o.Authentication.ApplyTo(&c.Authentication, c.SecureServing, nil); err != nil {
  145. return err
  146. }
  147. if err = o.Authorization.ApplyTo(&c.Authorization); err != nil {
  148. return err
  149. }
  150. }
  151. c.Kubeconfig, err = clientcmd.BuildConfigFromFlags(o.Master, o.Kubeconfig)
  152. if err != nil {
  153. return err
  154. }
  155. c.Kubeconfig.DisableCompression = true
  156. c.Kubeconfig.ContentConfig.AcceptContentTypes = o.Generic.ClientConnection.AcceptContentTypes
  157. c.Kubeconfig.ContentConfig.ContentType = o.Generic.ClientConnection.ContentType
  158. c.Kubeconfig.QPS = o.Generic.ClientConnection.QPS
  159. c.Kubeconfig.Burst = int(o.Generic.ClientConnection.Burst)
  160. c.Client, err = clientset.NewForConfig(restclient.AddUserAgent(c.Kubeconfig, userAgent))
  161. if err != nil {
  162. return err
  163. }
  164. c.LeaderElectionClient = clientset.NewForConfigOrDie(restclient.AddUserAgent(c.Kubeconfig, "leader-election"))
  165. c.EventRecorder = createRecorder(c.Client, userAgent)
  166. rootClientBuilder := controller.SimpleControllerClientBuilder{
  167. ClientConfig: c.Kubeconfig,
  168. }
  169. if c.ComponentConfig.KubeCloudShared.UseServiceAccountCredentials {
  170. c.ClientBuilder = controller.SAControllerClientBuilder{
  171. ClientConfig: restclient.AnonymousClientConfig(c.Kubeconfig),
  172. CoreClient: c.Client.CoreV1(),
  173. AuthenticationClient: c.Client.AuthenticationV1(),
  174. Namespace: metav1.NamespaceSystem,
  175. }
  176. } else {
  177. c.ClientBuilder = rootClientBuilder
  178. }
  179. c.VersionedClient = rootClientBuilder.ClientOrDie("shared-informers")
  180. c.SharedInformers = informers.NewSharedInformerFactory(c.VersionedClient, resyncPeriod(c)())
  181. // sync back to component config
  182. // TODO: find more elegant way than syncing back the values.
  183. c.ComponentConfig.Generic.Port = int32(o.InsecureServing.BindPort)
  184. c.ComponentConfig.Generic.Address = o.InsecureServing.BindAddress.String()
  185. c.ComponentConfig.NodeStatusUpdateFrequency = o.NodeStatusUpdateFrequency
  186. return nil
  187. }
  188. // Validate is used to validate config before launching the cloud controller manager
  189. func (o *CloudControllerManagerOptions) Validate(allControllers, disabledByDefaultControllers []string) error {
  190. errors := []error{}
  191. errors = append(errors, o.Generic.Validate(allControllers, disabledByDefaultControllers)...)
  192. errors = append(errors, o.KubeCloudShared.Validate()...)
  193. errors = append(errors, o.ServiceController.Validate()...)
  194. errors = append(errors, o.SecureServing.Validate()...)
  195. errors = append(errors, o.InsecureServing.Validate()...)
  196. errors = append(errors, o.Authentication.Validate()...)
  197. errors = append(errors, o.Authorization.Validate()...)
  198. if len(o.KubeCloudShared.CloudProvider.Name) == 0 {
  199. errors = append(errors, fmt.Errorf("--cloud-provider cannot be empty"))
  200. }
  201. return utilerrors.NewAggregate(errors)
  202. }
  203. // resyncPeriod computes the time interval a shared informer waits before resyncing with the api server
  204. func resyncPeriod(c *cloudcontrollerconfig.Config) func() time.Duration {
  205. return func() time.Duration {
  206. factor := rand.Float64() + 1
  207. return time.Duration(float64(c.ComponentConfig.Generic.MinResyncPeriod.Nanoseconds()) * factor)
  208. }
  209. }
  210. // Config return a cloud controller manager config objective
  211. func (o *CloudControllerManagerOptions) Config(allControllers, disabledByDefaultControllers []string) (*cloudcontrollerconfig.Config, error) {
  212. if err := o.Validate(allControllers, disabledByDefaultControllers); err != nil {
  213. return nil, err
  214. }
  215. if err := o.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost", nil, []net.IP{net.ParseIP("127.0.0.1")}); err != nil {
  216. return nil, fmt.Errorf("error creating self-signed certificates: %v", err)
  217. }
  218. c := &cloudcontrollerconfig.Config{}
  219. if err := o.ApplyTo(c, CloudControllerManagerUserAgent); err != nil {
  220. return nil, err
  221. }
  222. return c, nil
  223. }
  224. func createRecorder(kubeClient clientset.Interface, userAgent string) record.EventRecorder {
  225. eventBroadcaster := record.NewBroadcaster()
  226. eventBroadcaster.StartLogging(klog.Infof)
  227. eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")})
  228. // TODO: remove dependence on the legacyscheme
  229. return eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: userAgent})
  230. }