Skip to content

Commit 04a921c

Browse files
chore: Allow setting leader election namespace when running out of cluster (#1704)
1 parent e410762 commit 04a921c

File tree

4 files changed

+92
-81
lines changed

4 files changed

+92
-81
lines changed

pkg/operator/operator.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ func NewOperator() (context.Context, *Operator) {
127127
Logger: logging.IgnoreDebugEvents(logger),
128128
LeaderElection: !options.FromContext(ctx).DisableLeaderElection,
129129
LeaderElectionID: "karpenter-leader-election",
130+
LeaderElectionNamespace: options.FromContext(ctx).LeaderElectionNamespace,
130131
LeaderElectionResourceLock: resourcelock.LeasesResourceLock,
131132
LeaderElectionReleaseOnCancel: true,
132133
Metrics: server.Options{

pkg/operator/options/options.go

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,21 @@ type FeatureGates struct {
4646

4747
// Options contains all CLI flags / env vars for karpenter-core. It adheres to the options.Injectable interface.
4848
type Options struct {
49-
ServiceName string
50-
MetricsPort int
51-
HealthProbePort int
52-
KubeClientQPS int
53-
KubeClientBurst int
54-
EnableProfiling bool
55-
DisableLeaderElection bool
56-
MemoryLimit int64
57-
LogLevel string
58-
LogOutputPaths string
59-
LogErrorOutputPaths string
60-
BatchMaxDuration time.Duration
61-
BatchIdleDuration time.Duration
62-
FeatureGates FeatureGates
49+
ServiceName string
50+
MetricsPort int
51+
HealthProbePort int
52+
KubeClientQPS int
53+
KubeClientBurst int
54+
EnableProfiling bool
55+
DisableLeaderElection bool
56+
LeaderElectionNamespace string
57+
MemoryLimit int64
58+
LogLevel string
59+
LogOutputPaths string
60+
LogErrorOutputPaths string
61+
BatchMaxDuration time.Duration
62+
BatchIdleDuration time.Duration
63+
FeatureGates FeatureGates
6364
}
6465

6566
type FlagSet struct {
@@ -87,6 +88,7 @@ func (o *Options) AddFlags(fs *FlagSet) {
8788
fs.IntVar(&o.KubeClientBurst, "kube-client-burst", env.WithDefaultInt("KUBE_CLIENT_BURST", 300), "The maximum allowed burst of queries to the kube-apiserver")
8889
fs.BoolVarWithEnv(&o.EnableProfiling, "enable-profiling", "ENABLE_PROFILING", false, "Enable the profiling on the metric endpoint")
8990
fs.BoolVarWithEnv(&o.DisableLeaderElection, "disable-leader-election", "DISABLE_LEADER_ELECTION", false, "Disable the leader election client before executing the main loop. Disable when running replicated components for high availability is not desired.")
91+
fs.StringVar(&o.LeaderElectionNamespace, "leader-election-namespace", env.WithDefaultString("LEADER_ELECTION_NAMESPACE", ""), "Leader election namespace to create and monitor the lease if running outside the cluster")
9092
fs.Int64Var(&o.MemoryLimit, "memory-limit", env.WithDefaultInt64("MEMORY_LIMIT", -1), "Memory limit on the container running the controller. The GC soft memory limit is set to 90% of this value.")
9193
fs.StringVar(&o.LogLevel, "log-level", env.WithDefaultString("LOG_LEVEL", "info"), "Log verbosity level. Can be one of 'debug', 'info', or 'error'")
9294
fs.StringVar(&o.LogOutputPaths, "log-output-paths", env.WithDefaultString("LOG_OUTPUT_PATHS", "stdout"), "Optional comma separated paths for directing log output")
@@ -105,7 +107,7 @@ func (o *Options) Parse(fs *FlagSet, args ...string) error {
105107
}
106108

107109
if !lo.Contains(validLogLevels, o.LogLevel) {
108-
return fmt.Errorf("validating cli flags / env vars, invalid log level %q", o.LogLevel)
110+
return fmt.Errorf("validating cli flags / env vars, invalid LOG_LEVEL %q", o.LogLevel)
109111
}
110112
gates, err := ParseFeatureGates(o.FeatureGates.inputStr)
111113
if err != nil {

pkg/operator/options/suite_test.go

Lines changed: 59 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ var _ = Describe("Options", func() {
5151
"KUBE_CLIENT_BURST",
5252
"ENABLE_PROFILING",
5353
"DISABLE_LEADER_ELECTION",
54+
"LEADER_ELECTION_NAMESPACE",
5455
"MEMORY_LIMIT",
5556
"LOG_LEVEL",
5657
"LOG_OUTPUT_PATHS",
@@ -94,19 +95,20 @@ var _ = Describe("Options", func() {
9495
err := opts.Parse(fs)
9596
Expect(err).To(BeNil())
9697
expectOptionsMatch(opts, test.Options(test.OptionsFields{
97-
ServiceName: lo.ToPtr(""),
98-
MetricsPort: lo.ToPtr(8080),
99-
HealthProbePort: lo.ToPtr(8081),
100-
KubeClientQPS: lo.ToPtr(200),
101-
KubeClientBurst: lo.ToPtr(300),
102-
EnableProfiling: lo.ToPtr(false),
103-
DisableLeaderElection: lo.ToPtr(false),
104-
MemoryLimit: lo.ToPtr[int64](-1),
105-
LogLevel: lo.ToPtr("info"),
106-
LogOutputPaths: lo.ToPtr("stdout"),
107-
LogErrorOutputPaths: lo.ToPtr("stderr"),
108-
BatchMaxDuration: lo.ToPtr(10 * time.Second),
109-
BatchIdleDuration: lo.ToPtr(time.Second),
98+
ServiceName: lo.ToPtr(""),
99+
MetricsPort: lo.ToPtr(8080),
100+
HealthProbePort: lo.ToPtr(8081),
101+
KubeClientQPS: lo.ToPtr(200),
102+
KubeClientBurst: lo.ToPtr(300),
103+
EnableProfiling: lo.ToPtr(false),
104+
DisableLeaderElection: lo.ToPtr(false),
105+
LeaderElectionNamespace: lo.ToPtr(""),
106+
MemoryLimit: lo.ToPtr[int64](-1),
107+
LogLevel: lo.ToPtr("info"),
108+
LogOutputPaths: lo.ToPtr("stdout"),
109+
LogErrorOutputPaths: lo.ToPtr("stderr"),
110+
BatchMaxDuration: lo.ToPtr(10 * time.Second),
111+
BatchIdleDuration: lo.ToPtr(time.Second),
110112
FeatureGates: test.FeatureGates{
111113
SpotToSpotConsolidation: lo.ToPtr(false),
112114
},
@@ -125,6 +127,7 @@ var _ = Describe("Options", func() {
125127
"--kube-client-burst", "0",
126128
"--enable-profiling",
127129
"--disable-leader-election=true",
130+
"--leader-election-namespace=karpenter",
128131
"--memory-limit", "0",
129132
"--log-level", "debug",
130133
"--log-output-paths", "/etc/k8s/test",
@@ -135,19 +138,20 @@ var _ = Describe("Options", func() {
135138
)
136139
Expect(err).To(BeNil())
137140
expectOptionsMatch(opts, test.Options(test.OptionsFields{
138-
ServiceName: lo.ToPtr("cli"),
139-
MetricsPort: lo.ToPtr(0),
140-
HealthProbePort: lo.ToPtr(0),
141-
KubeClientQPS: lo.ToPtr(0),
142-
KubeClientBurst: lo.ToPtr(0),
143-
EnableProfiling: lo.ToPtr(true),
144-
DisableLeaderElection: lo.ToPtr(true),
145-
MemoryLimit: lo.ToPtr[int64](0),
146-
LogLevel: lo.ToPtr("debug"),
147-
LogOutputPaths: lo.ToPtr("/etc/k8s/test"),
148-
LogErrorOutputPaths: lo.ToPtr("/etc/k8s/testerror"),
149-
BatchMaxDuration: lo.ToPtr(5 * time.Second),
150-
BatchIdleDuration: lo.ToPtr(5 * time.Second),
141+
ServiceName: lo.ToPtr("cli"),
142+
MetricsPort: lo.ToPtr(0),
143+
HealthProbePort: lo.ToPtr(0),
144+
KubeClientQPS: lo.ToPtr(0),
145+
KubeClientBurst: lo.ToPtr(0),
146+
EnableProfiling: lo.ToPtr(true),
147+
DisableLeaderElection: lo.ToPtr(true),
148+
LeaderElectionNamespace: lo.ToPtr("karpenter"),
149+
MemoryLimit: lo.ToPtr[int64](0),
150+
LogLevel: lo.ToPtr("debug"),
151+
LogOutputPaths: lo.ToPtr("/etc/k8s/test"),
152+
LogErrorOutputPaths: lo.ToPtr("/etc/k8s/testerror"),
153+
BatchMaxDuration: lo.ToPtr(5 * time.Second),
154+
BatchIdleDuration: lo.ToPtr(5 * time.Second),
151155
FeatureGates: test.FeatureGates{
152156
SpotToSpotConsolidation: lo.ToPtr(true),
153157
},
@@ -162,6 +166,7 @@ var _ = Describe("Options", func() {
162166
os.Setenv("KUBE_CLIENT_BURST", "0")
163167
os.Setenv("ENABLE_PROFILING", "true")
164168
os.Setenv("DISABLE_LEADER_ELECTION", "true")
169+
os.Setenv("LEADER_ELECTION_NAMESPACE", "karpenter")
165170
os.Setenv("MEMORY_LIMIT", "0")
166171
os.Setenv("LOG_LEVEL", "debug")
167172
os.Setenv("LOG_OUTPUT_PATHS", "/etc/k8s/test")
@@ -176,19 +181,20 @@ var _ = Describe("Options", func() {
176181
err := opts.Parse(fs)
177182
Expect(err).To(BeNil())
178183
expectOptionsMatch(opts, test.Options(test.OptionsFields{
179-
ServiceName: lo.ToPtr("env"),
180-
MetricsPort: lo.ToPtr(0),
181-
HealthProbePort: lo.ToPtr(0),
182-
KubeClientQPS: lo.ToPtr(0),
183-
KubeClientBurst: lo.ToPtr(0),
184-
EnableProfiling: lo.ToPtr(true),
185-
DisableLeaderElection: lo.ToPtr(true),
186-
MemoryLimit: lo.ToPtr[int64](0),
187-
LogLevel: lo.ToPtr("debug"),
188-
LogOutputPaths: lo.ToPtr("/etc/k8s/test"),
189-
LogErrorOutputPaths: lo.ToPtr("/etc/k8s/testerror"),
190-
BatchMaxDuration: lo.ToPtr(5 * time.Second),
191-
BatchIdleDuration: lo.ToPtr(5 * time.Second),
184+
ServiceName: lo.ToPtr("env"),
185+
MetricsPort: lo.ToPtr(0),
186+
HealthProbePort: lo.ToPtr(0),
187+
KubeClientQPS: lo.ToPtr(0),
188+
KubeClientBurst: lo.ToPtr(0),
189+
EnableProfiling: lo.ToPtr(true),
190+
DisableLeaderElection: lo.ToPtr(true),
191+
LeaderElectionNamespace: lo.ToPtr("karpenter"),
192+
MemoryLimit: lo.ToPtr[int64](0),
193+
LogLevel: lo.ToPtr("debug"),
194+
LogOutputPaths: lo.ToPtr("/etc/k8s/test"),
195+
LogErrorOutputPaths: lo.ToPtr("/etc/k8s/testerror"),
196+
BatchMaxDuration: lo.ToPtr(5 * time.Second),
197+
BatchIdleDuration: lo.ToPtr(5 * time.Second),
192198
FeatureGates: test.FeatureGates{
193199
SpotToSpotConsolidation: lo.ToPtr(true),
194200
},
@@ -219,19 +225,20 @@ var _ = Describe("Options", func() {
219225
)
220226
Expect(err).To(BeNil())
221227
expectOptionsMatch(opts, test.Options(test.OptionsFields{
222-
ServiceName: lo.ToPtr("cli"),
223-
MetricsPort: lo.ToPtr(0),
224-
HealthProbePort: lo.ToPtr(0),
225-
KubeClientQPS: lo.ToPtr(0),
226-
KubeClientBurst: lo.ToPtr(0),
227-
EnableProfiling: lo.ToPtr(true),
228-
DisableLeaderElection: lo.ToPtr(true),
229-
MemoryLimit: lo.ToPtr[int64](0),
230-
LogLevel: lo.ToPtr("debug"),
231-
LogOutputPaths: lo.ToPtr("/etc/k8s/test"),
232-
LogErrorOutputPaths: lo.ToPtr("/etc/k8s/testerror"),
233-
BatchMaxDuration: lo.ToPtr(5 * time.Second),
234-
BatchIdleDuration: lo.ToPtr(5 * time.Second),
228+
ServiceName: lo.ToPtr("cli"),
229+
MetricsPort: lo.ToPtr(0),
230+
HealthProbePort: lo.ToPtr(0),
231+
KubeClientQPS: lo.ToPtr(0),
232+
KubeClientBurst: lo.ToPtr(0),
233+
EnableProfiling: lo.ToPtr(true),
234+
DisableLeaderElection: lo.ToPtr(true),
235+
LeaderElectionNamespace: lo.ToPtr(""),
236+
MemoryLimit: lo.ToPtr[int64](0),
237+
LogLevel: lo.ToPtr("debug"),
238+
LogOutputPaths: lo.ToPtr("/etc/k8s/test"),
239+
LogErrorOutputPaths: lo.ToPtr("/etc/k8s/testerror"),
240+
BatchMaxDuration: lo.ToPtr(5 * time.Second),
241+
BatchIdleDuration: lo.ToPtr(5 * time.Second),
235242
FeatureGates: test.FeatureGates{
236243
SpotToSpotConsolidation: lo.ToPtr(true),
237244
},

pkg/test/options.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,21 @@ import (
2828

2929
type OptionsFields struct {
3030
// Vendor Neutral
31-
ServiceName *string
32-
MetricsPort *int
33-
HealthProbePort *int
34-
KubeClientQPS *int
35-
KubeClientBurst *int
36-
EnableProfiling *bool
37-
DisableLeaderElection *bool
38-
MemoryLimit *int64
39-
LogLevel *string
40-
LogOutputPaths *string
41-
LogErrorOutputPaths *string
42-
BatchMaxDuration *time.Duration
43-
BatchIdleDuration *time.Duration
44-
FeatureGates FeatureGates
31+
ServiceName *string
32+
MetricsPort *int
33+
HealthProbePort *int
34+
KubeClientQPS *int
35+
KubeClientBurst *int
36+
EnableProfiling *bool
37+
DisableLeaderElection *bool
38+
LeaderElectionNamespace *string
39+
MemoryLimit *int64
40+
LogLevel *string
41+
LogOutputPaths *string
42+
LogErrorOutputPaths *string
43+
BatchMaxDuration *time.Duration
44+
BatchIdleDuration *time.Duration
45+
FeatureGates FeatureGates
4546
}
4647

4748
type FeatureGates struct {

0 commit comments

Comments
 (0)