Soa with consul

Post on 13-Apr-2017

58 views 0 download

transcript

Service Oriented Architecturewith Consul

Rajesh Sharma

@broncha

VantageBit

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?