Skip to content

Commit

Permalink
Update documentation for Leader Election
Browse files Browse the repository at this point in the history
Specifically mention the new SSE API
  • Loading branch information
mortenlj committed Aug 22, 2024
1 parent fdc1bb8 commit 79b17f9
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 13 deletions.
24 changes: 16 additions & 8 deletions docs/services/leader-election/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,23 @@ This is done by asking the [elector container](https://github.com/nais/elector)
The leader election configuration does not control which pod the external service requests will be routed to.

## Elector sidecar

When you [enable leader election](how-to/enable.md), NAIS will inject an elector container as a sidecar into your pod.

When you have the `elector` container running in your pod,
you can make a HTTP GET to the URL set in environment variable `$ELECTOR_PATH` to see which pod is the leader.
This will return a JSON object with the name of the leader,
which you can now compare with your hostname.
### Simple API

The environment variable `$ELECTOR_GET_URL` contains a URL that can be used to `GET` the current leader.
Previously, the environment variable `$ELECTOR_PATH`[^1] was used for this API, and it is still available for backwards compatibility.

The simple API returns a JSON object with the name of the leader, which you can now compare with your hostname.

[^1]: Contains only hostname and port, without the protocol. E.g. `localhost:4040`.

### Server Sent Events API

The environment variable `$ELECTOR_SSE_URL` contains a URL that can be used to subscribe to leadership changes using Server Sent Events.

This will emit an event whenever there are changes to leadership, and you can use this to update your application accordingly.

## Caveats

Expand All @@ -26,8 +37,5 @@ which you can now compare with your hostname.
The only way for a leader to lose leadership is to be deleted from the cluster.
**We recommend that you create alerts to detect when your leader is not doing its job, so that you can intervene.**

* Participants in an election need to poll the `$ELECTOR_PATH` to be informed of changes in leadership.
There is no push mechanism in place to inform your application about changes.
* When using the simple API the application needs to poll the API at regular intervals to be informed of changes in leadership.
This means your application needs to check at reasonable intervals for changes in leadership.
NB: `$ELECTOR_PATH` is the raw ip string without the protocol i.e localhost:4040 so be aware
of this and make sure to specify this in your http-client.
50 changes: 45 additions & 5 deletions docs/services/leader-election/how-to/enable.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ This guide will show you how to enable leader election for your application.
leaderElection: true
```

## Using leader election in your application
## Using leader election in your application (simple API)

=== "java"
=== "Java"

```java
// Implementation of getJSONFromUrl is left as an exercise for the reader
class Leader {
public static boolean isLeader() {
String electorPath = System.getenv("ELECTOR_PATH");
JSONObject leaderJson = getJSONFromUrl(electorPath);
String electorUrl = System.getenv("ELECTOR_GET_URL");
JSONObject leaderJson = getJSONFromUrl(electorUrl);
String leader = leaderJson.getString("name");
String hostname = InetAddress.getLocalHost().getHostname();

Expand All @@ -37,6 +37,46 @@ This guide will show you how to enable leader election for your application.

```bash
$ kubectl exec -it elector-sidecar-755b7c5795-7k2qn -c debug bash
root@elector-sidecar-755b7c5795-7k2qn:/# curl $ELECTOR_PATH
root@elector-sidecar-755b7c5795-7k2qn:/# curl ${ELECTOR_GET_URL}
{"name":"elector-sidecar-755b7c5795-2kcm7","last_update":"2022-10-18T10:59:58Z"}
```

=== "Python"

```python
import os
import socket
import requests

def is_leader():
elector_url = os.getenv("ELECTOR_GET_URL")
resp = requests.get(elector_url)
leader = resp.json()["name"]
return socket.gethostname() == leader
```

=== "TypeScript"

```typescript
import * as os from 'node:os'

export async function isLeader(): Promise<boolean> {
const hostname = os.hostname()
const electorUrl = process.env.ELECTOR_GET_URL

const electorResponse = await fetch(electorUrl)
if (!electorResponse.ok) {
throw new Error(
`Failed to fetch leader from ${electorUrl}, response: ${electorResponse.status} ${electorResponse.statusText}`,
)
}
const result: { name: string; last_update: string } = await electorResponse.json()

return result.name === hostname
}
```


## Using leader election in your application (Server Sent Events API)

:construction_worker: Help Wanted! Please contribute with examples on how to use the Server Sent Events API.

0 comments on commit 79b17f9

Please sign in to comment.