Skip to content

Commit 7967663

Browse files
authored
ha: add support for specifying the lock namespace (#832)
When HA mode is enabled, the leader lock must be managed in a specific namespace, but when setting the `nomad.namespace` configuration to the wildcard `*` value the Nomad API client was trying to write to this namespace value, which is not allowed. This commit adds a new `high_availability.lock_namespace` configuration to allow operators to specify the exact lock variable namespace.
1 parent dab18db commit 7967663

File tree

6 files changed

+63
-32
lines changed

6 files changed

+63
-32
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
IMPROVEMENTS:
44
* agent: Add `BlockQueryWaitTime` config option for Nomad API connectivity [[GH-755](https://github.com/hashicorp/nomad-autoscaler/pull/755)]
5+
* agent: Add `high_availability.lock_namespace` configuration to specify the namespace used for writing the high availability lock variable. [[GH-832](https://github.com/hashicorp/nomad-autoscaler/pull/832)]
56
* metrics: Add `policy_id` and `target_name` labels to `scale.invoke.success_count` and `scale.invoke.error_count` metrics [[GH-814](https://github.com/hashicorp/nomad-autoscaler/pull/814)]
67
* plugin/target/aws: Add `scale_in_protection` configuration [[GH-807](https://github.com/hashicorp/nomad-autoscaler/pull/807)]
78
* scaleutils: Add new node filter option `node_pool` to select nodes by their node pool value [[GH-810](https://github.com/hashicorp/nomad-autoscaler/pull/810)]

agent/config/config.go

+14-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/hashicorp/nomad-autoscaler/plugins"
1717
"github.com/hashicorp/nomad-autoscaler/sdk/helper/file"
1818
"github.com/hashicorp/nomad-autoscaler/sdk/helper/ptr"
19+
"github.com/hashicorp/nomad/api"
1920
"github.com/mitchellh/copystructure"
2021
)
2122

@@ -288,6 +289,10 @@ type HighAvailability struct {
288289
// is successfully acquired.
289290
Enabled *bool `hcl:"enabled"`
290291

292+
// LockNamespace defines the namespace where the high availability lock
293+
// variable is written.
294+
LockNamespace string `hcl:"lock_namespace,optional" json:"-"`
295+
291296
// LockPath defines the path of the variable that will be used to sync the
292297
// leader when running on high availability mode.
293298
LockPath string `hcl:"lock_path,optional" json:"-"`
@@ -472,10 +477,11 @@ func Default() (*Agent, error) {
472477
{Name: plugins.InternalTargetNomad, Driver: plugins.InternalTargetNomad},
473478
},
474479
HighAvailability: &HighAvailability{
475-
Enabled: ptr.Of(false),
476-
LockPath: defaultLockPath,
477-
LockTTL: defaultLockTTL,
478-
LockDelay: defaultLockDelay,
480+
Enabled: ptr.Of(false),
481+
LockNamespace: api.DefaultNamespace,
482+
LockPath: defaultLockPath,
483+
LockTTL: defaultLockTTL,
484+
LockDelay: defaultLockDelay,
479485
},
480486
}, nil
481487
}
@@ -768,6 +774,10 @@ func (ha *HighAvailability) merge(b *HighAvailability) *HighAvailability {
768774
result.Enabled = b.Enabled
769775
}
770776

777+
if b.LockNamespace != "" {
778+
result.LockNamespace = b.LockNamespace
779+
}
780+
771781
if b.LockPath != "" {
772782
result.LockPath = b.LockPath
773783
}

agent/config/config_test.go

+11-6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"time"
1313

1414
"github.com/hashicorp/nomad-autoscaler/sdk/helper/ptr"
15+
"github.com/hashicorp/nomad/api"
1516
"github.com/stretchr/testify/assert"
1617
"github.com/stretchr/testify/require"
1718
)
@@ -38,6 +39,7 @@ func Test_Default(t *testing.T) {
3839
assert.Equal(t, 1*time.Second, def.Telemetry.CollectionInterval)
3940
assert.False(t, def.EnableDebug, "ensure debugging is disabled by default")
4041
assert.False(t, *def.HighAvailability.Enabled, "ensure high availability is disabled by default")
42+
assert.Equal(t, api.DefaultNamespace, def.HighAvailability.LockNamespace)
4143
assert.Equal(t, defaultLockPath, def.HighAvailability.LockPath)
4244
assert.Equal(t, defaultLockTTL, def.HighAvailability.LockTTL)
4345
assert.Equal(t, defaultLockDelay, def.HighAvailability.LockDelay)
@@ -80,8 +82,9 @@ func TestAgent_Merge(t *testing.T) {
8082
},
8183
},
8284
HighAvailability: &HighAvailability{
83-
Enabled: ptr.Of(false),
84-
LockPath: "original/path",
85+
Enabled: ptr.Of(false),
86+
LockNamespace: "ns-1",
87+
LockPath: "original/path",
8588
},
8689
}
8790

@@ -183,8 +186,9 @@ func TestAgent_Merge(t *testing.T) {
183186
},
184187
},
185188
HighAvailability: &HighAvailability{
186-
Enabled: ptr.Of(true),
187-
LockPath: "second/path",
189+
Enabled: ptr.Of(true),
190+
LockNamespace: "ns-2",
191+
LockPath: "second/path",
188192
},
189193
}
190194

@@ -316,8 +320,9 @@ func TestAgent_Merge(t *testing.T) {
316320
},
317321
},
318322
HighAvailability: &HighAvailability{
319-
Enabled: ptr.Of(true),
320-
LockPath: "second/path",
323+
Enabled: ptr.Of(true),
324+
LockNamespace: "ns-2",
325+
LockPath: "second/path",
321326
},
322327
}
323328

command/agent.go

+16-6
Original file line numberDiff line numberDiff line change
@@ -268,18 +268,24 @@ Telemetry Options:
268268
-telemetry-circonus-broker-select-tag
269269
A tag which is used to select a broker ID when an explicit broker ID is not
270270
provided.
271-
271+
272272
High Availability Options:
273273
274274
-high-availability-enabled
275275
On cases when multiple instances of the autoscaler need to be run at the same
276-
time, the high-availability option triggers a leader election using a lock
276+
time, the high-availability option triggers a leader election using a lock
277277
for sync among the different lock instances. It defaults to false.
278-
278+
279+
-high-availability-lock-namepsace
280+
When using the high-availability mode, the namepsace where the lock is
281+
written for leader election can be provided using the
282+
high-availability-lock-namespace flag. The same namespace must be provided
283+
to every instance of the autoscaler in order to be included in the election.
284+
279285
-high-availability-lock-path
280286
When using the high-availability mode, the path to the lock to be used for the
281-
leader election can be provided using the high-availability-lock-path flag.
282-
The same path must be provided to every instance of the autoscaler in order
287+
leader election can be provided using the high-availability-lock-path flag.
288+
The same path must be provided to every instance of the autoscaler in order
283289
to be included in the election.
284290
285291
-high-availability-lock-ttl
@@ -396,6 +402,7 @@ func (c *AgentCommand) Run(args []string) int {
396402
switch *parsedConfig.HighAvailability.Enabled {
397403
case true:
398404
logger.Info("running in HA mode",
405+
"lock_namespace", parsedConfig.HighAvailability.LockNamespace,
399406
"lock_path", parsedConfig.HighAvailability.LockPath,
400407
"lock_ttl", parsedConfig.HighAvailability.LockTTL,
401408
"lock_delay", parsedConfig.HighAvailability.LockDelay)
@@ -408,7 +415,9 @@ func (c *AgentCommand) Run(args []string) int {
408415
},
409416
}
410417

411-
locker, err := c.agent.NomadClient.Locks(api.WriteOptions{}, asLock)
418+
locker, err := c.agent.NomadClient.Locks(api.WriteOptions{
419+
Namespace: parsedConfig.HighAvailability.LockNamespace,
420+
}, asLock)
412421
if err != nil {
413422
logger.Error("failed to start locker", "error", err)
414423
return 1
@@ -571,6 +580,7 @@ func (c *AgentCommand) readConfig() (*config.Agent, []string) {
571580

572581
// Specify our High Availability flags.
573582
flags.BoolVar(&enableHighAvailability, "high-availability-enabled", false, "")
583+
flags.StringVar(&cmdConfig.HighAvailability.LockNamespace, "high-availability-lock-namespace", "", "")
574584
flags.StringVar(&cmdConfig.HighAvailability.LockPath, "high-availability-lock-path", "", "")
575585
flags.DurationVar(&cmdConfig.HighAvailability.LockTTL, "high-availability-lock-ttl", 0, "")
576586
flags.DurationVar(&cmdConfig.HighAvailability.LockDelay, "high-availability-lock-delay", 0, "")

command/agent_test.go

+16-12
Original file line numberDiff line numberDiff line change
@@ -195,16 +195,18 @@ func TestCommandAgent_readConfig(t *testing.T) {
195195
name: "high availlability flags",
196196
args: []string{
197197
"-high-availability-enabled",
198+
"-high-availability-lock-namespace", "my-namespace",
198199
"-high-availability-lock-path", "test/merge/path",
199200
"-high-availability-lock-ttl", "4m",
200201
"-high-availability-lock-delay", "2m",
201202
},
202203
want: defaultConfig.Merge(&config.Agent{
203204
HighAvailability: &config.HighAvailability{
204-
Enabled: ptr.Of(true),
205-
LockPath: "test/merge/path",
206-
LockTTL: 4 * time.Minute,
207-
LockDelay: 2 * time.Minute,
205+
Enabled: ptr.Of(true),
206+
LockNamespace: "my-namespace",
207+
LockPath: "test/merge/path",
208+
LockTTL: 4 * time.Minute,
209+
LockDelay: 2 * time.Minute,
208210
},
209211
}),
210212
},
@@ -255,10 +257,11 @@ func TestCommandAgent_readConfig(t *testing.T) {
255257
},
256258
},
257259
HighAvailability: &config.HighAvailability{
258-
Enabled: ptr.Of(true),
259-
LockPath: "my/custom/path",
260-
LockTTL: 30 * time.Second,
261-
LockDelay: 15 * time.Second,
260+
Enabled: ptr.Of(true),
261+
LockNamespace: "my-namespace",
262+
LockPath: "my/custom/path",
263+
LockTTL: 30 * time.Second,
264+
LockDelay: 15 * time.Second,
262265
},
263266
}),
264267
},
@@ -341,10 +344,11 @@ func TestCommandAgent_readConfig(t *testing.T) {
341344
},
342345
},
343346
HighAvailability: &config.HighAvailability{
344-
Enabled: ptr.Of(true),
345-
LockPath: "my/custom/path",
346-
LockTTL: 30 * time.Second,
347-
LockDelay: 15 * time.Second,
347+
Enabled: ptr.Of(true),
348+
LockNamespace: "my-namespace",
349+
LockPath: "my/custom/path",
350+
LockTTL: 30 * time.Second,
351+
LockDelay: 15 * time.Second,
348352
},
349353
}),
350354
},

command/test-fixtures/agent_config_full.hcl

+5-4
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ policy_eval {
5151
}
5252

5353
high_availability {
54-
enabled = true
55-
lock_path = "my/custom/path"
56-
lock_ttl = "30s"
57-
lock_delay = "15s"
54+
enabled = true
55+
lock_namespace = "my-namespace"
56+
lock_path = "my/custom/path"
57+
lock_ttl = "30s"
58+
lock_delay = "15s"
5859
}

0 commit comments

Comments
 (0)