github.com/outbrain/consul@v1.4.5/website/source/docs/guides/segments.html.markdown.erb (about) 1 --- 2 layout: "docs" 3 page_title: "Partial LAN Connectivity - Configuring Network Segments" 4 sidebar_current: "docs-guides-segments" 5 description: |- 6 Many advanced Consul users have the need to run clusters with segmented networks, meaning that 7 not all agents can be in a full mesh. This is usually the result of business policies enforced 8 via network rules or firewalls. Prior to Consul 0.9.3 this was only possible through federation, 9 which for some users is too heavyweight or expensive as it requires running multiple servers per 10 segment. 11 --- 12 13 # Network Segments 14 15 ## Partial LAN Connectivity with Network Segments 16 17 [//]: # ( ~> The network segment functionality described here is available only in ) 18 [//]: # ( [Consul Enterprise](https://www.hashicorp.com/products/consul/) version 0.9.3 and later. ) 19 20 <%= enterprise_alert :consul %> 21 22 Many advanced Consul users have the need to run clusters with segmented networks, meaning that 23 not all agents can be in a full mesh. This is usually the result of business policies enforced 24 via network rules or firewalls. Prior to Consul 0.9.3 this was only possible through federation, 25 which for some users is too heavyweight or expensive as it requires running multiple servers per 26 segment. 27 28 By default, all Consul agents in one datacenter are part of a shared gossip pool over the LAN; 29 this means that the partial connectivity caused by segmented networks would cause health flapping 30 as nodes failed to communicate. In this guide we will cover the Network Segments feature, added 31 in [Consul Enterprise](https://www.hashicorp.com/products/consul/) version 0.9.3, which allows users 32 to configure Consul to support this kind of segmented network topology. 33 34 This guide will cover the basic configuration for setting up multiple segments, as well as 35 how to configure a prepared query to limit service discovery to the services in the local agent's 36 network segment. 37 38 ## Configuring Network Segments 39 40 All Consul agents are part of the default network segment, `""`, unless a segment is specified in 41 their configuration. In a standard cluster setup all agents will normally be part of this default 42 segment and as a result, part of one shared LAN gossip pool. Network segments can be used to break 43 up the LAN gossip pool into multiple isolated smaller pools by specifying the configuration for segments 44 on the servers. Each desired segment must be given a name and port, as well as optionally a custom 45 bind and advertise address for that segment's gossip listener to bind to on the server. 46 47 A few things to note: 48 49 1. Servers will be a part of all segments they have been configured with. They are the common point 50 linking the different segments together. The configured list of segments is specified by the 51 [`segments`](/docs/agent/options.html#segments) option. 52 53 2. Client agents can only be part of one segment at a given time, specified by the [`-segment`] 54 (/docs/agent/options.html#_segment) option. 55 56 3. Clients can only join agents in the same segment as them. If they attempt to join a client in 57 another segment, or the listening port of another segment on a server, they will get a segment mismatch error. 58 59 Once the servers have been configured with the correct segment info, the clients only need to specify 60 their own segment in the [Agent Config](/docs/agent/options.html#_segment) and join by connecting to another 61 agent within the same segment. If joining to a Consul server, client will need to provide the server's 62 port for their segment along with the address of the server when performing the join (for example, 63 `consul agent -retry-join "consul.domain.internal:1234"`). 64 65 ## Getting Started 66 67 To get started, follow the [bootstrapping guide](/docs/guides/bootstrapping.html) to 68 start a server or group of servers, with the following section added to the configuration (you may need to 69 adjust the bind/advertise addresses for your setup): 70 71 ```json 72 { 73 ... 74 "segments": [ 75 {"name": "alpha", "bind": "{{GetPrivateIP}}", "advertise": "{{GetPrivateIP}}", "port": 8303}, 76 {"name": "beta", "bind": "{{GetPrivateIP}}", "advertise": "{{GetPrivateIP}}", "port": 8304} 77 ] 78 } 79 ``` 80 81 You should see a log message on the servers for each segment's listener as the agent starts up: 82 83 ```text 84 2017/08/30 19:05:13 [INFO] serf: EventMemberJoin: server1.dc1 192.168.0.4 85 2017/08/30 19:05:13 [INFO] serf: EventMemberJoin: server1 192.168.0.4 86 2017/08/30 19:05:13 [INFO] consul: Started listener for LAN segment "alpha" on 192.168.0.4:8303 87 2017/08/30 19:05:13 [INFO] serf: EventMemberJoin: server1 192.168.0.4 88 2017/08/30 19:05:13 [INFO] consul: Started listener for LAN segment "beta" on 192.168.0.4:8304 89 2017/08/30 19:05:13 [INFO] serf: EventMemberJoin: server1 192.168.0.4 90 ``` 91 92 Running `consul members` should show the server as being part of all segments: 93 94 ```text 95 (server1) $ consul members 96 Node Address Status Type Build Protocol DC Segment 97 server1 192.168.0.4:8301 alive server 0.9.3+ent 2 dc1 <all> 98 ``` 99 100 Next, start a client agent in the 'alpha' segment, with `-join` set to the server's segment 101 address/port for that segment: 102 103 ```text 104 (client1) $ consul agent ... -join 192.168.0.4:8303 -node client1 -segment alpha 105 ``` 106 107 After the join is successful, we should see the client show up by running the `consul members` command 108 on the server again: 109 110 ```text 111 (server1) $ consul members 112 Node Address Status Type Build Protocol DC Segment 113 server1 192.168.0.4:8301 alive server 0.9.3+ent 2 dc1 <all> 114 client1 192.168.0.5:8301 alive client 0.9.3+ent 2 dc1 alpha 115 ``` 116 117 Now join another client in segment 'beta' and run the `consul members` command another time: 118 119 ```text 120 (client2) $ consul agent ... -join 192.168.0.4:8304 -node client2 -segment beta 121 ``` 122 123 ```text 124 (server1) $ consul members 125 Node Address Status Type Build Protocol DC Segment 126 server1 192.168.0.4:8301 alive server 0.9.3+ent 2 dc1 <all> 127 client1 192.168.0.5:8301 alive client 0.9.3+ent 2 dc1 alpha 128 client2 192.168.0.6:8301 alive client 0.9.3+ent 2 dc1 beta 129 ``` 130 131 If we pass the `-segment` flag when running `consul members`, we can limit the view to agents 132 in a specific segment: 133 134 ```text 135 (server1) $ consul members -segment alpha 136 Node Address Status Type Build Protocol DC Segment 137 client1 192.168.0.5:8301 alive client 0.9.3+ent 2 dc1 alpha 138 server1 192.168.0.4:8303 alive server 0.9.3+ent 2 dc1 alpha 139 ``` 140 141 Using the `consul catalog nodes` command, we can filter on an internal metadata key, 142 `consul-network-segment`, which stores the network segment of the node: 143 144 ```text 145 (server1) $ consul catalog nodes -node-meta consul-network-segment=alpha 146 Node ID Address DC 147 client1 4c29819c 192.168.0.5 dc1 148 ``` 149 150 With this metadata key, we can construct a [Prepared Query](/api/query.html) that can be used 151 for DNS to return only services within the same network segment as the local agent. 152 153 First, register a service on each of the client nodes: 154 155 ```text 156 (client1) $ curl \ 157 --request PUT \ 158 --data '{"Name": "redis", "Port": 8000}' \ 159 localhost:8500/v1/agent/service/register 160 ``` 161 162 ```text 163 (client2) $ curl \ 164 --request PUT \ 165 --data '{"Name": "redis", "Port": 9000}' \ 166 localhost:8500/v1/agent/service/register 167 ``` 168 169 Next, write the following to `query.json` and create the query using the HTTP endpoint: 170 171 ```text 172 (server1) $ curl \ 173 --request POST \ 174 --data \ 175 '{ 176 "Name": "", 177 "Template": { 178 "Type": "name_prefix_match" 179 }, 180 "Service": { 181 "Service": "${name.full}", 182 "NodeMeta": {"consul-network-segment": "${agent.segment}"} 183 } 184 }' localhost:8500/v1/query 185 186 {"ID":"6f49dd24-de9b-0b6c-fd29-525eca069419"} 187 ``` 188 189 Now, we can replace any dns lookups of the form `<service>.service.consul` with 190 `<service>.query.consul` to look up only services within the same network segment: 191 192 **Client 1:** 193 194 ```text 195 (client1) $ dig @127.0.0.1 -p 8600 redis.query.consul SRV 196 197 ; <<>> DiG 9.8.3-P1 <<>> @127.0.0.1 -p 8600 redis.query.consul SRV 198 ; (1 server found) 199 ;; global options: +cmd 200 ;; Got answer: 201 ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3149 202 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 203 ;; WARNING: recursion requested but not available 204 205 ;; QUESTION SECTION: 206 ;redis.query.consul. IN SRV 207 208 ;; ANSWER SECTION: 209 redis.query.consul. 0 IN SRV 1 1 8000 client1.node.dc1.consul. 210 211 ;; ADDITIONAL SECTION: 212 client1.node.dc1.consul. 0 IN A 192.168.0.5 213 ``` 214 215 **Client 2:** 216 217 ```text 218 (client2) $ dig @127.0.0.1 -p 8600 redis.query.consul SRV 219 220 ; <<>> DiG 9.8.3-P1 <<>> @127.0.0.1 -p 8600 redis.query.consul SRV 221 ; (1 server found) 222 ;; global options: +cmd 223 ;; Got answer: 224 ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3149 225 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 226 ;; WARNING: recursion requested but not available 227 228 ;; QUESTION SECTION: 229 ;redis.query.consul. IN SRV 230 231 ;; ANSWER SECTION: 232 redis.query.consul. 0 IN SRV 1 1 9000 client2.node.dc1.consul. 233 234 ;; ADDITIONAL SECTION: 235 client2.node.dc1.consul. 0 IN A 192.168.0.6 236 ```