Merge pull request #3456 from hashicorp/gossip-fix

Adds gossip keys to network segment memberlist configs.
pull/3465/head
James Phillips 7 years ago committed by GitHub
commit 17681f04f9

@ -31,6 +31,7 @@ import (
"github.com/hashicorp/consul/types" "github.com/hashicorp/consul/types"
"github.com/hashicorp/consul/watch" "github.com/hashicorp/consul/watch"
"github.com/hashicorp/go-uuid" "github.com/hashicorp/go-uuid"
"github.com/hashicorp/memberlist"
"github.com/hashicorp/raft" "github.com/hashicorp/raft"
"github.com/hashicorp/serf/serf" "github.com/hashicorp/serf/serf"
"github.com/shirou/gopsutil/host" "github.com/shirou/gopsutil/host"
@ -772,7 +773,8 @@ func (a *Agent) consulConfig() (*consul.Config, error) {
// Setup the loggers // Setup the loggers
base.LogOutput = a.LogOutput base.LogOutput = a.LogOutput
// This will set up the LAN keyring, as well as the WAN for servers. // This will set up the LAN keyring, as well as the WAN and any segments
// for servers.
if err := a.setupKeyrings(base); err != nil { if err := a.setupKeyrings(base); err != nil {
return nil, fmt.Errorf("Failed to configure keyring: %v", err) return nil, fmt.Errorf("Failed to configure keyring: %v", err)
} }
@ -946,8 +948,8 @@ func (a *Agent) setupNodeID(config *Config) error {
return nil return nil
} }
// setupKeyrings is used to initialize and load keyrings during agent startup // setupBaseKeyrings configures the LAN and WAN keyrings.
func (a *Agent) setupKeyrings(config *consul.Config) error { func (a *Agent) setupBaseKeyrings(config *consul.Config) error {
// If the keyring file is disabled then just poke the provided key // If the keyring file is disabled then just poke the provided key
// into the in-memory keyring. // into the in-memory keyring.
if a.config.DisableKeyringFile { if a.config.DisableKeyringFile {
@ -1006,6 +1008,34 @@ LOAD:
return nil return nil
} }
// setupKeyrings is used to initialize and load keyrings during agent startup.
func (a *Agent) setupKeyrings(config *consul.Config) error {
// First set up the LAN and WAN keyrings.
if err := a.setupBaseKeyrings(config); err != nil {
return err
}
// If there's no LAN keyring then there's nothing else to set up for
// any segments.
lanKeyring := config.SerfLANConfig.MemberlistConfig.Keyring
if lanKeyring == nil {
return nil
}
// Copy the initial state of the LAN keyring into each segment config.
// Segments don't have their own keyring file, they rely on the LAN
// holding the state so things can't get out of sync.
k, pk := lanKeyring.GetKeys(), lanKeyring.GetPrimaryKey()
for _, segment := range config.Segments {
keyring, err := memberlist.NewKeyring(k, pk)
if err != nil {
return err
}
segment.SerfConfig.MemberlistConfig.Keyring = keyring
}
return nil
}
// registerEndpoint registers a handler for the consul RPC server // registerEndpoint registers a handler for the consul RPC server
// under a unique name while making it accessible under the provided // under a unique name while making it accessible under the provided
// name. This allows overwriting handlers for the golang net/rpc // name. This allows overwriting handlers for the golang net/rpc

@ -149,12 +149,12 @@ func (m *Internal) executeKeyringOp(
if wan { if wan {
mgr := m.srv.KeyManagerWAN() mgr := m.srv.KeyManagerWAN()
m.executeKeyringOpMgr(mgr, args, reply, wan) m.executeKeyringOpMgr(mgr, args, reply, wan, "")
} else { } else {
segments := m.srv.LANSegments() segments := m.srv.LANSegments()
for _, segment := range segments { for name, segment := range segments {
mgr := segment.KeyManager() mgr := segment.KeyManager()
m.executeKeyringOpMgr(mgr, args, reply, wan) m.executeKeyringOpMgr(mgr, args, reply, wan, name)
} }
} }
} }
@ -166,7 +166,8 @@ func (m *Internal) executeKeyringOpMgr(
mgr *serf.KeyManager, mgr *serf.KeyManager,
args *structs.KeyringRequest, args *structs.KeyringRequest,
reply *structs.KeyringResponses, reply *structs.KeyringResponses,
wan bool) { wan bool,
segment string) {
var serfResp *serf.KeyResponse var serfResp *serf.KeyResponse
var err error var err error
@ -190,6 +191,7 @@ func (m *Internal) executeKeyringOpMgr(
reply.Responses = append(reply.Responses, &structs.KeyringResponse{ reply.Responses = append(reply.Responses, &structs.KeyringResponse{
WAN: wan, WAN: wan,
Datacenter: m.srv.config.Datacenter, Datacenter: m.srv.config.Datacenter,
Segment: segment,
Messages: serfResp.Messages, Messages: serfResp.Messages,
Keys: serfResp.Keys, Keys: serfResp.Keys,
NumNodes: serfResp.NumNodes, NumNodes: serfResp.NumNodes,

@ -887,6 +887,7 @@ func (r *KeyringRequest) RequestDatacenter() string {
type KeyringResponse struct { type KeyringResponse struct {
WAN bool WAN bool
Datacenter string Datacenter string
Segment string
Messages map[string]string `json:",omitempty"` Messages map[string]string `json:",omitempty"`
Keys map[string]int Keys map[string]int
NumNodes int NumNodes int

@ -13,6 +13,9 @@ type KeyringResponse struct {
// The datacenter name this request corresponds to // The datacenter name this request corresponds to
Datacenter string Datacenter string
// Segment has the network segment this request corresponds to.
Segment string
// A map of the encryption keys to the number of nodes they're installed on // A map of the encryption keys to the number of nodes they're installed on
Keys map[string]int Keys map[string]int

@ -129,6 +129,9 @@ func (c *KeyringCommand) Run(args []string) int {
func (c *KeyringCommand) handleList(responses []*consulapi.KeyringResponse) { func (c *KeyringCommand) handleList(responses []*consulapi.KeyringResponse) {
for _, response := range responses { for _, response := range responses {
pool := response.Datacenter + " (LAN)" pool := response.Datacenter + " (LAN)"
if response.Segment != "" {
pool += fmt.Sprintf(" [%s]", response.Segment)
}
if response.WAN { if response.WAN {
pool = "WAN" pool = "WAN"
} }

@ -55,6 +55,7 @@ $ curl \
{ {
"WAN": true, "WAN": true,
"Datacenter": "dc1", "Datacenter": "dc1",
"Segment": "",
"Keys": { "Keys": {
"0eK8RjnsGC/+I1fJErQsBA==": 1, "0eK8RjnsGC/+I1fJErQsBA==": 1,
"G/3/L4yOw3e5T7NTvuRi9g==": 1, "G/3/L4yOw3e5T7NTvuRi9g==": 1,
@ -65,6 +66,7 @@ $ curl \
{ {
"WAN": false, "WAN": false,
"Datacenter": "dc1", "Datacenter": "dc1",
"Segment": "",
"Keys": { "Keys": {
"0eK8RjnsGC/+I1fJErQsBA==": 1, "0eK8RjnsGC/+I1fJErQsBA==": 1,
"G/3/L4yOw3e5T7NTvuRi9g==": 1, "G/3/L4yOw3e5T7NTvuRi9g==": 1,
@ -80,6 +82,8 @@ $ curl \
- `Datacenter` is the datacenter the block refers to. - `Datacenter` is the datacenter the block refers to.
- `Segment` is the network segment the block refers to.
- `Keys` is a map of each gossip key to the number of nodes it's currently - `Keys` is a map of each gossip key to the number of nodes it's currently
installed on. installed on.

@ -73,11 +73,14 @@ dc2 (LAN):
dc1 (LAN): dc1 (LAN):
a1i101sMY8rxB+0eAKD/gw== [2/2] a1i101sMY8rxB+0eAKD/gw== [2/2]
dc1 (LAN) [alpha]:
a1i101sMY8rxB+0eAKD/gw== [2/2]
``` ```
As you can see, the output above is divided first by gossip pool, and then by As you can see, the output above is divided first by gossip pool, including any network
encryption key. The indicator to the right of each key displays the number of segments, and then by encryption key. The indicator to the right of each key displays
nodes the key is installed on over the total number of nodes in the pool. the number of nodes the key is installed on over the total number of nodes in the pool.
## Errors ## Errors

Loading…
Cancel
Save