Consul: Service Discovery & Beyond
24 September 2018
What is Consul?
Service Discovery
Distributed
Key-Value Store
Live Templating
Service Mesh
(coming soon)
Distributed, Scalable Architecture
Architecture
Agents
- Single binary written in Go
- Run on every node in the network
- Can operate as servers or clients
- Run DNS and HTTP interfaces
- Responsible for
	- running checks
- keeping services in sync
 
Clients
- Forward RPCs to servers
- Participate in LAN gossip protocol
- Consume minimal resources and bandwidth
Servers
- Operate as Clustered, Distributed Architecture
	- PLOS: 1 cluster of 3 servers (SOMA)
 
- Maintain cluster state
- Respond to queries
- Exchange WAN gossip (not used at PLOS)
- Forward queries to leaders or remote DCs
Consensus
- Agreement upon the Elected Leader
- Agreement on Ordering of Transactions
- Consistency of Replicated State Machine
- Implements Raft Protocol
- Implementation Notes
Gossip
- Node-to-Node communication
- Provides
	- Membership
- Failure Detection
- Event Broadcast
 
- Implements Serf Protocol
- Gossip Documentation

Service Discovery
the automatic detection of devices and services offered by these devices on a computer network
Advertising a Service
- Drop a json file in /etc/consul.d
{
    "service": {
        "checks": [
            {
                "http": "http://solr-210.soma.plos.org:8983/solr",
                "interval": "10s",
                "timeout": "5s"
            }
        ],
        "name": "solr",
        "port": 8983,
        "tags": [
            "dev",
            "cluster=solr-mini"
        ]
    }
}Advertising a Service
- Tip: use file.serialize salt state
solr-advertise:
  file.serialize:
    - name: /etc/consul.d/solr.json
    - formatter: json
    - dataset:
        service:
          name: solr
          port: {{ solr_port }}
          checks:
            - http: 'http://{{ hostname }}:8983/solr'
              interval: 10s
              timeout: 5s
          tags:
            - {{ environment }}
            - cluster={{ cluster }}
Service Discovery APIs
- Command Line
	- 'consul node [...]'
- 'consul catalog [...]'
- 'consul service [...]'
 
- REST
	- listens on localhost:8500 on every node
- e.g. 'curl -sS localhost:8500/v1/[...]'
 
- DNS
	- listens on localhost:8600 on every node
- e.g. 'dig @localhost -p 8600 [...]'
 
Discovering Services: CLI
chaumes@ops-admin-201:~$ consul catalog nodes -service=solr
Node      ID        Address    DC
solr-110  b53e5afd  10.5.3.64  soma
solr-111  5a1dc5a2  10.5.3.68  soma
solr-120  e1058eb7  10.5.2.2   soma
solr-121  b17a2d57  10.5.2.3   soma
solr-122  34074129  10.5.2.4   soma
solr-123  6944d721  10.5.2.5   soma
solr-124  88245dec  10.5.2.6   soma
solr-125  4dca2a93  10.5.2.7   soma
solr-126  9584d894  10.5.2.8   soma
solr-127  de640708  10.5.2.9   soma
solr-210  b94b9aa0  10.5.4.88  soma
solr-211  bbb9c4c9  10.5.4.89  soma
solr-220  2818b2af  10.5.4.2   soma
solr-221  42359f86  10.5.4.3   soma
solr-222  51322276  10.5.4.4   soma
solr-223  3bbabeb3  10.5.4.5   soma
solr-224  9351dc84  10.5.4.6   soma
solr-225  028c8e97  10.5.4.7   soma
solr-226  a74090ac  10.5.4.8   soma
solr-227  e91b0761  10.5.4.9   somaDiscovering Services: HTTP
chaumes@ops-admin-201:~$ curl -sS 'http://localhost:8500/v1/catalog/service/solr?tag=prod' | jq .
[
    {
        "Address": "10.5.3.64",
        "CreateIndex": 6348285,
        "Datacenter": "soma",
        "ID": "b53e5afd-1b9d-8a3a-a012-060a2429c08d",
        "ModifyIndex": 6348285,
        "Node": "solr-110",
        "NodeMeta": {
            "consul-network-segment": ""
        },
        "ServiceAddress": "",
        "ServiceEnableTagOverride": false,
        "ServiceID": "solr",
        "ServiceName": "solr",
        "ServicePort": 8983,
        "ServiceTags": [
            "prod",
            "cluster=solr-mini"
        ],
        "TaggedAddresses": {
            "lan": "10.5.3.64",
            "wan": "10.5.3.64"
        }
    },
    { ... }
]Discovering Services: DNS
chaumes@ops-admin-201:~$ dig @localhost -p 8600 prod.solr.service.consul
; <<>> DiG 9.9.5-3ubuntu0.17-Ubuntu <<>> @localhost -p 8600 prod.solr.service.consul
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32640
;; flags: qr aa rd; QUERY: 1, ANSWER: 10, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;prod.solr.service.consul.	IN	A
;; ANSWER SECTION:
prod.solr.service.consul. 0	IN	A	10.5.2.3
prod.solr.service.consul. 0	IN	A	10.5.3.64
prod.solr.service.consul. 0	IN	A	10.5.2.9
prod.solr.service.consul. 0	IN	A	10.5.2.7
prod.solr.service.consul. 0	IN	A	10.5.2.4
prod.solr.service.consul. 0	IN	A	10.5.2.6
prod.solr.service.consul. 0	IN	A	10.5.2.5
prod.solr.service.consul. 0	IN	A	10.5.3.68
prod.solr.service.consul. 0	IN	A	10.5.2.8
prod.solr.service.consul. 0	IN	A	10.5.2.2
;; Query time: 14 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Fri Sep 21 15:47:31 PDT 2018
;; MSG SIZE  rcvd: 213Prepared Queries
chaumes@ops-admin-201:~$ cat prep.json
{
  "Name": "solr-mega-dev",
  "Service": {
    "Service": "solr",
    "Tags": ["dev", "cluster=solr-mega"],
  }
}
chaumes@ops-admin-201:~$ curl -X POST -d @prep.json localhost:8500/v1/query
{"ID":"3cab98ae-529a-6f2e-04a5-a88c347c6444"}
chaumes@ops-admin-201:~$ curl -sS localhost:8500/v1/query | jq .[].ID
"3cab98ae-529a-6f2e-04a5-a88c347c6444"
- Create more complex queries
- Save queries for reuse
- Managed via REST API
Prepared Queries
chaumes@ops-admin-201:~$ curl -sS \
> 'http://localhost:8500/v1/query/3cab98ae-529a-6f2e-04a5-a88c347c6444/execute' \
> | jq .Nodes[]?.Node.Node
"solr-226"
"solr-222"
"solr-220"
"solr-221"
"solr-223"
"solr-225"
"solr-224"
"solr-227"
chaumes@ops-admin-201:~$ curl -sS \
> 'http://localhost:8500/v1/query/3cab98ae-529a-6f2e-04a5-a88c347c6444/execute' \
> | jq .Nodes[]?.Node.Address
"10.5.4.5"
"10.5.4.6"
"10.5.4.8"
"10.5.4.3"
"10.5.4.4"
"10.5.4.7"
"10.5.4.9"
"10.5.4.2"Prepared Queries
chaumes@ops-admin-201:~$ dig @localhost -p 8600 solr-mega-dev.query.consul SRV
; <<>> DiG 9.9.5-3ubuntu0.17-Ubuntu <<>> @localhost -p 8600 solr-mega-dev.query.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22472
;; flags: qr aa rd; QUERY: 1, ANSWER: 8, AUTHORITY: 0, ADDITIONAL: 17
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;solr-mega-dev.query.consul.	IN	SRV
;; ANSWER SECTION:
solr-mega-dev.query.consul. 0	IN	SRV	1 1 8983 solr-220.node.soma.consul.
solr-mega-dev.query.consul. 0	IN	SRV	1 1 8983 solr-221.node.soma.consul.
solr-mega-dev.query.consul. 0	IN	SRV	1 1 8983 solr-224.node.soma.consul.
solr-mega-dev.query.consul. 0	IN	SRV	1 1 8983 solr-226.node.soma.consul.
solr-mega-dev.query.consul. 0	IN	SRV	1 1 8983 solr-227.node.soma.consul.
solr-mega-dev.query.consul. 0	IN	SRV	1 1 8983 solr-223.node.soma.consul.
solr-mega-dev.query.consul. 0	IN	SRV	1 1 8983 solr-222.node.soma.consul.
solr-mega-dev.query.consul. 0	IN	SRV	1 1 8983 solr-225.node.soma.consul.
Distributed
Key-Value Store
Useful For
- Dynamic Configuration
- Service Coordination
- Leader Election
- Much more!
Key-Value APIs
- Consul CLI
- REST/HTTP
Key-Value CLI
chaumes@ops-admin-201:~$ consul kv put foo/bar baz
Success! Data written to: foo/bar
chaumes@ops-admin-201:~$ consul kv put foo/xyz 123
Success! Data written to: foo/xyz
chaumes@ops-admin-201:~$ consul kv put bar/foo bat
Success! Data written to: bar/foo
chaumes@ops-admin-201:~$ consul kv get -recurse
bar/foo:bat
foo/bar:baz
foo/xyz:123
chaumes@ops-admin-201:~$ consul kv get bar/foo
bat
chaumes@ops-admin-201:~$ consul kv get -recurse foo
foo/bar:baz
foo/xyz:123
chaumes@ops-admin-201:~$ consul kv delete bar/foo
Success! Deleted key: bar/foo
chaumes@ops-admin-201:~$ consul kv delete -recurse foo
Success! Deleted keys with prefix: foo
chaumes@ops-admin-201:~$ consul kv get
chaumes@ops-admin-201:~$ consul kv get -recurse
chaumes@ops-admin-201:~$Key-Value REST
chaumes@ops-admin-201:~$ curl -X PUT localhost:8500/v1/kv/foo/bar -d '{"value": "bat"}'
true
chaumes@ops-admin-201:~$ curl -sS localhost:8500/v1/kv/foo/bar | jq .
[
  {
    "LockIndex": 0,
    "Key": "foo/bar",
    "Flags": 0,
    "Value": "eyJ2YWx1ZSI6ICJiYXQifQ==",
    "CreateIndex": 8434456,
    "ModifyIndex": 8434456
  }
]
chaumes@ops-admin-201:~$ curl -sS localhost:8500/v1/kv/foo/bar | jq -r .[].Value | base64 -d
{"value": "bat"}
chaumes@ops-admin-201:~$ curl -X DELETE localhost:8500/v1/kv/foo/bar
true
chaumes@ops-admin-201:~$ curl -sS localhost:8500/v1/kv/foo/bar | jq .
chaumes@ops-admin-201:~$
Live Templating
- Populate variables in a file from Consul data
	- Service Discovery Catalog
- K/V Store
- Vault
 
- Automatically restart service when values change
- Coming to PLOS in Q4 2018
Service Mesh
- Secure Service-to-Service Communication
- Automatic TLS Encryption
	- Automated certificate management and rotation
 
- Identity-Based Authorization via Intentions
- No Need to Change Existing Code
	- Connect via Proxy Sidecars
 
- Highly-Available & Distributed Architecture
- Beta Feature in Consul 1.2
- Coming to PLOS in Q1/Q2 2019
Access Controls
- Capability-Based Security
- Tokens are Tied to Capabilities
- Every Token Has:
	- Identifier
- Name
- Type
- Ruleset
 
- Managed via API
- Ops is Currently Developing Best Practices & Docs
Implementation Timeline
- Service Discovery: Implemented
- K/V Store: Implemented
	- Best Practices Guide and ACL Advice coming Q4 2018
 
- Live Templating: Coming Q4 2018
- Service Mesh: Coming Q1 2019
consul service discovery
By wryfi
consul service discovery
- 196
