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.