k3s/vendor/k8s.io/kubernetes/cmd/kube-scheduler/app/options/options.go

370 lines
13 KiB
Go
Raw Normal View History

2019-01-12 04:58:27 +00:00
/*
Copyright 2018 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 options
import (
"fmt"
"net"
"os"
"strconv"
"time"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/uuid"
apiserveroptions "k8s.io/apiserver/pkg/server/options"
utilfeature "k8s.io/apiserver/pkg/util/feature"
clientset "k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
2020-08-10 17:43:49 +00:00
"k8s.io/client-go/tools/events"
2019-01-12 04:58:27 +00:00
"k8s.io/client-go/tools/leaderelection"
"k8s.io/client-go/tools/leaderelection/resourcelock"
"k8s.io/client-go/tools/record"
2019-04-07 17:07:55 +00:00
cliflag "k8s.io/component-base/cli/flag"
componentbaseconfig "k8s.io/component-base/config"
2020-08-10 17:43:49 +00:00
"k8s.io/component-base/config/options"
2020-03-26 21:07:15 +00:00
configv1alpha1 "k8s.io/component-base/config/v1alpha1"
2020-08-10 17:43:49 +00:00
"k8s.io/component-base/logs"
2020-03-26 21:07:15 +00:00
"k8s.io/component-base/metrics"
2020-08-10 17:43:49 +00:00
"k8s.io/klog/v2"
kubeschedulerconfigv1beta1 "k8s.io/kube-scheduler/config/v1beta1"
2019-01-12 04:58:27 +00:00
schedulerappconfig "k8s.io/kubernetes/cmd/kube-scheduler/app/config"
2019-12-12 01:27:03 +00:00
"k8s.io/kubernetes/pkg/scheduler"
2019-01-12 04:58:27 +00:00
kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
kubeschedulerscheme "k8s.io/kubernetes/pkg/scheduler/apis/config/scheme"
"k8s.io/kubernetes/pkg/scheduler/apis/config/validation"
)
// Options has all the params needed to run a Scheduler
type Options struct {
// The default values. These are overridden if ConfigFile is set or by values in InsecureServing.
ComponentConfig kubeschedulerconfig.KubeSchedulerConfiguration
SecureServing *apiserveroptions.SecureServingOptionsWithLoopback
CombinedInsecureServing *CombinedInsecureServingOptions
Authentication *apiserveroptions.DelegatingAuthenticationOptions
Authorization *apiserveroptions.DelegatingAuthorizationOptions
2020-08-10 17:43:49 +00:00
Metrics *metrics.Options
Logs *logs.Options
2019-01-12 04:58:27 +00:00
Deprecated *DeprecatedOptions
// ConfigFile is the location of the scheduler server's configuration file.
ConfigFile string
// WriteConfigTo is the path where the default configuration will be written.
WriteConfigTo string
Master string
}
// NewOptions returns default scheduler app options.
func NewOptions() (*Options, error) {
cfg, err := newDefaultComponentConfig()
if err != nil {
return nil, err
}
hhost, hport, err := splitHostIntPort(cfg.HealthzBindAddress)
if err != nil {
return nil, err
}
o := &Options{
ComponentConfig: *cfg,
SecureServing: apiserveroptions.NewSecureServingOptions().WithLoopback(),
CombinedInsecureServing: &CombinedInsecureServingOptions{
Healthz: (&apiserveroptions.DeprecatedInsecureServingOptions{
BindNetwork: "tcp",
}).WithLoopback(),
Metrics: (&apiserveroptions.DeprecatedInsecureServingOptions{
BindNetwork: "tcp",
}).WithLoopback(),
BindPort: hport,
BindAddress: hhost,
},
Authentication: apiserveroptions.NewDelegatingAuthenticationOptions(),
Authorization: apiserveroptions.NewDelegatingAuthorizationOptions(),
Deprecated: &DeprecatedOptions{
2020-03-26 21:07:15 +00:00
UseLegacyPolicyConfig: false,
PolicyConfigMapNamespace: metav1.NamespaceSystem,
SchedulerName: corev1.DefaultSchedulerName,
2020-08-10 17:43:49 +00:00
HardPodAffinitySymmetricWeight: 1,
2019-01-12 04:58:27 +00:00
},
2020-08-10 17:43:49 +00:00
Metrics: metrics.NewOptions(),
Logs: logs.NewOptions(),
2019-01-12 04:58:27 +00:00
}
o.Authentication.TolerateInClusterLookupFailure = true
o.Authentication.RemoteKubeConfigFileOptional = true
o.Authorization.RemoteKubeConfigFileOptional = true
// Set the PairName but leave certificate directory blank to generate in-memory by default
o.SecureServing.ServerCert.CertDirectory = ""
o.SecureServing.ServerCert.PairName = "kube-scheduler"
2020-08-10 17:43:49 +00:00
o.SecureServing.BindPort = kubeschedulerconfig.DefaultKubeSchedulerPort
2019-01-12 04:58:27 +00:00
return o, nil
}
func splitHostIntPort(s string) (string, int, error) {
host, port, err := net.SplitHostPort(s)
if err != nil {
return "", 0, err
}
portInt, err := strconv.Atoi(port)
if err != nil {
return "", 0, err
}
return host, portInt, err
}
func newDefaultComponentConfig() (*kubeschedulerconfig.KubeSchedulerConfiguration, error) {
2020-08-10 17:43:49 +00:00
versionedCfg := kubeschedulerconfigv1beta1.KubeSchedulerConfiguration{}
2020-03-26 21:07:15 +00:00
versionedCfg.DebuggingConfiguration = *configv1alpha1.NewRecommendedDebuggingConfiguration()
kubeschedulerscheme.Scheme.Default(&versionedCfg)
2019-01-12 04:58:27 +00:00
cfg := kubeschedulerconfig.KubeSchedulerConfiguration{}
2020-03-26 21:07:15 +00:00
if err := kubeschedulerscheme.Scheme.Convert(&versionedCfg, &cfg, nil); err != nil {
2019-01-12 04:58:27 +00:00
return nil, err
}
return &cfg, nil
}
// Flags returns flags for a specific scheduler by section name
2019-04-07 17:07:55 +00:00
func (o *Options) Flags() (nfs cliflag.NamedFlagSets) {
2019-01-12 04:58:27 +00:00
fs := nfs.FlagSet("misc")
2020-08-10 17:43:49 +00:00
fs.StringVar(&o.ConfigFile, "config", o.ConfigFile, `The path to the configuration file. The following flags can overwrite fields in this file:
--algorithm-provider
2020-08-10 17:43:49 +00:00
--policy-config-file
--policy-configmap
--policy-configmap-namespace`)
2019-01-12 04:58:27 +00:00
fs.StringVar(&o.WriteConfigTo, "write-config-to", o.WriteConfigTo, "If set, write the configuration values to this file and exit.")
fs.StringVar(&o.Master, "master", o.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig)")
o.SecureServing.AddFlags(nfs.FlagSet("secure serving"))
o.CombinedInsecureServing.AddFlags(nfs.FlagSet("insecure serving"))
o.Authentication.AddFlags(nfs.FlagSet("authentication"))
o.Authorization.AddFlags(nfs.FlagSet("authorization"))
o.Deprecated.AddFlags(nfs.FlagSet("deprecated"), &o.ComponentConfig)
2020-08-10 17:43:49 +00:00
options.BindLeaderElectionFlags(&o.ComponentConfig.LeaderElection, nfs.FlagSet("leader election"))
2019-04-07 17:07:55 +00:00
utilfeature.DefaultMutableFeatureGate.AddFlag(nfs.FlagSet("feature gate"))
2020-08-10 17:43:49 +00:00
o.Metrics.AddFlags(nfs.FlagSet("metrics"))
o.Logs.AddFlags(nfs.FlagSet("logs"))
2020-03-26 21:07:15 +00:00
2019-01-12 04:58:27 +00:00
return nfs
}
// ApplyTo applies the scheduler options to the given scheduler app configuration.
func (o *Options) ApplyTo(c *schedulerappconfig.Config) error {
if len(o.ConfigFile) == 0 {
c.ComponentConfig = o.ComponentConfig
2020-08-10 17:43:49 +00:00
// apply deprecated flags if no config file is loaded (this is the old behaviour).
o.Deprecated.ApplyTo(&c.ComponentConfig)
2019-01-12 04:58:27 +00:00
if err := o.CombinedInsecureServing.ApplyTo(c, &c.ComponentConfig); err != nil {
return err
}
} else {
cfg, err := loadConfigFromFile(o.ConfigFile)
if err != nil {
return err
}
2019-12-12 01:27:03 +00:00
if err := validation.ValidateKubeSchedulerConfiguration(cfg).ToAggregate(); err != nil {
return err
}
2019-01-12 04:58:27 +00:00
c.ComponentConfig = *cfg
2020-08-10 17:43:49 +00:00
// apply any deprecated Policy flags, if applicable
o.Deprecated.ApplyAlgorithmSourceTo(&c.ComponentConfig)
// if the user has set CC profiles and is trying to use a Policy config, error out
// these configs are no longer merged and they should not be used simultaneously
if !emptySchedulerProfileConfig(c.ComponentConfig.Profiles) && c.ComponentConfig.AlgorithmSource.Policy != nil {
return fmt.Errorf("cannot set a Plugin config and Policy config")
}
// use the loaded config file only, with the exception of --address and --port.
2019-01-12 04:58:27 +00:00
if err := o.CombinedInsecureServing.ApplyToFromLoadedConfig(c, &c.ComponentConfig); err != nil {
return err
}
}
if err := o.SecureServing.ApplyTo(&c.SecureServing, &c.LoopbackClientConfig); err != nil {
return err
}
if o.SecureServing != nil && (o.SecureServing.BindPort != 0 || o.SecureServing.Listener != nil) {
2019-08-30 18:33:25 +00:00
if err := o.Authentication.ApplyTo(&c.Authentication, c.SecureServing, nil); err != nil {
2019-01-12 04:58:27 +00:00
return err
}
if err := o.Authorization.ApplyTo(&c.Authorization); err != nil {
return err
}
}
2020-08-10 17:43:49 +00:00
o.Metrics.Apply()
o.Logs.Apply()
2019-01-12 04:58:27 +00:00
return nil
}
2020-08-10 17:43:49 +00:00
// emptySchedulerProfileConfig returns true if the list of profiles passed to it contains only
// the "default-scheduler" profile with no plugins or pluginconfigs registered
// (this is the default empty profile initialized by defaults.go)
func emptySchedulerProfileConfig(profiles []kubeschedulerconfig.KubeSchedulerProfile) bool {
return len(profiles) == 1 &&
len(profiles[0].PluginConfig) == 0 &&
profiles[0].Plugins == nil
}
2019-01-12 04:58:27 +00:00
// Validate validates all the required options.
func (o *Options) Validate() []error {
var errs []error
if err := validation.ValidateKubeSchedulerConfiguration(&o.ComponentConfig).ToAggregate(); err != nil {
errs = append(errs, err.Errors()...)
}
errs = append(errs, o.SecureServing.Validate()...)
errs = append(errs, o.CombinedInsecureServing.Validate()...)
errs = append(errs, o.Authentication.Validate()...)
errs = append(errs, o.Authorization.Validate()...)
errs = append(errs, o.Deprecated.Validate()...)
2020-08-10 17:43:49 +00:00
errs = append(errs, o.Metrics.Validate()...)
errs = append(errs, o.Logs.Validate()...)
2019-01-12 04:58:27 +00:00
return errs
}
// Config return a scheduler config object
func (o *Options) Config() (*schedulerappconfig.Config, error) {
if o.SecureServing != nil {
if err := o.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost", nil, []net.IP{net.ParseIP("127.0.0.1")}); err != nil {
return nil, fmt.Errorf("error creating self-signed certificates: %v", err)
}
}
c := &schedulerappconfig.Config{}
if err := o.ApplyTo(c); err != nil {
return nil, err
}
// Prepare kube config.
kubeConfig, err := createKubeConfig(c.ComponentConfig.ClientConnection, o.Master)
if err != nil {
return nil, err
}
2019-01-12 04:58:27 +00:00
// Prepare kube clients.
client, eventClient, err := createClients(kubeConfig)
2019-01-12 04:58:27 +00:00
if err != nil {
return nil, err
}
2020-08-10 17:43:49 +00:00
c.EventBroadcaster = events.NewEventBroadcasterAdapter(eventClient)
2019-01-12 04:58:27 +00:00
// Set up leader election if enabled.
var leaderElectionConfig *leaderelection.LeaderElectionConfig
if c.ComponentConfig.LeaderElection.LeaderElect {
2020-03-26 21:07:15 +00:00
// Use the scheduler name in the first profile to record leader election.
2020-08-10 17:43:49 +00:00
coreRecorder := c.EventBroadcaster.DeprecatedNewLegacyRecorder(c.ComponentConfig.Profiles[0].SchedulerName)
leaderElectionConfig, err = makeLeaderElectionConfig(c.ComponentConfig.LeaderElection, kubeConfig, coreRecorder)
2019-01-12 04:58:27 +00:00
if err != nil {
return nil, err
}
}
c.Client = client
c.InformerFactory = scheduler.NewInformerFactory(client, 0)
2019-01-12 04:58:27 +00:00
c.LeaderElection = leaderElectionConfig
return c, nil
}
// makeLeaderElectionConfig builds a leader election configuration. It will
// create a new resource lock associated with the configuration.
func makeLeaderElectionConfig(config componentbaseconfig.LeaderElectionConfiguration, kubeConfig *restclient.Config, recorder record.EventRecorder) (*leaderelection.LeaderElectionConfig, error) {
2019-01-12 04:58:27 +00:00
hostname, err := os.Hostname()
if err != nil {
return nil, fmt.Errorf("unable to get hostname: %v", err)
}
// add a uniquifier so that two processes on the same host don't accidentally both become active
id := hostname + "_" + string(uuid.NewUUID())
rl, err := resourcelock.NewFromKubeconfig(config.ResourceLock,
2019-09-27 21:51:53 +00:00
config.ResourceNamespace,
config.ResourceName,
2019-01-12 04:58:27 +00:00
resourcelock.ResourceLockConfig{
Identity: id,
EventRecorder: recorder,
},
kubeConfig,
config.RenewDeadline.Duration)
2019-01-12 04:58:27 +00:00
if err != nil {
return nil, fmt.Errorf("couldn't create resource lock: %v", err)
}
return &leaderelection.LeaderElectionConfig{
Lock: rl,
LeaseDuration: config.LeaseDuration.Duration,
RenewDeadline: config.RenewDeadline.Duration,
RetryPeriod: config.RetryPeriod.Duration,
WatchDog: leaderelection.NewLeaderHealthzAdaptor(time.Second * 20),
Name: "kube-scheduler",
}, nil
}
// createKubeConfig creates a kubeConfig from the given config and masterOverride.
2019-01-12 04:58:27 +00:00
// TODO remove masterOverride when CLI flags are removed.
func createKubeConfig(config componentbaseconfig.ClientConnectionConfiguration, masterOverride string) (*restclient.Config, error) {
2019-01-12 04:58:27 +00:00
if len(config.Kubeconfig) == 0 && len(masterOverride) == 0 {
klog.Warning("Neither --kubeconfig nor --master was specified. Using default API client. This might not work.")
2019-01-12 04:58:27 +00:00
}
// This creates a client, first loading any specified kubeconfig
// file, and then overriding the Master flag, if non-empty.
kubeConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{ExplicitPath: config.Kubeconfig},
&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: masterOverride}}).ClientConfig()
if err != nil {
return nil, err
2019-01-12 04:58:27 +00:00
}
2019-09-27 21:51:53 +00:00
kubeConfig.DisableCompression = true
2019-01-12 04:58:27 +00:00
kubeConfig.AcceptContentTypes = config.AcceptContentTypes
kubeConfig.ContentType = config.ContentType
kubeConfig.QPS = config.QPS
kubeConfig.Burst = int(config.Burst)
return kubeConfig, nil
}
2019-01-12 04:58:27 +00:00
// createClients creates a kube client and an event client from the given kubeConfig
func createClients(kubeConfig *restclient.Config) (clientset.Interface, clientset.Interface, error) {
client, err := clientset.NewForConfig(restclient.AddUserAgent(kubeConfig, "scheduler"))
2019-01-12 04:58:27 +00:00
if err != nil {
return nil, nil, err
2019-01-12 04:58:27 +00:00
}
eventClient, err := clientset.NewForConfig(kubeConfig)
if err != nil {
return nil, nil, err
2019-01-12 04:58:27 +00:00
}
return client, eventClient, nil
2019-01-12 04:58:27 +00:00
}