1

I am building a cloud stack using consul for service discovery, but I've hit a wall, so I ask the people of internet about that.

What I do want to do is registering a service in consul from multiple hosts, but return only one of them for all of the queries while the service is up. To be exact:

  • node A, node B, node C are all capable to provide service X
  • all the nodes are up and running
  • and they all register the service into consul.

In this moment when I query consul for these data I'll get all of the three nodes as answer. I do want to get only one of them, as long as the service is provided by that node, but if not, I'd like to get an another node for all the questions.

To be more exact with an example: I build up an xtradb cluster, and one of the nodes has to replicate from the old datacenter of us. There could be only one, which is replicating in a given moment, but if that node goes down, some of the other nodes have to continue replicating.

I can solve this with an external monitoring host, but that can be a SPOF, so the best would be to put a replication supervising script on all the nodes, which is querying consul about 'am I the responsible host for replication?' and if the answer is yes, then set up replica locally. Theoretically if that node goes down, consul could vote for the new 'replica master' --- and the agent on that node will set up replication.

So, is consul capable of this? If not, is there any other way for achieving this? (We are running on GCP so I can't quorum with disks, or with floating IPs. All the hosts are independent, I need some layer which can have consensus about hosts.) In worst case scenario I'll write this by myself, but it would be better to have a production-ready solution.

1

Assuming you have 3 services running and registered with consul, and a query curl -s 'http://localhost:8500/v1/catalog/service/consul' | jq '' resulting in this

[{
  "Node": "local01-consul0001.local",
  "Address": "192.168.33.11",
  "ServiceID": "consul",
  "ServiceName": "consul",
  "ServiceTags": [
    "master"
  ],
  "ServiceAddress": "",
  "ServicePort": 8300
},
{
  "Node": "local01-consul0002.local",
  "Address": "192.168.33.12",
  "ServiceID": "consul",
  "ServiceName": "consul",
  "ServiceTags": [
    "master"
  ],
  "ServiceAddress": "",
  "ServicePort": 8300
},
{
  "Node": "local01-consul0003.local",
  "Address": "192.168.33.13",
  "ServiceID": "consul",
  "ServiceName": "consul",
  "ServiceTags": [
    "master"
  ],
  "ServiceAddress": "",
  "ServicePort": 8300
}]

Since all are available, you should be able to use the first one in alphanumerical order:

# curl -s  'http://localhost:8500/v1/catalog/service/consul'  | jq '.[0]'
{
  "Node": "local01-consul0001.local",
  "Address": "192.168.33.11",
  "ServiceID": "consul",
  "ServiceName": "consul",
  "ServiceTags": [
    "master"
  ],
  "ServiceAddress": "",
  "ServicePort": 8300
}
2
  • It's a good idea. I don't really like it: there is still 3 different services available at a given moment. I mean, it's really good, but I still see some possibilities to break. – banyek Aug 29 '16 at 22:46
  • (At the end of the day I solved it with consul lock but I still accept your answer.) – banyek Aug 29 '16 at 22:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.