Skip to content

Commit

Permalink
Supports WAN and LAN Serf Bind Addresses. (#2468)
Browse files Browse the repository at this point in the history
* * adding cli config and config file support for specifying the serf wan and lan bind addresses
* updating documentation for serf wan and lan options
Fixes #2007

* Cleans up some small things from #2380.

* Uses the bind default for the agent test for Serf WAN and LAN.
  • Loading branch information
slackpad authored Nov 3, 2016
1 parent cbf2874 commit 233a3a1
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 5 deletions.
15 changes: 11 additions & 4 deletions command/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,6 @@ func (a *Agent) consulConfig() *consul.Config {
if a.config.NodeName != "" {
base.NodeName = a.config.NodeName
}
if a.config.BindAddr != "" {
base.SerfLANConfig.MemberlistConfig.BindAddr = a.config.BindAddr
base.SerfWANConfig.MemberlistConfig.BindAddr = a.config.BindAddr
}
if a.config.Ports.SerfLan != 0 {
base.SerfLANConfig.MemberlistConfig.BindPort = a.config.Ports.SerfLan
base.SerfLANConfig.MemberlistConfig.AdvertisePort = a.config.Ports.SerfLan
Expand All @@ -286,6 +282,17 @@ func (a *Agent) consulConfig() *consul.Config {
Port: a.config.Ports.Server,
}
base.RPCAddr = bindAddr

// Set the Serf configs using the old default behavior, we may
// override these in the code right below.
base.SerfLANConfig.MemberlistConfig.BindAddr = a.config.BindAddr
base.SerfWANConfig.MemberlistConfig.BindAddr = a.config.BindAddr
}
if a.config.SerfLanBindAddr != "" {
base.SerfLANConfig.MemberlistConfig.BindAddr = a.config.SerfLanBindAddr
}
if a.config.SerfWanBindAddr != "" {
base.SerfWANConfig.MemberlistConfig.BindAddr = a.config.SerfWanBindAddr
}
if a.config.AdvertiseAddr != "" {
base.SerfLANConfig.MemberlistConfig.AdvertiseAddr = a.config.AdvertiseAddr
Expand Down
37 changes: 37 additions & 0 deletions command/agent/agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,21 @@ func makeAgent(t *testing.T, conf *Config) (string, *Agent) {
return makeAgentLog(t, conf, nil)
}

func externalIP() (string, error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
return "", fmt.Errorf("Unable to lookup network interfaces: %v", err)
}
for _, a := range addrs {
if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
return ipnet.IP.String(), nil
}
}
}
return "", fmt.Errorf("Unable to find a non-loopback interface")
}

func TestAgentStartStop(t *testing.T) {
dir, agent := makeAgent(t, nextConfig())
defer os.RemoveAll(dir)
Expand Down Expand Up @@ -154,6 +169,28 @@ func TestAgent_RPCPing(t *testing.T) {
}
}

func TestAgent_CheckSerfBindAddrsSettings(t *testing.T) {
c := nextConfig()
ip, err := externalIP()
if err != nil {
t.Fatalf("Unable to get a non-loopback IP: %v", err)
}
c.SerfLanBindAddr = ip
c.SerfWanBindAddr = ip
dir, agent := makeAgent(t, c)
defer os.RemoveAll(dir)
defer agent.Shutdown()

serfWanBind := agent.consulConfig().SerfWANConfig.MemberlistConfig.BindAddr
if serfWanBind != ip {
t.Fatalf("SerfWanBindAddr is should be a non-loopback IP not %s", serfWanBind)
}

serfLanBind := agent.consulConfig().SerfLANConfig.MemberlistConfig.BindAddr
if serfLanBind != ip {
t.Fatalf("SerfLanBindAddr is should be a non-loopback IP not %s", serfWanBind)
}
}
func TestAgent_CheckAdvertiseAddrsSettings(t *testing.T) {
c := nextConfig()
c.AdvertiseAddrs.SerfLan, _ = net.ResolveTCPAddr("tcp", "127.0.0.42:1233")
Expand Down
2 changes: 2 additions & 0 deletions command/agent/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ func (c *Command) readConfig() *Config {

cmdFlags.StringVar(&cmdConfig.ClientAddr, "client", "", "address to bind client listeners to (DNS, HTTP, HTTPS, RPC)")
cmdFlags.StringVar(&cmdConfig.BindAddr, "bind", "", "address to bind server listeners to")
cmdFlags.StringVar(&cmdConfig.SerfWanBindAddr, "serf-wan-bind", "", "address to bind Serf WAN listeners to")
cmdFlags.StringVar(&cmdConfig.SerfLanBindAddr, "serf-lan-bind", "", "address to bind Serf LAN listeners to")
cmdFlags.IntVar(&cmdConfig.Ports.HTTP, "http-port", 0, "http port to use")
cmdFlags.IntVar(&cmdConfig.Ports.DNS, "dns-port", 0, "DNS port to use")
cmdFlags.StringVar(&cmdConfig.AdvertiseAddr, "advertise", "", "address to advertise instead of bind addr")
Expand Down
8 changes: 8 additions & 0 deletions command/agent/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ func TestReadCliConfig(t *testing.T) {
"-data-dir", tmpDir,
"-node", `"a"`,
"-advertise-wan", "1.2.3.4",
"-serf-wan-bind", "4.3.2.1",
"-serf-lan-bind", "4.3.2.2",
},
ShutdownCh: shutdownCh,
Ui: new(cli.MockUi),
Expand All @@ -135,6 +137,12 @@ func TestReadCliConfig(t *testing.T) {
if config.AdvertiseAddrWan != "1.2.3.4" {
t.Fatalf("expected -advertise-addr-wan 1.2.3.4 got %s", config.AdvertiseAddrWan)
}
if config.SerfWanBindAddr != "4.3.2.1" {
t.Fatalf("expected -serf-wan-bind 4.3.2.1 got %s", config.SerfWanBindAddr)
}
if config.SerfLanBindAddr != "4.3.2.2" {
t.Fatalf("expected -serf-lan-bind 4.3.2.2 got %s", config.SerfLanBindAddr)
}
}

// Test LeaveOnTerm and SkipLeaveOnInt defaults for server mode
Expand Down
18 changes: 18 additions & 0 deletions command/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,18 @@ type Config struct {
// services (Gossip, Server RPC)
BindAddr string `mapstructure:"bind_addr"`

// SerfWanBindAddr is used to control the address we bind to.
// If not specified, the first private IP we find is used.
// This controls the address we use for cluster facing
// services (Gossip) Serf
SerfWanBindAddr string `mapstructure:"serf_wan_bind"`

// SerfLanBindAddr is used to control the address we bind to.
// If not specified, the first private IP we find is used.
// This controls the address we use for cluster facing
// services (Gossip) Serf
SerfLanBindAddr string `mapstructure:"serf_lan_bind"`

// AdvertiseAddr is the address we use for advertising our Serf,
// and Consul RPC IP. If not specified, bind address is used.
AdvertiseAddr string `mapstructure:"advertise_addr"`
Expand Down Expand Up @@ -1180,6 +1192,12 @@ func MergeConfig(a, b *Config) *Config {
if b.AdvertiseAddrWan != "" {
result.AdvertiseAddrWan = b.AdvertiseAddrWan
}
if b.SerfWanBindAddr != "" {
result.SerfWanBindAddr = b.SerfWanBindAddr
}
if b.SerfLanBindAddr != "" {
result.SerfLanBindAddr = b.SerfLanBindAddr
}
if b.TranslateWanAddrs == true {
result.TranslateWanAddrs = true
}
Expand Down
11 changes: 10 additions & 1 deletion command/agent/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,9 @@ func TestDecodeConfig(t *testing.T) {
}

// Server addrs
input = `{"ports": {"server": 8000}, "bind_addr": "127.0.0.2", "advertise_addr": "127.0.0.3"}`
input = `{"ports": {"server": 8000}, "bind_addr": "127.0.0.2", "advertise_addr": "127.0.0.3", "serf_lan_bind": "127.0.0.4", "serf_wan_bind": "52.54.55.56"}`
config, err = DecodeConfig(bytes.NewReader([]byte(input)))

if err != nil {
t.Fatalf("err: %s", err)
}
Expand All @@ -189,6 +190,14 @@ func TestDecodeConfig(t *testing.T) {
t.Fatalf("bad: %#v", config)
}

if config.SerfWanBindAddr != "52.54.55.56" {
t.Fatalf("bad: %#v", config)
}

if config.SerfLanBindAddr != "127.0.0.4" {
t.Fatalf("bad: %#v", config)
}

if config.AdvertiseAddr != "127.0.0.3" {
t.Fatalf("bad: %#v", config)
}
Expand Down
14 changes: 14 additions & 0 deletions website/source/docs/agent/options.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ will exit with an error at startup.
Consul uses both TCP and UDP and the same port for both. If you
have any firewalls, be sure to allow both protocols.

* <a name="_serf_wan_bind"></a><a href="#_serf_wan_bind">`-serf-wan-bind`</a> - The address that should be bound to for Serf WAN gossip communications.
By default, the value follows the same rules as [`-bind` command-line flag](#_bind), and if this is not specified, the `-bind` option is used. This
is available in Consul 0.7.1 and later.

* <a name="_serf_lan_bind"></a><a href="#_serf_lan_bind">`-serf-lan-bind`</a> - The address that should be bound to for Serf LAN gossip communications.
This is an IP address that should be reachable by all other LAN nodes in the cluster. By default, the value follows the same rules as
[`-bind` command-line flag](#_bind), and if this is not specified, the `-bind` option is used. This is available in Consul 0.7.1 and later.

* <a name="_client"></a><a href="#_client">`-client`</a> - The address to which
Consul will bind client interfaces,
including the HTTP, DNS, and RPC servers. By default, this is "127.0.0.1",
Expand Down Expand Up @@ -428,6 +436,12 @@ Consul will not enable TLS for the HTTP API unless the `https` port has been ass
* <a name="advertise_addr"></a><a href="#advertise_addr">`advertise_addr`</a> Equivalent to
the [`-advertise` command-line flag](#_advertise).

* <a name="serf_wan_bind"></a><a href="#serf_wan_bind">`serf_wan_bind`</a> Equivalent to
the [`-serf-wan-bind` command-line flag](#_serf_wan_bind).

* <a name="serf_lan_bind"></a><a href="#serf_lan_bind">`serf_lan_bind`</a> Equivalent to
the [`-serf-lan-bind` command-line flag](#_serf_lan_bind).

* <a name="advertise_addrs"></a><a href="#advertise_addrs">`advertise_addrs`</a> Allows to set
the advertised addresses for SerfLan, SerfWan and RPC together with the port. This gives
you more control than <a href="#_advertise">`-advertise`</a> or <a href="#_advertise-wan">`-advertise-wan`</a>
Expand Down

0 comments on commit 233a3a1

Please sign in to comment.