Skip to content

fix: reap detached pgBackRest processes in the instance sidecar - #161

Open
melancholictheory wants to merge 1 commit into
operasoftware:mainfrom
melancholictheory:fix/sidecar-reap-orphans
Open

melancholictheory wants to merge 1 commit into
operasoftware:mainfrom
melancholictheory:fix/sidecar-reap-orphans

Conversation

@melancholictheory

Copy link
Copy Markdown
Contributor

Fixes #157.

What

The sidecar image runs tini as PID 1 in front of the manager, so the async pgBackRest processes that detach themselves are reaped when they exit instead of staying zombies until the sidecar restarts.

How

containers/Dockerfile.sidecar installs tini in the existing Debian stage, rather than in a stage of its own as sketched in the issue, copies tini-static in as /tini and changes the entrypoint to ["/tini", "--", "/manager"]. The static binary needs nothing from the distroless base. The operator only sets args on the sidecar, so the instance pods and the restore job pick up the new entrypoint without other changes. The startup probe runs /manager healthcheck unix directly and is not affected.

Testing

  • The image built from this Dockerfile has the entrypoint ["/tini","--","/manager"], runs as 26:26 and passes its arguments on to the manager.
  • A small test program that starts 30 detached workers the way the async archive-push does, in a new session with the parent exiting right away, leaves 30 zombies when it runs as PID 1 and none under this image's /tini.
  • On k3d with CloudNativePG 1.30.0, a sidecar built from source with tini archived 30 segments one at a time and left no zombies. SIGTERM still reached the manager, which exited with 0, and PostgreSQL kept running.
  • CI passes on our fork, e2e suite included (7 of 7), against CloudNativePG 1.30.0 with the MinIO images from fix(e2e): run MinIO from the Chainguard images #155. The e2e suite builds the sidecar from this Dockerfile, so all of it ran with tini as PID 1.

With --archive-async, archive-push starts the async process detached (setsid and a second
fork), so it is reparented to PID 1 of the sidecar. PID 1 was the manager, which only waits
for the children it starts itself, so every async process that exited stayed a zombie until
the sidecar restarted. With a quiet write load that is one zombie per archived segment, and
each of them keeps its PID.

The sidecar image now runs tini as PID 1 in front of the manager. It is installed in the
existing Debian stage and copied in as tini-static, which needs nothing from the distroless
base. The operator sets only args on the sidecar, so the entrypoint applies to the instance
pods and to the restore job without other changes, and tini passes SIGTERM on to the manager.

Refs: operasoftware#157
Signed-off-by: Vasiliy Fakunin <61789920+melancholictheory@users.noreply.github.com>
@melancholictheory

Copy link
Copy Markdown
Contributor Author

CI is red only on the e2e suite, for a reason unrelated to this change: docker.io/minio/minio:latest no longer exists on Docker Hub (pull access denied, repository does not exist), so the MinIO pods never start and the specs time out. Spellcheck, commitlint, lint, the unit tests and the uncommitted check pass.

#154 includes the switch to the Chainguard MinIO images from #155 and makes the restore specs pass on CloudNativePG main. Merged on top of #154, this branch passes the whole e2e suite against CloudNativePG main on our fork, 8 of 8 (#154 adds one spec): run. We will rebase once #154 is merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Async WAL archiving leaves zombie pgBackRest processes in the instance sidecar

1 participant