{"id":22288919,"url":"https://github.com/marceloneppel/patroni-replication-test","last_synced_at":"2026-03-19T22:19:25.332Z","repository":{"id":44753514,"uuid":"447969930","full_name":"marceloneppel/patroni-replication-test","owner":"marceloneppel","description":"Patroni replication test with Pebble.","archived":false,"fork":false,"pushed_at":"2022-02-04T13:32:25.000Z","size":20,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-05T19:02:45.495Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dockerfile","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/marceloneppel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-01-14T13:04:20.000Z","updated_at":"2022-01-14T21:21:01.000Z","dependencies_parsed_at":"2022-09-09T22:50:34.403Z","dependency_job_id":null,"html_url":"https://github.com/marceloneppel/patroni-replication-test","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/marceloneppel/patroni-replication-test","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marceloneppel%2Fpatroni-replication-test","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marceloneppel%2Fpatroni-replication-test/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marceloneppel%2Fpatroni-replication-test/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marceloneppel%2Fpatroni-replication-test/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marceloneppel","download_url":"https://codeload.github.com/marceloneppel/patroni-replication-test/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marceloneppel%2Fpatroni-replication-test/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29867561,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-26T18:27:06.972Z","status":"ssl_error","status_checked_at":"2026-02-26T18:26:57.848Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2024-12-03T17:07:35.248Z","updated_at":"2026-02-26T18:36:55.234Z","avatar_url":"https://github.com/marceloneppel.png","language":"Dockerfile","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Patroni Replication Test\n\nThis repository aims to show a difference on executing [patroni](https://github.com/zalando/patroni) directly inside a docker container and another situation where it's started by [pebble](https://github.com/canonical/pebble).\n\n## Dependencies\n\nThe command below will install `curl`, `gettext-base` package (in order to use `envsubst`) and `microk8s` snap (you will also need Docker installed in your system).\n```sh\nmake dependencies\n```\n\n## Building the images\n\nBuild the docker images (`test-patroni` and `test-pebble`) using the following command:\n```sh\nmake build\n```\n\n## Testing Patroni being the entrypoint\n\nFirstly you run the command to deploy the pods with patroni being the entrypoint:\n\n```sh\nmake patroni\n```\n\nThen you run the command `make logs` to see the logs and check that we have the first pod as the replication leader (it's the Postgres instance which accept both reads and writes).\n\n```sh\nkubectl exec pod/patronidemo-0 -- tail -2 patroni.log\n2022-01-14 20:59:54,813 INFO: no action. I am (patronidemo-0), the leader with the lock\n2022-01-14 21:00:04,776 INFO: no action. I am (patronidemo-0), the leader with the lock\n\nkubectl exec pod/patronidemo-1 -- tail -2 patroni.log\n2022-01-14 20:59:54,819 INFO: no action. I am (patronidemo-1), a secondary, and following a leader (patronidemo-0)\n2022-01-14 21:00:04,794 INFO: no action. I am (patronidemo-1), a secondary, and following a leader (patronidemo-0)\n\nkubectl exec pod/patronidemo-2 -- tail -2 patroni.log\n2022-01-14 20:59:54,821 INFO: no action. I am (patronidemo-2), a secondary, and following a leader (patronidemo-0)\n2022-01-14 21:00:04,797 INFO: no action. I am (patronidemo-2), a secondary, and following a leader (patronidemo-0)\n```\n\nSo, you can run the command `make crash-leader` to delete the pod of the leader and trigger a failover. Then you can check again the logs with `make logs`. After some time, we will have another instance as the leader and the other ones as replicas following the leader.\n\n```\nkubectl exec pod/patronidemo-0 -- tail -2 patroni.log\n2022-01-14 21:05:21,263 INFO: no action. I am (patronidemo-0), a secondary, and following a leader (patronidemo-1)\n2022-01-14 21:05:31,313 INFO: no action. I am (patronidemo-0), a secondary, and following a leader (patronidemo-1)\n\nkubectl exec pod/patronidemo-1 -- tail -2 patroni.log\n2022-01-14 21:05:21,248 INFO: no action. I am (patronidemo-1), the leader with the lock\n2022-01-14 21:05:31,295 INFO: no action. I am (patronidemo-1), the leader with the lock\n\nkubectl exec pod/patronidemo-2 -- tail -2 patroni.log\n2022-01-14 21:05:21,259 INFO: no action. I am (patronidemo-2), a secondary, and following a leader (patronidemo-1)\n2022-01-14 21:05:31,314 INFO: no action. I am (patronidemo-2), a secondary, and following a leader (patronidemo-1)\n```\n\nYou can also check that there are no zombie processes using the command `make zombies`:\n```\nkubectl exec pod/patronidemo-0 -- ps aux | grep defunct || true\n\nkubectl exec pod/patronidemo-1 -- ps aux | grep defunct || true\n\nkubectl exec pod/patronidemo-2 -- ps aux | grep defunct || true\n```\n\n## Testing Patroni with Pebble starting it\n\nFirstly you run the command to deploy the pods with pebble being the entrypoint. This time pebble starts patroni (we run `make clean` first in order to remove the previous deployment):\n\n```sh\nmake clean\nmake pebble\n```\n\nYou can check the logs with `make logs`:\n\n```\nkubectl exec pod/patronidemo-0 -- tail -2 patroni.log\n2022-01-14 21:12:15,644 INFO: no action. I am (patronidemo-0), the leader with the lock\n2022-01-14 21:12:25,752 INFO: no action. I am (patronidemo-0), the leader with the lock\n\nkubectl exec pod/patronidemo-1 -- tail -2 patroni.log\n2022-01-14 21:12:15,651 INFO: no action. I am (patronidemo-1), a secondary, and following a leader (patronidemo-0)\n2022-01-14 21:12:25,759 INFO: no action. I am (patronidemo-1), a secondary, and following a leader (patronidemo-0)\n\nkubectl exec pod/patronidemo-2 -- tail -2 patroni.log\n2022-01-14 21:12:15,651 INFO: no action. I am (patronidemo-2), a secondary, and following a leader (patronidemo-0)\n2022-01-14 21:12:25,758 INFO: no action. I am (patronidemo-2), a secondary, and following a leader (patronidemo-0)\n```\n\nThen crash the leader with `make crash-leader` and see the logs again with `make logs` after some time:\n\n```\nkubectl exec pod/patronidemo-0 -- tail -2 patroni.log\n2022-01-14 21:14:22,696 INFO: no action. I am (patronidemo-0), a secondary, and following a leader (patronidemo-1)\n2022-01-14 21:14:32,849 INFO: no action. I am (patronidemo-0), a secondary, and following a leader (patronidemo-1)\n\nkubectl exec pod/patronidemo-1 -- tail -2 patroni.log\n2022-01-14 21:14:22,690 INFO: no action. I am (patronidemo-1), the leader with the lock\n2022-01-14 21:14:32,891 INFO: no action. I am (patronidemo-1), the leader with the lock\n\nkubectl exec pod/patronidemo-2 -- tail -2 patroni.log\n2022-01-14 21:14:32,768 INFO: Lock owner: patronidemo-1; I am patronidemo-2\n2022-01-14 21:14:32,768 INFO: changing primary_conninfo and restarting in progress\n```\n\nThis time we see one of the replicas (the one that was not elected as a leader after the failover) stuck in the process of restarting Postgres. This happens because patroni is waiting for the Postgres process (which became a zombie process) to completely stop (it never happens). The following is the output of the command `make zombies`:\n\n```\nkubectl exec pod/patronidemo-0 -- ps aux | grep defunct || true\npostgres      29  0.0  0.0      0     0 ?        Z    21:14   0:00 [pg_basebackup] \u003cdefunct\u003e\n\nkubectl exec pod/patronidemo-1 -- ps aux | grep defunct || true\n\nkubectl exec pod/patronidemo-2 -- ps aux | grep defunct || true\npostgres      35  0.0  0.0      0     0 ?        Z    21:11   0:00 [postgres] \u003cdefunct\u003e\n```\n\n## Testing Patroni with Supervisord starting it\n\nFirstly you run the command to deploy the pods with supervisord being the entrypoint. This time supervisord starts patroni (we run `make clean` first in order to remove the previous deployment):\n\n```sh\nmake clean\nmake supervisord\n```\n\nThen, we can check the logs the same way the other times and we'll see that this time the automatic failover will be done correctly as the first time.\n\n## Triggering a manual failover\n\nYou can also check the a similar issue (zombie process preventing some operation) if you try to trigger a manual failover using:\n\n```sh\nmake failover\n```\n\nWhen using the pebble example, you'll face a situation where we can't complete the failover because of the zombie process.\n\n## Known issues\n\nIf you see a message like the one below when running `make patroni` or `make pebble`, just run `make clean` and rerun the original command.\n\n```\nWarning: resource endpoints/patronidemo is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.\n```\n\nAlso, we are using `host replication standby 0.0.0.0/0 md5` in the Postgres authentication rules just to make this example work the way we need. It's more secure to use the pod's IP.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarceloneppel%2Fpatroni-replication-test","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarceloneppel%2Fpatroni-replication-test","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarceloneppel%2Fpatroni-replication-test/lists"}