Skip to content

feat: pg_autoctl node — declarative node lifecycle from a single ini file - #1131

Merged
dimitri merged 12 commits into
mainfrom
pg-autoctl-node
Jul 6, 2026
Merged

feat: pg_autoctl node — declarative node lifecycle from a single ini file#1131
dimitri merged 12 commits into
mainfrom
pg-autoctl-node

Conversation

@dimitri

@dimitri dimitri commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds pg_autoctl node, a new sub-command tree that manages the full lifecycle of a pg_auto_failover node — creation, startup, and live reconfiguration — from a single pg_autoctl_node.ini file. This is the recommended entry-point for container and Kubernetes deployments.

Motivation

The existing pg_autoctl create ... && pg_autoctl run workflow is flag-heavy and hard to parameterise in containers. pg_autoctl node run /etc/pgaf/node.ini replaces the per-node command: lines in Docker Compose with a single image and a single entry-point; all per-node differences live in a mounted ini file.

pg_autoctl_node.ini

[node]
kind     = postgres
name     = node1
hostname = node1.internal
port     = 5432

[postgresql]
pgdata = /var/lib/postgresql/data

[monitor]
pguri = postgres://autoctl_node@monitor:5432/pg_auto_failover

[formation]
name = default

[settings]
candidate_priority = 50
replication_quorum = true

[options]
ssl        = self-signed
auth       = trust
pg_hba_lan = true

Sections: [node], [postgresql], [monitor], [formation], [settings] (mutable), [options] (create-time only), [ssl], [launch], [formation <name>] (monitor: extra formations), [pg_auto_failover], [replication], [citus].

Sub-commands

Command Description
node run [<file>] Create (if absent) then exec() into supervisor; sets PG_AUTOCTL_NODESPEC for live watching
node apply <file> Converge mutable settings on a running node
node start [<file>] Clear launch=deferred so a waiting node run proceeds
node show Dump current config as pg_autoctl_node.ini
node check <file> Parse-only validate

Live Reconfiguration

The supervisor watches PG_AUTOCTL_NODESPEC via inotify (Linux) or mtime polling (macOS/others). Editing [settings] and saving the file is sufficient to converge candidate_priority or replication_quorum on a running node — no restart required.

Deferred Launch

[launch]
mode = deferred

A node with mode = deferred waits in a poll loop. A sidecar or init container calls pg_autoctl node start to release it. Enables ordered startup without an external orchestrator.

Container Usage

Same image, same entry-point for every node type:

command: ["pg_autoctl", "node", "run", "/etc/pgaf/node.ini"]

Per-node differences are a bind-mount (Docker) or ConfigMap volume (Kubernetes).

Files

  • src/bin/pg_autoctl/cli_node.c / .h — command tree
  • src/bin/pg_autoctl/nodespec.c / .h — ini parser, create-argv builder, apply logic
  • src/bin/pg_autoctl/supervisor.c / .h — NodeSpecWatcher integration
  • docs/ref/pg_autoctl_node.rst — full reference with Docker Compose and Kubernetes examples
  • docs/ref/pg_autoctl_node_run.rst — run sub-command detail

Relationship to existing commands

pg_autoctl node run translates the ini file into the same flags and exec's into the same supervisor that pg_autoctl create ... --run would start. No hidden API. Existing nodes can adopt the ini-based workflow via pg_autoctl node show --pgdata <dir>.

@dimitri dimitri self-assigned this Jul 6, 2026
@dimitri dimitri added the enhancement New feature or request label Jul 6, 2026
Base automatically changed from pg-autoctl-commands to main July 6, 2026 21:33
dimitri added 4 commits July 6, 2026 23:35
…de.ini

Adds a new pg_autoctl node sub-command tree and a NodeSpec file format
designed as the recommended entry-point for container and Kubernetes
deployments.

## pg_autoctl_node.ini sections

  [node]         kind (postgres|monitor|coordinator|worker), name, hostname, port
  [postgresql]   pgdata
  [monitor]      pguri (empty for monitor nodes), no_monitor, node_id
  [formation]    name, group
  [settings]     candidate_priority, replication_quorum   ← mutable, applied live
  [options]      ssl, auth, pg_hba_lan                    ← create-time only
  [ssl]          ssl_ca_file, ssl_cert_file, ssl_key_file
  [launch]       mode=deferred: wait for pg_autoctl node start
  [formation N]  monitor only: additional named formations

## pg_autoctl node sub-commands

  run   <file>   Read ini, create node if absent, exec() into supervisor.
                 Sets PG_AUTOCTL_NODESPEC so the supervisor watches for
                 live [settings] changes via inotify (Linux) or mtime poll.
  apply <file>   Converge mutable settings on an already-running node.
  start [<file>] Clear launch=deferred so a waiting node run proceeds.
  show           Dump live config as pg_autoctl_node.ini on stdout.
  check <file>   Parse-only validate; print resolved fields.

## Supervisor file watcher (nodespec_watcher)

The supervisor initialises a NodeSpecWatcher when PG_AUTOCTL_NODESPEC is
set. Every tick it checks for file changes:
  - Linux:   drain inotify IN_CLOSE_WRITE / IN_MOVED_TO events
  - Others:  stat() every NODESPEC_WATCH_INTERVAL_SECS (10 s)
On change, re-parse [settings] and call nodespec_apply() to converge
mutable fields without restarting the node.

## Files

  src/bin/pg_autoctl/cli_node.c / cli_node.h
  src/bin/pg_autoctl/nodespec.c / nodespec.h
  src/bin/pg_autoctl/supervisor.c / supervisor.h  (watcher integration)
  docs/ref/pg_autoctl_node.rst
  docs/ref/pg_autoctl_node_run.rst
- pg_autoctl_node.rst: replace prose property list with a structured
  table (section/property/type/mutable/default/description), each
  property on its own row; fix 'disabled-monitor' label → actual ref

- nodespec_apply: add ssl apply block — when [options].ssl or any [ssl]
  cert path changes, call 'pg_autoctl enable ssl' with the appropriate
  flags (--ssl-self-signed, --no-ssl, or --ssl-mode + cert paths);
  update nodespec_apply comment to list ssl as mutable

- docs/index.rst: remove 'Container and Kubernetes' as a top-level
  toctree caption; the manual page is still reachable via Manual Pages

- docs/operations.rst: add 'Container and Kubernetes Deployments'
  section describing pg_autoctl node run, live reconfiguration, and
  the launch=deferred pattern; cross-refs to pg_autoctl_node for details

- docs/ref/configuration.rst: add 'Declarative Node Configuration'
  section covering pg_autoctl_node.ini sections and their relationship
  to pg_autoctl.cfg; cross-ref to pg_autoctl_node
When the [monitor] pguri changes in pg_autoctl_node.ini, nodespec_apply
now re-registers the node to the new monitor without stopping Postgres:

  pg_autoctl disable monitor --force --pgdata <dir>
  pg_autoctl enable monitor <new_uri> --pgdata <dir>

The disable step removes the node from the old monitor (--force allows
this even if the old monitor is temporarily unreachable). The enable step
registers the node to the new monitor and signals the running supervisor
to start using the new monitor_pguri for node_active calls.

Document the change in the property table and Live Reconfiguration section
of pg_autoctl_node.rst.
…ction

Follow the pg_autoctl_create pattern: each pg_autoctl node sub-command
now has its own manual page, all listed in pg_autoctl_node.rst's toctree:

  pg_autoctl node run    (existing)
  pg_autoctl node apply  (new)
  pg_autoctl node start  (new)
  pg_autoctl node show   (new)
  pg_autoctl node check  (new)

Remove the redundant 'Container and Kubernetes Deployments' section from
operations.rst. The full documentation for this feature lives in the
pg_autoctl_node manual page (ref/pg_autoctl_node.rst) and its sub-pages.
@dimitri
dimitri force-pushed the pg-autoctl-node branch from 8019d3a to 6a860c2 Compare July 6, 2026 21:36
dimitri added 8 commits July 6, 2026 23:40
The list-table rendered poorly in the Sphinx HTML theme. Replace it with
the same definition-list style used throughout the other manual pages
(e.g. pg_autoctl_create_postgres Options section): each property is a
bare term followed by indented description paragraphs, grouped under
ini-section sub-headings.
…ioning

Re-add the 'Container and Kubernetes Deployments' section at the end of
operations.rst with a named anchor so it can be referenced from elsewhere.

Add a short note in the Provisioning section pointing to pg_autoctl node run
as the declarative alternative for container and Kubernetes deployments,
with a cross-reference down to the new section.
Add references to pg_autoctl node / pg_autoctl node run in all the places
identified by the documentation audit:

Reference pages (new See Also section):
- pg_autoctl_create_postgres.rst
- pg_autoctl_create_monitor.rst
- pg_autoctl_create_coordinator.rst
- pg_autoctl_create_worker.rst
- pg_autoctl_run.rst

Narrative docs (short note pointing to the declarative alternative):
- how-to.rst — after the pg_autoctl run step in Quick Start
- tutorial.rst — after the docker-compose.yml literalinclude
- citus-quickstart.rst — after the docker-compose-scale.yml literalinclude
- install.rst — after the systemd unit section
Replace the imperative pg_autoctl create postgres / pg_autoctl create
monitor commands with the declarative pg_autoctl node run approach:

- Add tutorial/ini/monitor.ini and tutorial/ini/postgres.ini — two small
  ini files that describe the monitor and every data node respectively.
  Data nodes share one ini file; hostname and name default to the
  container hostname set by Docker Compose.

- Rewrite tutorial/docker-compose.yml: all PG_AUTOCTL_* environment
  variables are gone; each service bind-mounts its ini file at
  /etc/pgaf/node.ini and runs 'pg_autoctl node run'. The x-node anchor
  is now clean — no env vars, single command.

- Update tutorial.rst to introduce the ini files before the compose file,
  explain that pg_autoctl node run handles both create and run, and show
  that live reconfiguration (candidate_priority change for node3) is done
  by editing the ini file rather than calling pg_autoctl set.

- Replace the stale pg_autoctl_do_tmux_compose_session reference in Next
  steps with a pointer to the pg_autoctl_node reference and the Container
  and Kubernetes Deployments section.
… paths

Show both approaches side by side:

- Direct command (pg_autoctl set candidate-priority): immediate, no restart
- Declarative ini file: explain that changing docker-compose.yml volumes
  requires 'docker compose up -d node3' to recreate the container, that
  pg_autoctl node run applies the ini diff on startup before exec'ing into
  the supervisor, and that once the dedicated ini file is mounted any
  subsequent edits to it are picked up live by the running supervisor.
Replace all pg_autoctl create coordinator/worker/monitor commands with
the declarative pg_autoctl node run approach:

New ini files:
  citus/ini/monitor.ini     — kind = monitor
  citus/ini/coordinator.ini — kind = coordinator, shared by coord0a/coord0b
  citus/ini/worker.ini      — kind = worker, no group (monitor auto-assigns)
  citus/ini/worker1.ini     — kind = worker, group = 1
  citus/ini/worker2.ini     — kind = worker, group = 2
  citus/ini/worker3.ini     — kind = worker, group = 3

Rewritten compose files:
  docker-compose-scale.yml  — three services (monitor/coord/worker), each
    bind-mounts its ini file; all PG_AUTOCTL_* env vars removed
  docker-compose.yml        — named services with per-group worker ini files;
    YAML anchors kept for coord and per-group worker templates

Updated citus-quickstart.rst:
  - Show all ini files with literalinclude captions before each compose file
  - Explain that worker.ini without [formation] group triggers monitor
    auto-assignment (right for --scale), while workerN.ini with group = N
    pins the pair to a specific shard group (right for named services)
  - Explain that pg_autoctl node run uses the container hostname as the
    node name when name is not set in the ini file
  - Replace stale pg_autoctl_do_tmux_compose_session reference in Next
    steps with pointer to pg_autoctl_node and container deployments guide
@dimitri
dimitri merged commit 80e9573 into main Jul 6, 2026
51 of 52 checks passed
@dimitri
dimitri deleted the pg-autoctl-node branch July 6, 2026 22:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant