{"id":19378862,"url":"https://github.com/linbit/k8s-await-election","last_synced_at":"2025-09-05T07:37:23.122Z","repository":{"id":47636790,"uuid":"283519560","full_name":"LINBIT/k8s-await-election","owner":"LINBIT","description":"Start the main process of a pod only if elected via kubernetes leader election. While this was developed for LINSTOR, it may proof useful for other use cases.","archived":false,"fork":false,"pushed_at":"2024-02-14T15:41:32.000Z","size":90,"stargazers_count":70,"open_issues_count":0,"forks_count":3,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-23T19:49:22.181Z","etag":null,"topics":["jobcontrol","kubernetes"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LINBIT.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-29T14:21:42.000Z","updated_at":"2025-03-17T09:36:30.000Z","dependencies_parsed_at":"2024-06-19T10:12:25.274Z","dependency_job_id":null,"html_url":"https://github.com/LINBIT/k8s-await-election","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/LINBIT/k8s-await-election","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LINBIT%2Fk8s-await-election","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LINBIT%2Fk8s-await-election/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LINBIT%2Fk8s-await-election/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LINBIT%2Fk8s-await-election/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LINBIT","download_url":"https://codeload.github.com/LINBIT/k8s-await-election/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LINBIT%2Fk8s-await-election/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273727696,"owners_count":25157132,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-05T02:00:09.113Z","response_time":402,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["jobcontrol","kubernetes"],"created_at":"2024-11-10T09:07:39.412Z","updated_at":"2025-09-05T07:37:18.083Z","avatar_url":"https://github.com/LINBIT.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# k8s-await-election\n\n![Latest release](https://img.shields.io/github/v/release/linbit/k8s-await-election)\n\nEnsure that only a single instance of a process is running in your Kubernetes cluster.\n\n`k8s-await-election` leverages Kubernetes built-in [leader election](https://pkg.go.dev/k8s.io/client-go/tools/leaderelection?tab=doc)\ncapabilities to coordinate commands running in different pods. It acts as a gatekeeper, only\nstarting the command when the pod becomes a leader. \n\n### Why leader election?\nSome applications aren't natively able to run in a replicated way.\nFor example, they maintain some internal state which is only synchronized at the start.\n\nRunning such an application as a single replica is not ideal. Should the node the pod\nis running on go offline unexpectedly, Kubernetes will take its time to reschedule\n(5min+ by default).\n\nLeader election is able to elect a new leader in about 10-15 seconds in such an event.\n\n## Usage\nJust set `k8s-await-election` as entry point into your image. Configuration of the leader election\nhappens via environment variables. If no environment variables were passed, `k8s-await-election` \nwill just start the command without waiting to become elected.\n\nThe relevant environment variables are\n\n| Variable                                | Description                                                       |\n|-----------------------------------------|-------------------------------------------------------------------|\n| `K8S_AWAIT_ELECTION_ENABLED`            | Set to any non-empty value to enable leader election              |\n| `K8S_AWAIT_ELECTION_NAME`               | Name of the election processes. Useful for debugging              |\n| `K8S_AWAIT_ELECTION_LOCK_NAME`          | Name of the `leases.coordination.k8s.io` resource                 |\n| `K8S_AWAIT_ELECTION_LOCK_NAMESPACE`     | Namespace of the  `leases.coordination.k8s.io`  resource          |\n| `K8S_AWAIT_ELECTION_IDENTITY`           | Unique identity for each member of the election process           |\n| `K8S_AWAIT_ELECTION_STATUS_ENDPOINT`    | Optional: endpoint to report if the election process is running   |\n| `K8S_AWAIT_ELECTION_SERVICE_NAME`       | Optional: set the service to update. [On Service Updates]         |\n| `K8S_AWAIT_ELECTION_SERVICE_NAMESPACE`  | Optional: set the service namespace.                              |\n| `K8S_AWAIT_ELECTION_SERVICE_PORTS_JSON` | Optional: set to json array of endpoint ports.                    |\n| `K8S_AWAIT_ELECTION_POD_IP`             | Optional: IP of the pod, which will be used to update the service |\n| `K8S_AWAIT_ELECTION_NODE_NAME`          | Optional: Node name, will be used to update the service           |\n| `K8S_AWAIT_ELECTION_LEASE_DURATION`     | Optional: Time in seconds after which followers will start elections, if a leader did not renew it's claim. Default: 15|\n| `K8S_AWAIT_ELECTION_RENEW_DEADLINE`     | Optional: Time in seconds after which leaders will renew claims. Default: 10 |\n| `K8S_AWAIT_ELECTION_RETRY_PERIOD`       | Optional: Time in seconds after which failed claims are retried. Default: 2 |\n\n[On Service Updates]: #service-updates\n\nMost of the time you will want to use this process in a Deployment spec or similar context. Here is\nan example:\n\n```yaml\napiVersion: apps/v1                                                                                                                                           \nkind: Deployment                                                                                                                                              \nmetadata:                                                                                                                                                     \n  name: my-singleton-with-replicas\nspec:\n  replicas: 5\n  selector:\n    matchLabels:\n      app: my-singleton-server\n  template:\n    metadata:\n      labels:\n        app: my-singleton-server\n    spec:\n      containers:          \n      - name: my-singleton-server\n        args:                \n        - my-singleton-server                      \n        env:                              \n        - name: K8S_AWAIT_ELECTION_ENABLED\n          value: \"1\"         \n        - name: K8S_AWAIT_ELECTION_NAME           \n          value: linstor-controller                 \n        - name: K8S_AWAIT_ELECTION_LOCK_NAME                                                \n          value: piraeus-op-cs      \n        - name: K8S_AWAIT_ELECTION_LOCK_NAMESPACE\n          value: default    \n        - name: K8S_AWAIT_ELECTION_IDENTITY\n          valueFrom:    \n            fieldRef:   \n              apiVersion: v1\n              fieldPath: metadata.name\n        - name: K8S_AWAIT_ELECTION_STATUS_ENDPOINT\n          value: :9999\n```\n\n### Service Updates\n\n`k8s-await-election` can also be used to select which pod should receive traffic for a service.\nThis is done by updating the endpoint resource associated with a service whenever a new leader is elected.\nThis leader will be the only pod receiving traffic via the service.\nTo enable this feature, set the `K8S_AWAIT_ELECTION_SERVICE_*` variables.\nSee [the full example](./examples/singleton-service.yml)\n\n#### Why update service endpoints?\n\nFor deployments that provide some kind of external API (for example a REST API), we would\nalso like to automatically re-route traffic to the current leader.\n\nThis is normally done via the readiness state of the pod: only ready pods associated with\na service receive traffic. Because we only start the application if we are elected, only\none pod is ever \"ready\" in the sense that it should receive traffic.\n\nThis means that if we wanted to use the automatic service configuration via selectors, we\nrun into some issues. The \"ready\" state of a pod has a kind of dual use. Consider a rolling upgrade of a deployment:\n\n1. A new pod starts.\n2. It won't become leader as the old one is still running\n3. Since the app starts, it is never \"ready\" to receive traffic\n4. the deployment controller sees the pod is not ready, and does not continue with upgrading\n \n`k8s-await-election` has all the information it needs to tell Kubernetes which pod should receive\ntraffic. This works around the above issue, at the cost of a non-usable readiness probe.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinbit%2Fk8s-await-election","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flinbit%2Fk8s-await-election","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinbit%2Fk8s-await-election/lists"}