Controller-Runtime Shutdown and Signal Handling in plugin-barman-cloud#
plugin-barman-cloud uses controller-runtime's SetupSignalHandler as the single source of the shutdown signal. The resulting context is threaded through Cobra and into every long-running subsystem, so a single SIGTERM (or SIGINT) cancels all runnables without any per-component signal wiring.
Signal Origin: SetupSignalHandler#
The binary's entry point (cmd/manager/main.go) calls ctrl.SetupSignalHandler() once and passes the returned context to Cobra's root command via rootCmd.ExecuteContext(...) . SetupSignalHandler installs OS-level handlers for SIGTERM and SIGINT and cancels the context on the first signal; a second signal causes an immediate exit.
The root command also enriches the context with a structured logger before subcommands run , so all downstream code receives both the cancellation signal and logging from the same context.
Context Propagation to Subcommands#
Both the operator and instance subcommands forward the Cobra command context directly to their Start functions:
- Operator:
internal/cmd/operator/main.go→operator.Start(cmd.Context()) - Instance (sidecar):
internal/cmd/instance/main.go→instance.Start(cmd.Context())
No additional signal handling occurs at the subcommand level; the cancellation propagates purely through the context tree.
Manager Lifecycle and Runnable Registration#
Both Start functions follow the same pattern: create a ctrl.Manager, register runnables, then block on mgr.Start(ctx).
Operator (internal/cnpgi/operator/manager.go):
- Creates a manager with
LeaderElectionReleaseOnCancel: true, which lets the leader step down immediately when the manager context is cancelled rather than waiting out the fullLeaseDuration. - Registers a
CNPGIrunnable that serves the gRPC plugin interface . - Blocks on
mgr.Start(ctx); returns when all runnables exit.
Instance/sidecar (internal/cnpgi/instance/manager.go):
- Registers two runnables via
mgr.Add(...):CNPGI— serves WAL, Backup, and Metrics gRPC services .CatalogMaintenanceRunnable— enforces backup retention policies on a periodic timer .
- Blocks on
mgr.Start(ctx).
Runnable Shutdown Contract#
Each runnable's Start(ctx context.Context) error method is responsible for exiting cleanly when ctx is cancelled. The canonical example is CatalogMaintenanceRunnable (internal/cnpgi/instance/retention.go), whose event loop uses a select to wait on either a timer tick or ctx.Done(), returning nil on cancellation. The gRPC servers (CNPGI in both operator and instance) delegate to cnpg-i-machinery's http.Server.Start(ctx) , which is responsible for stopping the gRPC listener when the context is cancelled.
Controller-runtime's manager waits for all registered runnables to return before mgr.Start itself returns, giving every runnable the chance to flush state or close connections gracefully.
Error Handling on Shutdown#
Back in cmd/manager/main.go, ExecuteContext returns a context.Canceled error when the binary shuts down normally (i.e., signal received). The main function explicitly ignores this error and exits with code 0 , preventing Kubernetes from treating a clean SIGTERM shutdown as a crash.
Flow Summary#
SIGTERM/SIGINT
│
▼
ctrl.SetupSignalHandler() ← cmd/manager/main.go
│ cancels context
▼
rootCmd.ExecuteContext(ctx)
│ cmd.Context() propagated
├── operator.Start(ctx) ← internal/cmd/operator/main.go
│ └── mgr.Start(ctx) ← internal/cnpgi/operator/manager.go
│ ├── CNPGI (gRPC server)
│ └── [controllers / webhooks]
│
└── instance.Start(ctx) ← internal/cmd/instance/main.go
└── mgr.Start(ctx) ← internal/cnpgi/instance/manager.go
├── CNPGI (WAL/Backup/Metrics gRPC)
└── CatalogMaintenanceRunnable (retention loop)