mirror of
https://github.com/hashicorp/vault.git
synced 2025-11-29 06:31:10 +01:00
Add support for reloading raft config (#29485)
This commit is contained in:
parent
0c3449dacd
commit
38c3e15e1e
3
changelog/29485.txt
Normal file
3
changelog/29485.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
```release-note:improvement
|
||||||
|
core: Config reloading on SIGHUP now includes some Raft settings, which are now also present in `/sys/config/state/sanitized` output.
|
||||||
|
```
|
||||||
@ -1639,6 +1639,10 @@ func (c *ServerCommand) Run(args []string) int {
|
|||||||
c.logger.Warn(cErr.String())
|
c.logger.Warn(cErr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := core.ReloadRaftConfig(config.Storage.Config); err != nil {
|
||||||
|
c.logger.Warn("error reloading raft config", "error", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
// Note that seal reloading can also be triggered via Core.TriggerSealReload.
|
// Note that seal reloading can also be triggered via Core.TriggerSealReload.
|
||||||
// See the call to Core.SetSealReloadFunc above.
|
// See the call to Core.SetSealReloadFunc above.
|
||||||
if reloaded, err := c.reloadSealsOnSigHup(ctx, core, config); err != nil {
|
if reloaded, err := c.reloadSealsOnSigHup(ctx, core, config); err != nil {
|
||||||
|
|||||||
@ -1338,6 +1338,9 @@ func (c *Config) Sanitized() map[string]interface{} {
|
|||||||
sanitizedStorage["raft"] = map[string]interface{}{
|
sanitizedStorage["raft"] = map[string]interface{}{
|
||||||
"max_entry_size": c.Storage.Config["max_entry_size"],
|
"max_entry_size": c.Storage.Config["max_entry_size"],
|
||||||
}
|
}
|
||||||
|
for k, v := range c.Storage.Config {
|
||||||
|
sanitizedStorage["raft"].(map[string]interface{})[k] = v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result["storage"] = sanitizedStorage
|
result["storage"] = sanitizedStorage
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-test/deep"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/hashicorp/vault/command/server"
|
"github.com/hashicorp/vault/command/server"
|
||||||
"github.com/hashicorp/vault/internalshared/configutil"
|
"github.com/hashicorp/vault/internalshared/configutil"
|
||||||
"github.com/hashicorp/vault/vault"
|
"github.com/hashicorp/vault/vault"
|
||||||
@ -42,6 +42,8 @@ func TestSysConfigState_Sanitized(t *testing.T) {
|
|||||||
"cluster_addr": "http://127.0.0.1:8201",
|
"cluster_addr": "http://127.0.0.1:8201",
|
||||||
"disable_clustering": false,
|
"disable_clustering": false,
|
||||||
"raft": map[string]interface{}{
|
"raft": map[string]interface{}{
|
||||||
|
"path": "/storage/path/raft",
|
||||||
|
"node_id": "raft1",
|
||||||
"max_entry_size": "2097152",
|
"max_entry_size": "2097152",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -199,7 +201,7 @@ func TestSysConfigState_Sanitized(t *testing.T) {
|
|||||||
testResponseBody(t, resp, &actual)
|
testResponseBody(t, resp, &actual)
|
||||||
expected["request_id"] = actual["request_id"]
|
expected["request_id"] = actual["request_id"]
|
||||||
|
|
||||||
if diff := deep.Equal(actual, expected); len(diff) > 0 {
|
if diff := cmp.Diff(actual, expected); len(diff) > 0 {
|
||||||
t.Fatalf("bad mismatch response body: diff: %v", diff)
|
t.Fatalf("bad mismatch response body: diff: %v", diff)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -34,7 +34,7 @@ func TestRaft_Chunking_Lifecycle(t *testing.T) {
|
|||||||
|
|
||||||
t.Log("applying configuration")
|
t.Log("applying configuration")
|
||||||
|
|
||||||
b.applyConfigSettings(raft.DefaultConfig())
|
ApplyConfigSettings(b.logger, b.conf, raft.DefaultConfig())
|
||||||
|
|
||||||
t.Log("chunking")
|
t.Log("chunking")
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ func TestFSM_Chunking_TermChange(t *testing.T) {
|
|||||||
|
|
||||||
t.Log("applying configuration")
|
t.Log("applying configuration")
|
||||||
|
|
||||||
b.applyConfigSettings(raft.DefaultConfig())
|
ApplyConfigSettings(b.logger, b.conf, raft.DefaultConfig())
|
||||||
|
|
||||||
t.Log("chunking")
|
t.Log("chunking")
|
||||||
|
|
||||||
|
|||||||
@ -1069,9 +1069,9 @@ func (b *RaftBackend) SetRemovedCallback(cb func()) {
|
|||||||
b.removedCallback = cb
|
b.removedCallback = cb
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *RaftBackend) applyConfigSettings(config *raft.Config) error {
|
func ApplyConfigSettings(logger log.Logger, parsedConf map[string]string, config *raft.Config) error {
|
||||||
config.Logger = b.logger
|
config.Logger = logger
|
||||||
multiplierRaw, ok := b.conf["performance_multiplier"]
|
multiplierRaw, ok := parsedConf["performance_multiplier"]
|
||||||
multiplier := 5
|
multiplier := 5
|
||||||
if ok {
|
if ok {
|
||||||
var err error
|
var err error
|
||||||
@ -1084,7 +1084,7 @@ func (b *RaftBackend) applyConfigSettings(config *raft.Config) error {
|
|||||||
config.HeartbeatTimeout *= time.Duration(multiplier)
|
config.HeartbeatTimeout *= time.Duration(multiplier)
|
||||||
config.LeaderLeaseTimeout *= time.Duration(multiplier)
|
config.LeaderLeaseTimeout *= time.Duration(multiplier)
|
||||||
|
|
||||||
snapThresholdRaw, ok := b.conf["snapshot_threshold"]
|
snapThresholdRaw, ok := parsedConf["snapshot_threshold"]
|
||||||
if ok {
|
if ok {
|
||||||
var err error
|
var err error
|
||||||
snapThreshold, err := strconv.Atoi(snapThresholdRaw)
|
snapThreshold, err := strconv.Atoi(snapThresholdRaw)
|
||||||
@ -1094,7 +1094,7 @@ func (b *RaftBackend) applyConfigSettings(config *raft.Config) error {
|
|||||||
config.SnapshotThreshold = uint64(snapThreshold)
|
config.SnapshotThreshold = uint64(snapThreshold)
|
||||||
}
|
}
|
||||||
|
|
||||||
trailingLogsRaw, ok := b.conf["trailing_logs"]
|
trailingLogsRaw, ok := parsedConf["trailing_logs"]
|
||||||
if ok {
|
if ok {
|
||||||
var err error
|
var err error
|
||||||
trailingLogs, err := strconv.Atoi(trailingLogsRaw)
|
trailingLogs, err := strconv.Atoi(trailingLogsRaw)
|
||||||
@ -1103,7 +1103,7 @@ func (b *RaftBackend) applyConfigSettings(config *raft.Config) error {
|
|||||||
}
|
}
|
||||||
config.TrailingLogs = uint64(trailingLogs)
|
config.TrailingLogs = uint64(trailingLogs)
|
||||||
}
|
}
|
||||||
snapshotIntervalRaw, ok := b.conf["snapshot_interval"]
|
snapshotIntervalRaw, ok := parsedConf["snapshot_interval"]
|
||||||
if ok {
|
if ok {
|
||||||
var err error
|
var err error
|
||||||
snapshotInterval, err := parseutil.ParseDurationSecond(snapshotIntervalRaw)
|
snapshotInterval, err := parseutil.ParseDurationSecond(snapshotIntervalRaw)
|
||||||
@ -1121,7 +1121,7 @@ func (b *RaftBackend) applyConfigSettings(config *raft.Config) error {
|
|||||||
// scheduler.
|
// scheduler.
|
||||||
config.BatchApplyCh = true
|
config.BatchApplyCh = true
|
||||||
|
|
||||||
b.logger.Trace("applying raft config", "inputs", b.conf)
|
logger.Trace("applying raft config", "inputs", parsedConf)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1200,7 +1200,7 @@ func (b *RaftBackend) SetupCluster(ctx context.Context, opts SetupOpts) error {
|
|||||||
|
|
||||||
// Setup the raft config
|
// Setup the raft config
|
||||||
raftConfig := raft.DefaultConfig()
|
raftConfig := raft.DefaultConfig()
|
||||||
if err := b.applyConfigSettings(raftConfig); err != nil {
|
if err := ApplyConfigSettings(b.logger, b.conf, raftConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2322,3 +2322,17 @@ func isRaftLogVerifyCheckpoint(l *raft.Log) bool {
|
|||||||
// Must be the last chunk of a chunked object that has chunking meta
|
// Must be the last chunk of a chunked object that has chunking meta
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *RaftBackend) ReloadConfig(config raft.ReloadableConfig) error {
|
||||||
|
b.l.RLock()
|
||||||
|
defer b.l.RUnlock()
|
||||||
|
|
||||||
|
if b.raft != nil {
|
||||||
|
if err := b.raft.ReloadConfig(config); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
b.logger.Info("reloaded raft config", "settings", config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@ -894,7 +894,7 @@ func TestRaft_Backend_Performance(t *testing.T) {
|
|||||||
|
|
||||||
defaultConfig := raft.DefaultConfig()
|
defaultConfig := raft.DefaultConfig()
|
||||||
localConfig := raft.DefaultConfig()
|
localConfig := raft.DefaultConfig()
|
||||||
err := b.applyConfigSettings(localConfig)
|
err := ApplyConfigSettings(b.logger, b.conf, localConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -915,7 +915,7 @@ func TestRaft_Backend_Performance(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
localConfig = raft.DefaultConfig()
|
localConfig = raft.DefaultConfig()
|
||||||
err = b.applyConfigSettings(localConfig)
|
err = ApplyConfigSettings(b.logger, b.conf, localConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -936,7 +936,7 @@ func TestRaft_Backend_Performance(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
localConfig = raft.DefaultConfig()
|
localConfig = raft.DefaultConfig()
|
||||||
err = b.applyConfigSettings(localConfig)
|
err = ApplyConfigSettings(b.logger, b.conf, localConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import (
|
|||||||
"github.com/hashicorp/go-uuid"
|
"github.com/hashicorp/go-uuid"
|
||||||
goversion "github.com/hashicorp/go-version"
|
goversion "github.com/hashicorp/go-version"
|
||||||
lru "github.com/hashicorp/golang-lru/v2"
|
lru "github.com/hashicorp/golang-lru/v2"
|
||||||
|
raftlib "github.com/hashicorp/raft"
|
||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
httpPriority "github.com/hashicorp/vault/http/priority"
|
httpPriority "github.com/hashicorp/vault/http/priority"
|
||||||
"github.com/hashicorp/vault/physical/raft"
|
"github.com/hashicorp/vault/physical/raft"
|
||||||
@ -1321,6 +1322,25 @@ func NewDelegateForCore(c *Core) *raft.Delegate {
|
|||||||
return raft.NewDelegate(c.getRaftBackend(), persistedState, c.saveAutopilotPersistedState)
|
return raft.NewDelegate(c.getRaftBackend(), persistedState, c.saveAutopilotPersistedState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Core) ReloadRaftConfig(config map[string]string) error {
|
||||||
|
rb := c.getRaftBackend()
|
||||||
|
if rb == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
raftConfig := raftlib.DefaultConfig()
|
||||||
|
if err := raft.ApplyConfigSettings(c.logger, config, raftConfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rlconfig := raftlib.ReloadableConfig{
|
||||||
|
TrailingLogs: raftConfig.TrailingLogs,
|
||||||
|
SnapshotInterval: raftConfig.SnapshotInterval,
|
||||||
|
SnapshotThreshold: raftConfig.SnapshotThreshold,
|
||||||
|
HeartbeatTimeout: raftConfig.HeartbeatTimeout,
|
||||||
|
ElectionTimeout: raftConfig.ElectionTimeout,
|
||||||
|
}
|
||||||
|
return rb.ReloadConfig(rlconfig)
|
||||||
|
}
|
||||||
|
|
||||||
// getRaftBackend returns the RaftBackend from the HA or physical backend,
|
// getRaftBackend returns the RaftBackend from the HA or physical backend,
|
||||||
// in that order of preference, or nil if not of type RaftBackend.
|
// in that order of preference, or nil if not of type RaftBackend.
|
||||||
func (c *Core) getRaftBackend() *raft.RaftBackend {
|
func (c *Core) getRaftBackend() *raft.RaftBackend {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user