2014-05-20 19:22:16 +00:00
---
layout: "docs"
page_title: "Leader Election"
sidebar_current: "docs-guides-leader"
2014-10-19 23:40:10 +00:00
description: |-
2015-02-28 05:08:41 +00:00
This guide describes how to build client-side leader election using Consul. If you are interested in the leader election used internally to Consul, please refer to the consensus protocol documentation instead.
2014-05-20 19:22:16 +00:00
---
# Leader Election
2015-02-28 05:08:41 +00:00
This guide describes how to build client-side leader election using Consul. If you
are interested in the leader election used internally by Consul, please refer to the
[consensus protocol ](/docs/internals/consensus.html ) documentation instead.
2014-05-20 19:22:16 +00:00
There are a number of ways that leader election can be built, so our goal is not to
cover all the possible methods. Instead, we will focus on using Consul's support for
2015-02-28 05:08:41 +00:00
[sessions ](/docs/internals/sessions.html ). Sessions allow us to build a system that
can gracefully handle failures.
2014-05-20 19:22:16 +00:00
2014-12-05 19:09:45 +00:00
Note that JSON output in this guide has been pretty-printed for easier
reading. Actual values returned from the API will not be formatted.
2014-05-20 19:22:16 +00:00
## Contending Nodes
2015-02-28 05:08:41 +00:00
Let's imagine we have a set of nodes who are attempting to acquire leadership
2014-05-20 19:22:16 +00:00
for a given service. All nodes that are participating should agree on a given
2015-02-28 05:08:41 +00:00
key to coordinate. A good pattern is simply:
2014-05-20 19:22:16 +00:00
2014-10-19 23:40:10 +00:00
```text
service/< service name > /leader
```
2014-05-20 19:22:16 +00:00
2015-02-28 05:08:41 +00:00
We'll abbreviate this pattern as simply `<key>` for the rest of this guide.
2014-12-05 19:09:45 +00:00
2015-02-28 05:08:41 +00:00
The first step is to create a session using the
[Session HTTP API ](/docs/agent/http/session.html#session_create ):
2014-12-05 19:09:45 +00:00
```text
curl -X PUT -d '{"Name": "dbservice"}' \
http://localhost:8500/v1/session/create
```
2015-02-28 05:08:41 +00:00
This will return a JSON object containing the session ID:
2014-12-05 19:09:45 +00:00
```text
{
"ID": "4ca8e74b-6350-7587-addf-a18084928f3c"
}
```
2014-05-20 19:22:16 +00:00
2015-02-28 05:08:41 +00:00
The next step is to acquire a session for a given key from this node
using the PUT method on a [KV entry ](/docs/agent/http/kv.html ) with the
"?acquire=\<session\>" query parameter. The `<body>` of the PUT should be a
JSON object representing the local node. This value is opaque to
Consul, but it should contain whatever information clients require to
2014-12-05 19:09:45 +00:00
communicate with your application (e.g., it could be a JSON object
that contains the node's name and the application's port).
2014-05-20 19:22:16 +00:00
2015-02-28 05:08:41 +00:00
Attempt to `acquire` the `<key>` . This will look something like (note that
`<session>` is the ID returned by the call to
[`/v1/session/create` ](/docs/agent/http/session.html#session_create )):
2014-05-20 19:22:16 +00:00
2014-10-19 23:40:10 +00:00
```text
2014-12-05 19:09:45 +00:00
curl -X PUT -d < body > http://localhost:8500/v1/kv/< key > ?acquire=< session >
2014-10-19 23:40:10 +00:00
```
2014-05-20 19:22:16 +00:00
2015-02-28 05:08:41 +00:00
This will either return `true` or `false` . If `true` , the lock has been acquired and
the local node is now the leader. If `false` is returned, some other node has acquired
the lock.
2014-05-20 19:22:16 +00:00
All nodes now remain in an idle waiting state. In this state, we watch for changes
2014-12-05 19:09:45 +00:00
on `<key>` . This is because the lock may be released, the node may fail, etc.
2015-02-28 05:08:41 +00:00
The leader must also watch for changes since its lock may be released by an operator
2014-05-20 19:22:16 +00:00
or automatically released due to a false positive in the failure detector.
2015-02-28 05:08:41 +00:00
Note that the session by default makes use of only the gossip failure detector. That
is, the session is considered held by a node as long as the default Serf health check
has not declared the node unhealthy. Additional checks can be specified if desired.
Watching for changes is done via a blocking query against `<key>` . If we ever
notice that the `Session` of the `<key>` is blank, there is no leader, and we should
retry lock acquisition. Each attempt to acquire the key should be separated by a timed
2014-05-20 19:22:16 +00:00
wait. This is because Consul may be enforcing a [`lock-delay` ](/docs/internals/sessions.html ).
If the leader ever wishes to step down voluntarily, this should be done by simply
releasing the lock:
2014-10-19 23:40:10 +00:00
```text
2014-12-05 19:09:45 +00:00
curl -X PUT http://localhost:8500/v1/kv/< key > ?release=< session >
2014-10-19 23:40:10 +00:00
```
2014-05-20 19:22:16 +00:00
## Discovering a Leader
2015-02-28 05:08:41 +00:00
Another common practice regarding leader election is for nodes to wish to identify the
leader for a given service.
As with leader leader election, all nodes that are participating should agree on the key
being used to coordinate. This key will be referred to as just `key` .
2014-05-20 19:22:16 +00:00
2014-12-05 19:09:45 +00:00
Clients have a very simple role, they simply read `<key>` to discover who the current
leader is:
```text
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
}
]
```
2015-02-28 05:08:41 +00:00
If the key has no associated `Session` , then there is no leader. Otherwise, the value of
the key will provide all the application-dependent information required as a Base64 encoded
blob in the `Value` field.
You can query the [`/v1/session/info` ](/docs/agent/http/session.html#session_info ) endpoint
to get details about the session:
2014-12-05 19:09:45 +00:00
```text
curl http://localhost:8500/v1/session/info/4ca8e74b-6350-7587-addf-a18084928f3c
[
{
"LockDelay": 1.5e+10,
"Checks": [
"serfHealth"
],
"Node": "consul-master-bjsiobmvdij6-node-lhe5ihreel7y",
"Name": "dbservice",
"ID": "4ca8e74b-6350-7587-addf-a18084928f3c",
"CreateIndex": 28
}
]
```
2014-05-20 19:22:16 +00:00
Clients should also watch the key using a blocking query for any changes. If the leader
2015-02-28 05:08:41 +00:00
steps down or fails, the `Session` associated with the key will be cleared. When
2014-05-20 19:22:16 +00:00
a new leader is elected, the key value will also be updated.