Merge pull request #576 from Garrybest/enhance-lease
Leader election: clean up and add leader election to agent
This commit is contained in:
commit
2cefb24ecf
|
@ -67,10 +67,12 @@ func run(ctx context.Context, karmadaConfig karmadactl.KarmadaConfig, opts *opti
|
||||||
}
|
}
|
||||||
|
|
||||||
controllerManager, err := controllerruntime.NewManager(controlPlaneRestConfig, controllerruntime.Options{
|
controllerManager, err := controllerruntime.NewManager(controlPlaneRestConfig, controllerruntime.Options{
|
||||||
Scheme: gclient.NewSchema(),
|
Scheme: gclient.NewSchema(),
|
||||||
Namespace: executionSpace,
|
Namespace: executionSpace,
|
||||||
LeaderElection: false,
|
LeaderElection: opts.LeaderElection.LeaderElect,
|
||||||
LeaderElectionID: "agent.karmada.io",
|
LeaderElectionID: fmt.Sprintf("karmada-agent-%s", opts.ClusterName),
|
||||||
|
LeaderElectionNamespace: opts.LeaderElection.ResourceNamespace,
|
||||||
|
LeaderElectionResourceLock: opts.LeaderElection.ResourceLock,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("failed to build controller manager: %v", err)
|
klog.Errorf("failed to build controller manager: %v", err)
|
||||||
|
|
|
@ -5,10 +5,15 @@ import (
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
||||||
|
componentbaseconfig "k8s.io/component-base/config"
|
||||||
|
|
||||||
|
"github.com/karmada-io/karmada/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Options contains everything necessary to create and run controller-manager.
|
// Options contains everything necessary to create and run controller-manager.
|
||||||
type Options struct {
|
type Options struct {
|
||||||
|
LeaderElection componentbaseconfig.LeaderElectionConfiguration
|
||||||
KarmadaKubeConfig string
|
KarmadaKubeConfig string
|
||||||
// ClusterContext is the name of the cluster context in control plane KUBECONFIG file.
|
// ClusterContext is the name of the cluster context in control plane KUBECONFIG file.
|
||||||
// Default value is the current-context.
|
// Default value is the current-context.
|
||||||
|
@ -28,7 +33,13 @@ type Options struct {
|
||||||
|
|
||||||
// NewOptions builds an default scheduler options.
|
// NewOptions builds an default scheduler options.
|
||||||
func NewOptions() *Options {
|
func NewOptions() *Options {
|
||||||
return &Options{}
|
return &Options{
|
||||||
|
LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
|
||||||
|
LeaderElect: true,
|
||||||
|
ResourceLock: resourcelock.LeasesResourceLock,
|
||||||
|
ResourceNamespace: util.NamespaceKarmadaSystem,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddFlags adds flags of scheduler to the specified FlagSet
|
// AddFlags adds flags of scheduler to the specified FlagSet
|
||||||
|
@ -37,6 +48,7 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fs.BoolVar(&o.LeaderElection.LeaderElect, "leader-elect", true, "Start a leader election client and gain leadership before executing the main loop. Enable this when running replicated components for high availability.")
|
||||||
fs.StringVar(&o.KarmadaKubeConfig, "karmada-kubeconfig", o.KarmadaKubeConfig, "Path to karmada control plane kubeconfig file.")
|
fs.StringVar(&o.KarmadaKubeConfig, "karmada-kubeconfig", o.KarmadaKubeConfig, "Path to karmada control plane kubeconfig file.")
|
||||||
fs.StringVar(&o.KarmadaContext, "karmada-context", "", "Name of the cluster context in karmada control plane kubeconfig file.")
|
fs.StringVar(&o.KarmadaContext, "karmada-context", "", "Name of the cluster context in karmada control plane kubeconfig file.")
|
||||||
fs.StringVar(&o.ClusterName, "cluster-name", o.ClusterName, "Name of member cluster that the agent serves for.")
|
fs.StringVar(&o.ClusterName, "cluster-name", o.ClusterName, "Name of member cluster that the agent serves for.")
|
||||||
|
|
|
@ -44,7 +44,6 @@ func NewControllerManagerCommand(ctx context.Context) *cobra.Command {
|
||||||
Use: "controller-manager",
|
Use: "controller-manager",
|
||||||
Long: `The controller manager runs a bunch of controllers`,
|
Long: `The controller manager runs a bunch of controllers`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
opts.Complete()
|
|
||||||
if err := Run(ctx, opts); err != nil {
|
if err := Run(ctx, opts); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -64,11 +63,13 @@ func Run(ctx context.Context, opts *options.Options) error {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
controllerManager, err := controllerruntime.NewManager(config, controllerruntime.Options{
|
controllerManager, err := controllerruntime.NewManager(config, controllerruntime.Options{
|
||||||
Scheme: gclient.NewSchema(),
|
Scheme: gclient.NewSchema(),
|
||||||
LeaderElection: opts.LeaderElection.LeaderElect,
|
LeaderElection: opts.LeaderElection.LeaderElect,
|
||||||
LeaderElectionID: "karmada-controller-manager",
|
LeaderElectionID: opts.LeaderElection.ResourceName,
|
||||||
HealthProbeBindAddress: fmt.Sprintf("%s:%d", opts.BindAddress, opts.SecurePort),
|
LeaderElectionNamespace: opts.LeaderElection.ResourceNamespace,
|
||||||
LivenessEndpointName: "/healthz",
|
LeaderElectionResourceLock: opts.LeaderElection.ResourceLock,
|
||||||
|
HealthProbeBindAddress: fmt.Sprintf("%s:%d", opts.BindAddress, opts.SecurePort),
|
||||||
|
LivenessEndpointName: "/healthz",
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("failed to build controller manager: %v", err)
|
klog.Errorf("failed to build controller manager: %v", err)
|
||||||
|
|
|
@ -7,13 +7,8 @@ import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
||||||
componentbaseconfig "k8s.io/component-base/config"
|
componentbaseconfig "k8s.io/component-base/config"
|
||||||
"k8s.io/klog/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
"github.com/karmada-io/karmada/pkg/util"
|
||||||
defaultElectionLeaseDuration = metav1.Duration{Duration: 15 * time.Second}
|
|
||||||
defaultElectionRenewDeadline = metav1.Duration{Duration: 10 * time.Second}
|
|
||||||
defaultElectionRetryPeriod = metav1.Duration{Duration: 2 * time.Second}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -23,7 +18,6 @@ const (
|
||||||
|
|
||||||
// Options contains everything necessary to create and run controller-manager.
|
// Options contains everything necessary to create and run controller-manager.
|
||||||
type Options struct {
|
type Options struct {
|
||||||
HostNamespace string
|
|
||||||
LeaderElection componentbaseconfig.LeaderElectionConfiguration
|
LeaderElection componentbaseconfig.LeaderElectionConfiguration
|
||||||
// BindAddress is the IP address on which to listen for the --secure-port port.
|
// BindAddress is the IP address on which to listen for the --secure-port port.
|
||||||
BindAddress string
|
BindAddress string
|
||||||
|
@ -57,34 +51,13 @@ type Options struct {
|
||||||
|
|
||||||
// NewOptions builds an empty options.
|
// NewOptions builds an empty options.
|
||||||
func NewOptions() *Options {
|
func NewOptions() *Options {
|
||||||
return &Options{}
|
return &Options{
|
||||||
}
|
LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
|
||||||
|
LeaderElect: true,
|
||||||
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver.
|
ResourceLock: resourcelock.LeasesResourceLock,
|
||||||
func (o *Options) Complete() {
|
ResourceNamespace: util.NamespaceKarmadaSystem,
|
||||||
if len(o.HostNamespace) == 0 {
|
ResourceName: "karmada-controller-manager",
|
||||||
o.HostNamespace = "default"
|
},
|
||||||
klog.Infof("Set default value: Options.HostNamespace = %s", "default")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(o.LeaderElection.ResourceLock) == 0 {
|
|
||||||
o.LeaderElection.ResourceLock = resourcelock.EndpointsLeasesResourceLock
|
|
||||||
klog.Infof("Set default value: Options.LeaderElection.ResourceLock = %s", resourcelock.EndpointsLeasesResourceLock)
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.LeaderElection.LeaseDuration.Duration.Seconds() == 0 {
|
|
||||||
o.LeaderElection.LeaseDuration = defaultElectionLeaseDuration
|
|
||||||
klog.Infof("Set default value: Options.LeaderElection.LeaseDuration = %s", defaultElectionLeaseDuration.Duration.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.LeaderElection.RenewDeadline.Duration.Seconds() == 0 {
|
|
||||||
o.LeaderElection.RenewDeadline = defaultElectionRenewDeadline
|
|
||||||
klog.Infof("Set default value: Options.LeaderElection.RenewDeadline = %s", defaultElectionRenewDeadline.Duration.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.LeaderElection.RetryPeriod.Duration.Seconds() == 0 {
|
|
||||||
o.LeaderElection.RetryPeriod = defaultElectionRetryPeriod
|
|
||||||
klog.Infof("Set default value: Options.LeaderElection.RetryPeriod = %s", defaultElectionRetryPeriod.Duration.String())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
||||||
componentbaseconfig "k8s.io/component-base/config"
|
componentbaseconfig "k8s.io/component-base/config"
|
||||||
|
|
||||||
|
"github.com/karmada-io/karmada/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -38,11 +40,13 @@ type Options struct {
|
||||||
func NewOptions() *Options {
|
func NewOptions() *Options {
|
||||||
return &Options{
|
return &Options{
|
||||||
LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
|
LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
|
||||||
LeaderElect: false,
|
LeaderElect: true,
|
||||||
ResourceLock: resourcelock.LeasesResourceLock,
|
ResourceLock: resourcelock.LeasesResourceLock,
|
||||||
LeaseDuration: defaultElectionLeaseDuration,
|
ResourceNamespace: util.NamespaceKarmadaSystem,
|
||||||
RenewDeadline: defaultElectionRenewDeadline,
|
ResourceName: "karmada-scheduler",
|
||||||
RetryPeriod: defaultElectionRetryPeriod,
|
LeaseDuration: defaultElectionLeaseDuration,
|
||||||
|
RenewDeadline: defaultElectionRenewDeadline,
|
||||||
|
RetryPeriod: defaultElectionRetryPeriod,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,8 +57,7 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.BoolVar(&o.LeaderElection.LeaderElect, "leader-elect", false, "Enable leader election, which must be true when running multi instances.")
|
fs.BoolVar(&o.LeaderElection.LeaderElect, "leader-elect", true, "Enable leader election, which must be true when running multi instances.")
|
||||||
fs.StringVar(&o.LeaderElection.ResourceNamespace, "lock-namespace", "", "Define the namespace of the lock object.")
|
|
||||||
fs.StringVar(&o.KubeConfig, "kubeconfig", o.KubeConfig, "Path to a KubeConfig. Only required if out-of-cluster.")
|
fs.StringVar(&o.KubeConfig, "kubeconfig", o.KubeConfig, "Path to a KubeConfig. Only required if out-of-cluster.")
|
||||||
fs.StringVar(&o.Master, "master", o.Master, "The address of the Kubernetes API server. Overrides any value in KubeConfig. Only required if out-of-cluster.")
|
fs.StringVar(&o.Master, "master", o.Master, "The address of the Kubernetes API server. Overrides any value in KubeConfig. Only required if out-of-cluster.")
|
||||||
fs.StringVar(&o.BindAddress, "bind-address", defaultBindAddress, "The IP address on which to listen for the --secure-port port.")
|
fs.StringVar(&o.BindAddress, "bind-address", defaultBindAddress, "The IP address on which to listen for the --secure-port port.")
|
||||||
|
|
|
@ -80,7 +80,7 @@ func run(opts *options.Options, stopChan <-chan struct{}) error {
|
||||||
|
|
||||||
rl, err := resourcelock.New(opts.LeaderElection.ResourceLock,
|
rl, err := resourcelock.New(opts.LeaderElection.ResourceLock,
|
||||||
opts.LeaderElection.ResourceNamespace,
|
opts.LeaderElection.ResourceNamespace,
|
||||||
"karmada-scheduler",
|
opts.LeaderElection.ResourceName,
|
||||||
leaderElectionClient.CoreV1(),
|
leaderElectionClient.CoreV1(),
|
||||||
leaderElectionClient.CoordinationV1(),
|
leaderElectionClient.CoordinationV1(),
|
||||||
resourcelock.ResourceLockConfig{
|
resourcelock.ResourceLockConfig{
|
||||||
|
|
|
@ -1,19 +1,7 @@
|
||||||
package options
|
package options
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
|
||||||
componentbaseconfig "k8s.io/component-base/config"
|
|
||||||
"k8s.io/klog/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
defaultElectionLeaseDuration = metav1.Duration{Duration: 15 * time.Second}
|
|
||||||
defaultElectionRenewDeadline = metav1.Duration{Duration: 10 * time.Second}
|
|
||||||
defaultElectionRetryPeriod = metav1.Duration{Duration: 2 * time.Second}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -33,8 +21,7 @@ type Options struct {
|
||||||
// CertDir is the directory that contains the server key and certificate.
|
// CertDir is the directory that contains the server key and certificate.
|
||||||
// if not set, webhook server would look up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs.
|
// if not set, webhook server would look up the server key and certificate in {TempDir}/k8s-webhook-server/serving-certs.
|
||||||
// The server key and certificate must be named `tls.key` and `tls.crt`, respectively.
|
// The server key and certificate must be named `tls.key` and `tls.crt`, respectively.
|
||||||
CertDir string
|
CertDir string
|
||||||
LeaderElection componentbaseconfig.LeaderElectionConfiguration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOptions builds an empty options.
|
// NewOptions builds an empty options.
|
||||||
|
@ -42,29 +29,6 @@ func NewOptions() *Options {
|
||||||
return &Options{}
|
return &Options{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver.
|
|
||||||
func (o *Options) Complete() {
|
|
||||||
if len(o.LeaderElection.ResourceLock) == 0 {
|
|
||||||
o.LeaderElection.ResourceLock = resourcelock.EndpointsLeasesResourceLock
|
|
||||||
klog.Infof("Set default value: Options.LeaderElection.ResourceLock = %s", resourcelock.EndpointsLeasesResourceLock)
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.LeaderElection.LeaseDuration.Duration.Seconds() == 0 {
|
|
||||||
o.LeaderElection.LeaseDuration = defaultElectionLeaseDuration
|
|
||||||
klog.Infof("Set default value: Options.LeaderElection.LeaseDuration = %s", defaultElectionLeaseDuration.Duration.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.LeaderElection.RenewDeadline.Duration.Seconds() == 0 {
|
|
||||||
o.LeaderElection.RenewDeadline = defaultElectionRenewDeadline
|
|
||||||
klog.Infof("Set default value: Options.LeaderElection.RenewDeadline = %s", defaultElectionRenewDeadline.Duration.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.LeaderElection.RetryPeriod.Duration.Seconds() == 0 {
|
|
||||||
o.LeaderElection.RetryPeriod = defaultElectionRetryPeriod
|
|
||||||
klog.Infof("Set default value: Options.LeaderElection.RetryPeriod = %s", defaultElectionRetryPeriod.Duration.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddFlags adds flags to the specified FlagSet.
|
// AddFlags adds flags to the specified FlagSet.
|
||||||
func (o *Options) AddFlags(flags *pflag.FlagSet) {
|
func (o *Options) AddFlags(flags *pflag.FlagSet) {
|
||||||
flags.StringVar(&o.BindAddress, "bind-address", defaultBindAddress,
|
flags.StringVar(&o.BindAddress, "bind-address", defaultBindAddress,
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"k8s.io/component-base/logs"
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
controllerruntime "sigs.k8s.io/controller-runtime"
|
controllerruntime "sigs.k8s.io/controller-runtime"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||||
|
@ -31,7 +30,6 @@ func NewWebhookCommand(ctx context.Context) *cobra.Command {
|
||||||
Use: "webhook",
|
Use: "webhook",
|
||||||
Long: `Start a webhook server`,
|
Long: `Start a webhook server`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
opts.Complete()
|
|
||||||
if err := Run(ctx, opts); err != nil {
|
if err := Run(ctx, opts); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -47,20 +45,16 @@ func NewWebhookCommand(ctx context.Context) *cobra.Command {
|
||||||
|
|
||||||
// Run runs the webhook server with options. This should never exit.
|
// Run runs the webhook server with options. This should never exit.
|
||||||
func Run(ctx context.Context, opts *options.Options) error {
|
func Run(ctx context.Context, opts *options.Options) error {
|
||||||
logs.InitLogs()
|
|
||||||
defer logs.FlushLogs()
|
|
||||||
|
|
||||||
config, err := controllerruntime.GetConfig()
|
config, err := controllerruntime.GetConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
hookManager, err := controllerruntime.NewManager(config, controllerruntime.Options{
|
hookManager, err := controllerruntime.NewManager(config, controllerruntime.Options{
|
||||||
Scheme: gclient.NewSchema(),
|
Scheme: gclient.NewSchema(),
|
||||||
Host: opts.BindAddress,
|
Host: opts.BindAddress,
|
||||||
Port: opts.SecurePort,
|
Port: opts.SecurePort,
|
||||||
CertDir: opts.CertDir,
|
CertDir: opts.CertDir,
|
||||||
LeaderElection: false,
|
LeaderElection: false,
|
||||||
LeaderElectionID: "webhook.karmada.io",
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("failed to build webhook server: %v", err)
|
klog.Errorf("failed to build webhook server: %v", err)
|
||||||
|
|
|
@ -96,3 +96,8 @@ const (
|
||||||
// PropagationInstructionSuppressed indicates that the resource should not be propagated.
|
// PropagationInstructionSuppressed indicates that the resource should not be propagated.
|
||||||
PropagationInstructionSuppressed = "suppressed"
|
PropagationInstructionSuppressed = "suppressed"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// NamespaceKarmadaSystem is the karmada system namespace.
|
||||||
|
NamespaceKarmadaSystem = "karmada-system"
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue