soa with consul
TRANSCRIPT
Problems when you scale aSOA/microservices
Host resolution (service discovery)
Con�guration updates
SolutionsApache zookeeper
etcd
doozerd
consul
ConsulIt is a tool for discovering and con�guring services inyour infrastructure, with features like
Service Discovery
Health Checking
Key/Value Store
InstallationJust download a binary �le and you are good to go.
Con�guration
Server nodescon�g.json
{ "server": true, "data_dir": "/var/consul", "encrypt": "2346rxJm2aFuMNxWCKWnvPBA==", "log_level": "INFO", "enable_syslog": true, "bind_addr": "172.31.0.195", "start_join": ["172.31.12.223", "172.31.28.140"], "ui": true}
Client nodes
con�g.json
{ "server": false, "data_dir": "/var/consul", "encrypt": "2346rxJm2aFuMNxWCKWnvPBA==", "log_level": "INFO", "enable_syslog": true, "bind_addr": "172.31.21.186", "start_join": ["172.31.28.140","172.31.12.223","172.31.0.195"}
services.json
{ "services": [ { "id": "application@ip-172-31-21-186", "name": "application", "address": "172.31.21.186", "port": 8080, "checks": [ { "name": "Application/Apache on port 8080", "tcp": "localhost:8080", "interval": "10s", "timeout": "1s" } ] } ]}
The HTTP Interface
Catalog API
/v1/catalog/nodes
[ { "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", "Node": "baz", "Address": "10.1.10.11", "TaggedAddresses": { "lan": "10.1.10.11", "wan": "10.1.10.11" }, "Meta": { "instance_type": "t2.medium" } } ...]
/v1/catalog/services
{ "consul": [], "redis": [], "postgresql": [ "primary", "secondary" ]}
/v1/catalog/service/<service>
[ { "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", "Node": "foobar", "Address": "192.168.10.10", "Meta": { "instance_type": "t2.medium" }, "CreateIndex": 51, "ModifyIndex": 51, "ServiceAddress": "172.17.0.3", "ServiceEnableTagOverride": false, "ServiceID": "32a2a47f7992:nodea:5000", "ServiceName": "foobar", "ServicePort": 5000, "ServiceTags": [ "tacos" ] }
/v1/catalog/node/<node>
{ "Node": { "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", "Node": "foobar", "Address": "10.1.10.12" }, "Services": { "consul": { "ID": "consul", "Service": "consul", "Port": 8300 }, "redis": { "ID": "redis", "Service": "redis", "Tags": [ "v1" ], "Port": 6379
Health Check API
/v1/health/node/<node>
[ { "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", "Node": "foobar", "CheckID": "serfHealth", "Name": "Serf Health Status", "Status": "passing", "Notes": "", "Output": "", "ServiceID": "", "ServiceName": "" }, { "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", "Node": "foobar", "CheckID": "service:redis", "Name": "Service 'redis' check", "Status": "passing", "Notes": "",
/v1/health/checks/<service>
[ { "Node": "foobar", "CheckID": "service:redis", "Name": "Service 'redis' check", "Status": "passing", "Notes": "", "Output": "", "ServiceID": "redis", "ServiceName": "redis" }]
/v1/health/service/<service>
[ { "Node": { "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", "Node": "foobar", "Address": "10.1.10.12" }, "Service": { "ID": "redis", "Service": "redis", "Tags": null, "Address": "10.1.10.12", "Port": 6379 }, "Checks": [ { "Node": "foobar", "CheckID": "service:redis", "Name": "Service 'redis' check",
/v1/health/service/<service>?passing
[ { "Node": { "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", "Node": "foobar", "Address": "10.1.10.12" }, "Service": { "ID": "redis", "Service": "redis", "Tags": null, "Address": "10.1.10.12", "Port": 6379 }, "Checks": [ { "Node": "foobar", "CheckID": "service:redis", "Name": "Service 'redis' check",
The Key-Value Store API
GET /v1/kv/<key>
[ { "CreateIndex": 100, "ModifyIndex": 200, "LockIndex": 200, "Key": "zip", "Flags": 0, "Value": "dGVzdA==", "Session": "adf4238a-882b-9ddc-4a9d-5b6758e4159e" }]
PUT /v1/kv/<key>
DELETE /v1/kv/<key>
The DNS InterfaceInstead of making HTTP API requests to Consul, ahost can use the DNS server directly via namelookupsredis.service.us-east-1.consul
master.rabbitmq.service.us-east-1.consul
slave.redis.service.consul
Consul will listen on 127.0.0.1:8600 for DNSqueries in the consul. domain
We can use dnsmasq to route DNS queries for consul. domains to 127.0.0.1:8600
Unhealthy nodes are automatically �ltered
Node Lookups
<node>.node[.datacenter].<domain>
$ dig @127.0.0.1 -p 8600 foo.node.consul ANY
; <<>> DiG 9.8.3-P1 <<>> @127.0.0.1 -p 8600 foo.node.consul ANY; (1 server found);; truncating comment sections for brevity
;; QUESTION SECTION:;foo.node.consul. IN ANY
;; ANSWER SECTION:foo.node.consul. 0 IN A 10.1.10.12
;; AUTHORITY SECTION:consul. 0 IN SOA ns.consul. postmaster.consul. 1392836399 3600 600 86400 0
Service Lookups
[tag.]<service>.service[.datacenter].<domain>
$ dig master.redis.service.consul
; <<>> DiG 9.10.3-P4-Ubuntu <<>> master.redis.service.consul;; truncating comment sections for brevity
;; QUESTION SECTION:;master.redis.service.consul. IN A
;; ANSWER SECTION:master.redis.service.consul. 0 IN A 172.31.28.140
;; Query time: 2 msec;; SERVER: 127.0.0.1#53(127.0.0.1);; WHEN: Wed Feb 01 10:36:28 UTC 2017;; MSG SIZE rcvd: 88
Distributed lock and Leaderelection
Pick a key
service/<servicename>/leader`
Create a session
$ curl -X PUT -d '{"Name": "rabbitmq-service"}' \ http://localhost:8500/v1/session/create # response { "ID": "4ca8e74b-6350-7587-addf-a18084928f3c" }
Acquire a session for given key
$ curl -X PUT -d <body> \ http://localhost:8500/v1/kv/<key>?acquire=<session>
If return value is true key was acquired and thisnode is the leader
Else some other node already acquired that keyand is the leader
Other nodes can discover the leader node usingthe session info API
$ curl http://localhost:8500/v1/kv/<key>[ { "Session": "4ca8e74b-6350-7587-addf-a18084928f3c", "Value": "Ym9keQ==", "Flags": 0, "Key": "<key>", "LockIndex": 1, "ModifyIndex": 29, "CreateIndex": 29 }]
If the key has no associated Session, then there isno leader
The nodes would be watching the key to check if itwas released and try to become the leader
$ curl \http://localhost:8500/v1/session/info/4ca8e74b-6350-7587-addf-a18084928f3c[ { "LockDelay": 1.5e+10, "Checks": [ "serfHealth" ], "Node": "consul-primary-bjsiobmvdij6-node-lhe5ihreel7y" "Name": "dbservice", "ID": "4ca8e74b-6350-7587-addf-a18084928f3c", "CreateIndex": 28 }]
Questions?