KubernetesProbes.Drainer (kubernetes_probes v0.1.1)

Copy Markdown View Source

Holds the k8s readiness-probe status and enforces a drain window on shutdown.

On SIGTERM, OTP walks the supervision tree in reverse start order and terminates children in reverse order. This GenServer must be the last child of your application supervisor so it terminates first. Its terminate/2 flips the /probe/readiness probe to 503 via :persistent_term and sleeps for the drain window, giving Kubernetes time to stop routing traffic and allowing in-flight requests to finish before other resources (Repo, Endpoint, etc.) are torn down.

Note that the Endpoint keeps running and serving requests for the full drain window — only its readiness status changes. A caller with a persistent (keep-alive) connection already open to this instance can therefore keep reusing it, and keep seeing 503s, for the whole window, regardless of how quickly Kubernetes removes the instance from the Service's endpoints. KubernetesProbes.Plug closes the connection on a draining 503 specifically to prevent that — see its docs.

Usage

# lib/my_app/application.ex — last entry in children
children = [
  MyApp.Repo,
  MyAppWeb.Endpoint,
  {KubernetesProbes.Drainer, otp_app: :my_app}
]

Configuration

# config/config.exs — production default
config :my_app, KubernetesProbes.Drainer, wait: 20_000

# config/dev.exs — avoid 20s hang on Ctrl-C
config :my_app, KubernetesProbes.Drainer, wait: 100

# config/test.exs — avoid slow suite teardown
config :my_app, KubernetesProbes.Drainer, wait: 10

Options

  • :otp_app — the OTP application to read configuration from (required).
  • :wait — drain window in milliseconds. Can be set via config (see above) or passed directly to override config: {KubernetesProbes.Drainer, otp_app: :my_app, wait: 5_000}. Defaults to 20_000.

Summary

Functions

Returns a specification to start this module under a supervisor.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

start_link(opts)

status()

@spec status() :: :running | :stopping