{"id":19732863,"url":"https://github.com/riptl/redis-k8s-election","last_synced_at":"2026-05-06T13:15:14.057Z","repository":{"id":53823157,"uuid":"317620367","full_name":"riptl/redis-k8s-election","owner":"riptl","description":"[WIP!] Kubernetes-friendly replacement for Redis Sentinel","archived":false,"fork":false,"pushed_at":"2020-12-06T05:45:15.000Z","size":42,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-24T18:06:58.477Z","etag":null,"topics":["kubernetes","redis","sentinel"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/riptl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-01T17:40:02.000Z","updated_at":"2024-08-10T13:27:08.000Z","dependencies_parsed_at":"2022-08-22T06:01:32.251Z","dependency_job_id":null,"html_url":"https://github.com/riptl/redis-k8s-election","commit_stats":null,"previous_names":["riptl/redis-k8s-election"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riptl%2Fredis-k8s-election","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riptl%2Fredis-k8s-election/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riptl%2Fredis-k8s-election/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riptl%2Fredis-k8s-election/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/riptl","download_url":"https://codeload.github.com/riptl/redis-k8s-election/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241058401,"owners_count":19902175,"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","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":["kubernetes","redis","sentinel"],"created_at":"2024-11-12T00:28:15.053Z","updated_at":"2026-05-06T13:15:13.992Z","avatar_url":"https://github.com/riptl.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003eredis-k8s-election\u003c/h1\u003e\n  \u003cp\u003e\n    \u003cstrong\u003eKubernetes-native leader/follower replication for Redis\u003c/strong\u003e\n  \u003c/p\u003e\n  \u003csub\u003eBuilt with Go and 👿 at \u003ca href=\"https://github.com/Blockdaemon\"\u003eBlockdaemon\u003c/a\u003e\u003c/sub\u003e\n\u003c/div\u003e\n\n## About\n\nThis service implements leader/follower (master/slave) replication for Redis.\nIt replaces Redis Sentinel using Kubernetes-native leader election.\n\nThe list of capabilities is similar to [Sentinel's](https://redis.io/topics/sentinel):\n- **Monitoring**. Kubernetes readiness and liveness checks continually check\n- **Events**. Events regarding availability checks are handled with K8s-native APIs,\n  for example through Alertmanager via [`kube-state-metrics`](https://github.com/kubernetes/kube-state-metrics).\n- **Automatic failover**. If a master fails, another is re-elected.\n\n`redis-k8s-election` has certain advantages over Sentinel:\n- **Works with any Redis client**, and does not require explicit failover support, nor special configuration.\n- **No Sentinel quorum required** to achieve consensus.\n  The Redis service stays up as long as it has access to one Redis pod and the Kubernetes control-plane.\n- **Resilient against pod rescheduling** by using Pod DNS.\n  Redis Sentinel via the [bitnami/redis](https://artifacthub.io/packages/helm/bitnami/redis) Helm chart\n  use Pod IPs, which risks running into deadlocks when enough pods reschedule and change IPs.\n\nReasons to instead use Redis Sentinel or [ledisdb/redis-failover](https://github.com/ledisdb/redis-failover):\n- You prefer Redis Sentinel's maturity.\n- You don't have an existing Kubernetes environment.\n- You don't want to rely on the Kubernetes control plane for availability.\n- `k8s.io/client-go/tools/leaderelection`\n  - is in alpha state (though it has been stable for ~2 years).\n  - does not strictly guarantee that only one Redis instance is leading.\n  - has higher latency than Sentinel or etcd.\n  - is prone to clock skew larger than the lease duration.\n\nFor further information, please check the [Redis Sentinel Documentation](https://redis.io/topics/sentinel).\n\n## Quickstart\n\nThe manifests at `examples/cluster.yaml` deploy a three-node Redis leader/replica cluster.\n\n```shell script\nkubectl create namespace redis-k8s-election\nkubectl apply -n redis-k8s-election -f https://raw.githubusercontent.com/terorie/redis-k8s-election/main/examples/cluster.yaml\n```\n\nConnect to the leader for read/write access:\n\n```shell script\nkubectl port-forward -n redis-k8s-election svc/redis-leader 6378:6379\nredis-cli -p 6378 info replication\n```\n\nOr any of the nodes for read access:\n\n```shell script\nkubectl port-forward -n redis-k8s-election svc/redis-replica 6379\nredis-cli -p 6379 info replication\n```\n\n### Election results\n\n`redis-0` gets created first, winning the leader election.\n`redis-1` and `redis-2` will follow.\n\n```\n$ kubectl logs -n redis-k8s-election redis-0 -c redis-k8s-election\nI1206 04:23:06.496554       1 main.go:75] Connecting to Redis: localhost:6379\nI1206 04:23:06.525680       1 main.go:91] Successful initial ping from Redis\nI1206 04:23:06.525737       1 leaderelection.go:242] attempting to acquire leader lease  redis-k8s-election/redis-leader-lock...\nI1206 04:23:06.543659       1 leaderelection.go:252] successfully acquired lease redis-k8s-election/redis-leader-lock\nI1206 04:23:06.543864       1 main.go:126] I am the Redis leader\nI1206 04:23:06.544041       1 main.go:173] Setting leader service selector to pod redis-0\nI1206 04:23:06.554853       1 main.go:151] Setting Redis to replicate NO ONE\n\n$ kubectl logs -n redis-k8s-election redis-1 -c redis-k8s-election\nI1206 04:23:17.443600       1 main.go:75] Connecting to Redis: localhost:6379\nI1206 04:23:17.468970       1 main.go:91] Successful initial ping from Redis\nI1206 04:23:17.475652       1 leaderelection.go:345] lock is held by redis-0 and has not yet expired\nI1206 04:23:17.475695       1 main.go:151] Setting Redis to replicate redis-0.redis.redis-k8s-election.svc.cluster.local 6379\n\n$ kubectl logs -n redis-k8s-election redis-2 -c redis-k8s-election\nI1206 04:23:33.294719       1 main.go:75] Connecting to Redis: localhost:6379\nI1206 04:23:33.320662       1 main.go:91] Successful initial ping from Redis\nI1206 04:23:33.328167       1 leaderelection.go:345] lock is held by redis-0 and has not yet expired\nI1206 04:23:33.328212       1 main.go:151] Setting Redis to replicate redis-0.redis.redis-k8s-election.svc.cluster.local 6379\n```\n\nTo test failover, try to terminate `redis-0`.\n`redis-1` wins the next election and `redis-2` switches its replica config.\n\n```\n$ kubectl logs -n redis-k8s-election redis-1 -c redis-k8s-election\nI1206 04:25:17.886144       1 leaderelection.go:252] successfully acquired lease redis-k8s-election/redis-leader-lock\nI1206 04:25:17.886282       1 main.go:126] I am the Redis leader\nI1206 04:25:17.886439       1 main.go:173] Setting leader service selector to pod redis-1\nI1206 04:25:17.908234       1 main.go:151] Setting Redis to replicate NO ONE\n\n$ kubectl logs -n redis-k8s-election redis-2 -c redis-k8s-election\nI1206 04:25:19.447584       1 leaderelection.go:345] lock is held by redis-1 and has not yet expired\nI1206 04:25:19.447701       1 main.go:151] Setting Redis to replicate redis-1.redis.redis-k8s-election.svc.cluster.local 6379\nI1206 04:25:22.121783       1 leaderelection.go:345] lock is held by redis-1 and has not yet expired\n```\n\nTo clean up your resources when you are done:\n\n```shell script\nkubectl delete -n redis-k8s-election -f https://raw.githubusercontent.com/terorie/redis-k8s-election/main/examples/cluster.yaml\nkubectl get -n redis-k8s-election pvc -l app=redis,role=node -o name | xargs kubectl delete -n redis-k8s-election\nkubectl delete namespace redis-k8s-election\n```\n\n## Architecture\n\nTODO: Properly explain this\n\nCoordination\n\n* Each Redis pod runs a `redis-k8s-election` sidecar.\n* The sidecars compete in a Kubernetes leader election.\n* The leader configures its Redis instance as writable,\n  and the followers make themselves read-only replicas of the leader. \n\nService discovery\n\n* Clients use Kubernetes Services to connect to Redis.\n* All Redis clients are supported, no Sentinel client logic involved.\n* The `redis-replica` service connects to any Redis instance and supports read-only clients.\n* The `redis-leader` service connects to the current leader.\n  The election sidecar proxies all connections to the leader,\n  ensuring Redis is only reached when really talking with the leader.\n\n## Motivation\n\nAs with many things, when it comes to distributed systems, the less complexity, the better.\n\nThis service aims to be simpler and more reliable than a Redis Sentinel setup in a Kubernetes context.\n\nThe Kubernetes control-plane already provides highly-available service discovery\nand leader election facilities. Redis Sentinel duplicates a large part, including\nalgorithms for achieving distributed consensus written in C.\n\n## Attributions\n\nAuthor: [Richard Patel](https://github.com/terorie)\n\nKubernetes manifests (example/cluster.yaml) based on\n[Bitnami Redis Helm chart](https://github.com/bitnami/charts/tree/master/bitnami/redis).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Friptl%2Fredis-k8s-election","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Friptl%2Fredis-k8s-election","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Friptl%2Fredis-k8s-election/lists"}