github.com/outbrain/consul@v1.4.5/website/source/docs/guides/leader-election.html.md (about) 1 --- 2 layout: "docs" 3 page_title: "Leader Election" 4 sidebar_current: "docs-guides-leader" 5 description: |- 6 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. 7 --- 8 9 # Leader Election 10 11 This guide describes how to build client-side leader election using Consul. If you 12 are interested in the leader election used internally by Consul, please refer to the 13 [consensus protocol](/docs/internals/consensus.html) documentation instead. 14 15 There are a number of ways that leader election can be built, so our goal is not to 16 cover all the possible methods. Instead, we will focus on using Consul's support for 17 [sessions](/docs/internals/sessions.html). Sessions allow us to build a system that 18 can gracefully handle failures. 19 20 -> **Note:** JSON output in this guide has been pretty-printed for easier reading. Actual values returned from the API will not be formatted. 21 22 ## Contending Nodes 23 24 Let's imagine we have a set of nodes who are attempting to acquire leadership 25 for a given service. All nodes that are participating should agree on a given 26 key to coordinate. A good pattern is simply: 27 28 ```text 29 service/<service name>/leader 30 ``` 31 32 We'll abbreviate this pattern as simply `<key>` for the rest of this guide. 33 34 The first step is to create a session using the 35 [Session HTTP API](/api/session.html#session_create): 36 37 ```text 38 curl -X PUT -d '{"Name": "dbservice"}' \ 39 http://localhost:8500/v1/session/create 40 ``` 41 42 This will return a JSON object containing the session ID: 43 44 ```text 45 { 46 "ID": "4ca8e74b-6350-7587-addf-a18084928f3c" 47 } 48 ``` 49 50 The next step is to acquire a session for a given key from this node 51 using the PUT method on a [KV entry](/api/kv.html) with the 52 `?acquire=<session>` query parameter. The `<body>` of the PUT should be a 53 JSON object representing the local node. This value is opaque to 54 Consul, but it should contain whatever information clients require to 55 communicate with your application (e.g., it could be a JSON object 56 that contains the node's name and the application's port). 57 58 Attempt to `acquire` the `<key>`. This will look something like (note that 59 `<session>` is the ID returned by the call to 60 [`/v1/session/create`](/api/session.html#session_create)): 61 62 ```text 63 curl -X PUT -d <body> http://localhost:8500/v1/kv/<key>?acquire=<session> 64 ``` 65 66 This will either return `true` or `false`. If `true`, the lock has been acquired and 67 the local node is now the leader. If `false` is returned, some other node has acquired 68 the lock. 69 70 All nodes now remain in an idle waiting state. In this state, we watch for changes 71 on `<key>`. This is because the lock may be released, the node may fail, etc. 72 The leader must also watch for changes since its lock may be released by an operator 73 or automatically released due to a false positive in the failure detector. 74 75 By default, the session makes use of only the gossip failure detector. That 76 is, the session is considered held by a node as long as the default Serf health check 77 has not declared the node unhealthy. Additional checks can be specified if desired. 78 79 Watching for changes is done via a blocking query against `<key>`. If we ever 80 notice that the `Session` of the `<key>` is blank, there is no leader, and we should 81 retry lock acquisition. Each attempt to acquire the key should be separated by a timed 82 wait. This is because Consul may be enforcing a [`lock-delay`](/docs/internals/sessions.html). 83 84 If the leader ever wishes to step down voluntarily, this should be done by simply 85 releasing the lock: 86 87 ```text 88 curl -X PUT http://localhost:8500/v1/kv/<key>?release=<session> 89 ``` 90 91 ## Discovering a Leader 92 93 Another common practice regarding leader election is for nodes to wish to identify the 94 leader for a given service. 95 96 As with leader election, all nodes that are participating should agree on the key 97 being used to coordinate. This key will be referred to as just `key`. 98 99 Clients have a very simple role, they simply read `<key>` to discover who the current 100 leader is: 101 102 ```text 103 curl http://localhost:8500/v1/kv/<key> 104 [ 105 { 106 "Session": "4ca8e74b-6350-7587-addf-a18084928f3c", 107 "Value": "Ym9keQ==", 108 "Flags": 0, 109 "Key": "<key>", 110 "LockIndex": 1, 111 "ModifyIndex": 29, 112 "CreateIndex": 29 113 } 114 ] 115 ``` 116 117 If the key has no associated `Session`, then there is no leader. 118 Otherwise, the value of the key will provide all the 119 application-dependent information required as a Base64 encoded blob in 120 the `Value` field. 121 122 You can query the 123 [`/v1/session/info`](/api/session.html#session_info) 124 endpoint to get details about the session: 125 126 ```text 127 curl http://localhost:8500/v1/session/info/4ca8e74b-6350-7587-addf-a18084928f3c 128 [ 129 { 130 "LockDelay": 1.5e+10, 131 "Checks": [ 132 "serfHealth" 133 ], 134 "Node": "consul-primary-bjsiobmvdij6-node-lhe5ihreel7y", 135 "Name": "dbservice", 136 "ID": "4ca8e74b-6350-7587-addf-a18084928f3c", 137 "CreateIndex": 28 138 } 139 ] 140 ``` 141 142 Clients should also watch the key using a blocking query for any 143 changes. If the leader steps down or fails, the `Session` associated 144 with the key will be cleared. When a new leader is elected, the key 145 value will also be updated. 146 147 Using the `acquire` param is optional. This means 148 that if you use leader election to update a key, you must not update the key 149 without the acquire parameter.