diff --git a/.changelog/12496.txt b/.changelog/12496.txt new file mode 100644 index 000000000000..ad268bc67f22 --- /dev/null +++ b/.changelog/12496.txt @@ -0,0 +1,3 @@ +```release-note:bug +raft: upgrade to v1.3.6 which fixes a bug where a read replica node could attempt bootstrapping raft and prevent other nodes from bootstrapping at all +``` diff --git a/agent/consul/server.go b/agent/consul/server.go index 5c513efe8114..e31b396fbc49 100644 --- a/agent/consul/server.go +++ b/agent/consul/server.go @@ -807,7 +807,7 @@ func (s *Server) setupRaft() error { // If we are in bootstrap or dev mode and the state is clean then we can // bootstrap now. - if s.config.Bootstrap || s.config.DevMode { + if (s.config.Bootstrap || s.config.DevMode) && !s.config.ReadReplica { hasState, err := raft.HasExistingState(log, stable, snap) if err != nil { return err diff --git a/agent/consul/server_serf.go b/agent/consul/server_serf.go index b0847eaa49b8..1b61f9fa0295 100644 --- a/agent/consul/server_serf.go +++ b/agent/consul/server_serf.go @@ -334,6 +334,11 @@ func (s *Server) maybeBootstrap() { return } + if s.config.ReadReplica { + s.logger.Info("Read replicas cannot bootstrap raft") + return + } + // Scan for all the known servers. members := s.serfLAN.Members() var servers []metadata.Server diff --git a/go.mod b/go.mod index 5b1de62abdb3..24b5a1668500 100644 --- a/go.mod +++ b/go.mod @@ -52,7 +52,7 @@ require ( github.com/hashicorp/mdns v1.0.4 // indirect github.com/hashicorp/memberlist v0.3.1 github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69 - github.com/hashicorp/raft v1.3.5 + github.com/hashicorp/raft v1.3.6 github.com/hashicorp/raft-autopilot v0.1.5 github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea github.com/hashicorp/serf v0.9.5 diff --git a/go.sum b/go.sum index c3df92a77be7..7dd39a83fd9c 100644 --- a/go.sum +++ b/go.sum @@ -285,8 +285,8 @@ github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69 h1:lc github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69/go.mod h1:/z+jUGRBlwVpUZfjute9jWaF6/HuhjuFQuL1YXzVD1Q= github.com/hashicorp/raft v1.1.1/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= -github.com/hashicorp/raft v1.3.5 h1:93YBXmHWW2MuyMZfMxN1PsAnPXAt+hBfG0S0ZrZxRrY= -github.com/hashicorp/raft v1.3.5/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= +github.com/hashicorp/raft v1.3.6 h1:v5xW5KzByoerQlN/o31VJrFNiozgzGyDoMgDJgXpsto= +github.com/hashicorp/raft v1.3.6/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= github.com/hashicorp/raft-autopilot v0.1.5 h1:onEfMH5uHVdXQqtas36zXUHEZxLdsJVu/nXHLcLdL1I= github.com/hashicorp/raft-autopilot v0.1.5/go.mod h1:Af4jZBwaNOI+tXfIqIdbcAnh/UyyqIMj/pOISIfhArw= github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea h1:xykPFhrBAS2J0VBzVa5e80b5ZtYuNQtgXjN40qBZlD4= diff --git a/vendor/github.com/hashicorp/raft/api.go b/vendor/github.com/hashicorp/raft/api.go index 4b34b4d07c76..c056ec8b9f8d 100644 --- a/vendor/github.com/hashicorp/raft/api.go +++ b/vendor/github.com/hashicorp/raft/api.go @@ -36,6 +36,10 @@ var ( // follower or candidate node. ErrNotLeader = errors.New("node is not the leader") + // ErrNotVoter is returned when an operation can't be completed on a + // non-voter node. + ErrNotVoter = errors.New("node is not a voter") + // ErrLeadershipLost is returned when a leader fails to commit a log entry // because it's been deposed in the process. ErrLeadershipLost = errors.New("leadership lost while committing log") diff --git a/vendor/github.com/hashicorp/raft/raft.go b/vendor/github.com/hashicorp/raft/raft.go index 8ed676b1b974..2cbeb778d383 100644 --- a/vendor/github.com/hashicorp/raft/raft.go +++ b/vendor/github.com/hashicorp/raft/raft.go @@ -233,6 +233,11 @@ func (r *Raft) runFollower() { // the Raft object's member BootstrapCluster for more details. This must only be // called on the main thread, and only makes sense in the follower state. func (r *Raft) liveBootstrap(configuration Configuration) error { + if !hasVote(configuration, r.localID) { + // Reject this operation since we are not a voter + return ErrNotVoter + } + // Use the pre-init API to make the static updates. cfg := r.config() err := BootstrapCluster(&cfg, r.logs, r.stable, r.snapshots, r.trans, configuration) diff --git a/vendor/modules.txt b/vendor/modules.txt index 98228eedd61d..e777a05cf283 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -483,7 +483,7 @@ github.com/hashicorp/mdns github.com/hashicorp/memberlist # github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69 github.com/hashicorp/net-rpc-msgpackrpc -# github.com/hashicorp/raft v1.3.5 +# github.com/hashicorp/raft v1.3.6 github.com/hashicorp/raft # github.com/hashicorp/raft-autopilot v0.1.5 github.com/hashicorp/raft-autopilot