[docs] Leader Election Guide Updates (#5654)

* Updating the Leader Election guide.

* Update website/source/docs/guides/leader-election.html.md

* updating key name

* Update website/source/docs/guides/leader-election.html.md

Co-Authored-By: kaitlincarter-hc <43049322+kaitlincarter-hc@users.noreply.github.com>

* Update website/source/docs/guides/leader-election.html.md

Co-Authored-By: kaitlincarter-hc <43049322+kaitlincarter-hc@users.noreply.github.com>
This commit is contained in:
kaitlincarter-hc 2019-04-17 16:16:15 -05:00 committed by GitHub
parent 6cbd67f9df
commit 64a2e486f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 68 additions and 54 deletions

View File

@ -1,74 +1,83 @@
--- ---
layout: "docs" layout: "docs"
page_title: "Leader Election" page_title: "Application Leader Election with Sessions"
sidebar_current: "docs-guides-leader" sidebar_current: "docs-guides-leader"
description: |- description: |-
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. 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.
--- ---
# Leader Election # Application Leader Election with Sessions
This guide describes how to build client-side leader election using Consul. If you For some applications, like HDFS, it is necessary to set one instance as
a leader. This ensures the application data is current and stable.
This guide describes how to build client-side leader elections for service
instances, using Consul. Consul's support for
[sessions](/docs/internals/sessions.html) allows you to build a system that can gracefully handle failures.
If you
are interested in the leader election used internally by Consul, please refer to the are interested in the leader election used internally by Consul, please refer to the
[consensus protocol](/docs/internals/consensus.html) documentation instead. [consensus protocol](/docs/internals/consensus.html) documentation instead.
There are a number of ways that leader election can be built, so our goal is not to ## Contending Service Instances
cover all the possible methods. Instead, we will focus on using Consul's support for
[sessions](/docs/internals/sessions.html). Sessions allow us to build a system that
can gracefully handle failures.
-> **Note:** JSON output in this guide has been pretty-printed for easier reading. Actual values returned from the API will not be formatted. Imagine you have a set of MySQL service instances who are attempting to acquire leadership. All service instances that are participating should agree on a given
## Contending Nodes
Let's imagine we have a set of nodes who are attempting to acquire leadership
for a given service. All nodes that are participating should agree on a given
key to coordinate. A good pattern is simply: key to coordinate. A good pattern is simply:
```text ```text
service/<service name>/leader service/<service name>/leader
``` ```
We'll abbreviate this pattern as simply `<key>` for the rest of this guide. This key will be used for all requests to the Consul KV API.
The first step is to create a session using the We will use the same, simple pattern for the MySQL services for the remainder of the guide.
[Session HTTP API](/api/session.html#session_create):
```text ```text
curl -X PUT -d '{"Name": "dbservice"}' \ service/mysql/leader
http://localhost:8500/v1/session/create ```
```
### Create a Session
The first step is to create a session using the
[Session HTTP API](/api/session.html#session_create).
```sh
$ curl -X PUT -d '{"Name": "mysql-session"}' http://localhost:8500/v1/session/create
```
This will return a JSON object containing the session ID: This will return a JSON object containing the session ID:
```text ```json
{ {
"ID": "4ca8e74b-6350-7587-addf-a18084928f3c" "ID": "4ca8e74b-6350-7587-addf-a18084928f3c"
} }
``` ```
The next step is to acquire a session for a given key from this node ### Acquire a Session
The next step is to acquire a session for a given key from this instance
using the PUT method on a [KV entry](/api/kv.html) with the using the PUT method on a [KV entry](/api/kv.html) with the
`?acquire=<session>` query parameter. The `<body>` of the PUT should be a `?acquire=<session>` query parameter.
JSON object representing the local node. This value is opaque to
The `<body>` of the PUT should be a
JSON object representing the local instance. This value is opaque to
Consul, but it should contain whatever information clients require to Consul, but it should contain whatever information clients require to
communicate with your application (e.g., it could be a JSON object communicate with your application (e.g., it could be a JSON object
that contains the node's name and the application's port). that contains the node's name and the application's port).
Attempt to `acquire` the `<key>`. This will look something like (note that ```sh
`<session>` is the ID returned by the call to $ curl -X PUT -d <body> http://localhost:8500/v1/kv/service/mysql/leader?acquire=4ca8e74b-6350-7587-addf-a18084928f3c
[`/v1/session/create`](/api/session.html#session_create)):
```text
curl -X PUT -d <body> http://localhost:8500/v1/kv/<key>?acquire=<session>
``` ```
This will either return `true` or `false`. If `true`, the lock has been acquired and 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 local service instance is now the leader. If `false` is returned, some other node has acquired
the lock. the lock.
All nodes now remain in an idle waiting state. In this state, we watch for changes ### Watch the Session
on `<key>`. This is because the lock may be released, the node may fail, etc.
All instances now remain in an idle waiting state. In this state, they watch for changes
on the key `service/mysql/leader`. This is because the lock may be released or the instance could fail, etc.
The leader must also watch for changes since its lock may be released by an operator The leader must also watch for changes since its lock may be released by an operator
or automatically released due to a false positive in the failure detector. or automatically released due to a false positive in the failure detector.
@ -76,37 +85,38 @@ By default, the session 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 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. 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 Watching for changes is done via a blocking query against the key. If they ever
notice that the `Session` of the `<key>` is blank, there is no leader, and we should notice that the `Session` field in the response is blank, there is no leader, and then should
retry lock acquisition. Each attempt to acquire the key should be separated by a timed retry lock acquisition. Each attempt to acquire the key should be separated by a timed
wait. This is because Consul may be enforcing a [`lock-delay`](/docs/internals/sessions.html). wait. This is because Consul may be enforcing a [`lock-delay`](/docs/internals/sessions.html).
### Release the Session
If the leader ever wishes to step down voluntarily, this should be done by simply If the leader ever wishes to step down voluntarily, this should be done by simply
releasing the lock: releasing the lock:
```text ```sh
curl -X PUT http://localhost:8500/v1/kv/<key>?release=<session> $ curl -X PUT http://localhost:8500/v1/kv/service/mysql/leader?release=4ca8e74b-6350-7587-addf-a18084928f3c
``` ```
## Discovering a Leader ## Discover the Leader
Another common practice regarding leader election is for nodes to wish to identify the It is possible to identify the leader of a set of service instances participating in the election process.
leader for a given service.
As with leader election, all nodes that are participating should agree on the key As with leader election, all instances that are participating should agree on the key being used to coordinate.
being used to coordinate. This key will be referred to as just `key`.
Clients have a very simple role, they simply read `<key>` to discover who the current ### Retrieve the Key
leader is:
```text Instances have a very simple role, they simply read the Consul KV key to discover the current leader. If the key has an associated `Session`, then there is a leader.
curl http://localhost:8500/v1/kv/<key>
```sh
$ curl -X GET http://localhost:8500/v1/kv/service/mysql/leader
[ [
{ {
"Session": "4ca8e74b-6350-7587-addf-a18084928f3c", "Session": "4ca8e74b-6350-7587-addf-a18084928f3c",
"Value": "Ym9keQ==", "Value": "Ym9keQ==",
"Flags": 0, "Flags": 0,
"Key": "<key>", "Key": "service/mysql/leader",
"LockIndex": 1, "LockIndex": 1,
"ModifyIndex": 29, "ModifyIndex": 29,
"CreateIndex": 29 "CreateIndex": 29
@ -114,17 +124,18 @@ curl http://localhost:8500/v1/kv/<key>
] ]
``` ```
If the key has no associated `Session`, then there is no leader. If there is a leader then the value of the key will provide all the
Otherwise, the value of the key will provide all the
application-dependent information required as a Base64 encoded blob in application-dependent information required as a Base64 encoded blob in
the `Value` field. the `Value` field.
### Retrieve Session Information
You can query the You can query the
[`/v1/session/info`](/api/session.html#session_info) [`/v1/session/info`](/api/session.html#session_info)
endpoint to get details about the session: endpoint to get details about the session
```text ```sh
curl http://localhost:8500/v1/session/info/4ca8e74b-6350-7587-addf-a18084928f3c $ curl -X GET http://localhost:8500/v1/session/info/4ca8e74b-6350-7587-addf-a18084928f3c
[ [
{ {
"LockDelay": 1.5e+10, "LockDelay": 1.5e+10,
@ -132,18 +143,21 @@ curl http://localhost:8500/v1/session/info/4ca8e74b-6350-7587-addf-a18084928f3c
"serfHealth" "serfHealth"
], ],
"Node": "consul-primary-bjsiobmvdij6-node-lhe5ihreel7y", "Node": "consul-primary-bjsiobmvdij6-node-lhe5ihreel7y",
"Name": "dbservice", "Name": "mysql-session",
"ID": "4ca8e74b-6350-7587-addf-a18084928f3c", "ID": "4ca8e74b-6350-7587-addf-a18084928f3c",
"CreateIndex": 28 "CreateIndex": 28
} }
] ]
``` ```
Clients should also watch the key using a blocking query for any ## Summary
In this guide you used a session to initiate manual leader election for a
set of service instances. To fully benefit from this process, instances should also watch the key using a blocking query for any
changes. If the leader steps down or fails, the `Session` associated changes. If the leader steps down or fails, the `Session` associated
with the key will be cleared. When a new leader is elected, the key with the key will be cleared. When a new leader is elected, the key
value will also be updated. value will also be updated.
Using the `acquire` param is optional. This means Using the `acquire` parameter is optional. This means
that if you use leader election to update a key, you must not update the key that if you use leader election to update a key, you must not update the key
without the acquire parameter. without the acquire parameter.