Skip to content

Customizing a Playbook

The cluster deployed by a playbook may host high-availability nodes that reside in a single zone or in multiple zones; you can also customize a playbook with other configuration options.

Configuring a Single-Zone HA Playbook File

The playbook in the following example deploys a single-zone HA cluster using HAProxy; you can customize this deployment with the code samples that follow this section:

- hosts: all
  collections:
    - pgedge.platform
  roles:
    - init_server

- hosts: pgedge
  collections:
    - pgedge.platform
  roles:
    - install_repos
    - install_pgedge
    - setup_postgres
    - install_etcd
    - install_patroni
    - setup_etcd
    - setup_patroni

- hosts: haproxy
  collections:
    - pgedge.platform
  roles:
    - setup_haproxy

- hosts: pgedge
  collections:
    - pgedge.platform
  roles:
    - setup_pgedge

This configuration deploys the following components:

  • Patroni manages the Postgres cluster in zone 1.
  • An etcd cluster provides distributed consensus across the three nodes.
  • HAProxy routes new connections to the current Patroni primary.
  • Automatic failover activates when the primary becomes unavailable.

Configuring Multi-Zone Playbooks

Cluster designs that use multiple node groups require a playbook that targets all hosts at the top of the playbook. This ensures Ansible populates host variables for every server in the inventory before role-specific plays begin. Some roles require variables for hosts outside their own group; for example, a pgedge node needs zone information from nodes in the backup group.

The following pattern satisfies this requirement without running init_server twice:

# Populate variables for all hosts first
- hosts: all
  roles: []

# Then run roles on specific groups
- hosts: pgedge
  collections:
    - pgedge.platform
  roles:
    - init_server
    - install_repos
    # ...

Alternatively, run init_server against all as the first play, as shown in the Ultra-HA sample playbook.

Execution Strategy

Every play that applies the collection's roles must use Ansible's default linear strategy, over all of the play's hosts at once. Do not set strategy: free, in a play or in ansible.cfg, and do not set serial on a play.

free strategy or serial plays may deploy an inoperable cluster

These roles coordinate the hosts of a play with each other, and depend on every host finishing a task before any host starts the next. Hosts read facts and task results from each other throughout a deployment, and act on them in a fixed order.

The free strategy lets each host run ahead of the others, causing race conditions that violate these assumptions. serial runs a play over a few hosts at a time rather than all of the play's hosts at once, so each batch sees only its own hosts, and steps meant for the whole cluster act on part of it.

Either can leave the cluster in an inconsistent state. Some steps may never complete, or may deploy partially in ways that pass health checks but are otherwise invalid.

Check mode (--check) is not supported. The roles avoid failing under it where they can, but a check-mode run does not predict what a real run would change: many steps act on what an earlier step installed, wrote or started, and in check mode that earlier step did nothing.

Customizing the Configuration

The following examples demonstrate some common configuration overrides you may want to incorporate into this playbook.

Custom Database Configuration

The following inventory creates multiple databases with custom user accounts:

pgedge:
  vars:
    db_names:
      - app_db
      - reporting_db
    db_user: appuser
    db_password: "{{ vault_db_password }}"
    pgedge_user: replication
    pgedge_password: "{{ vault_repl_password }}"

Custom Port Configuration

The following inventory configures HAProxy to listen on port 5432 while Postgres listens on port 5433, allowing HAProxy to run on the same node as Postgres:

pgedge:
  vars:
    pg_port: 5433
    proxy_port: 5432

Strict Synchronous Replication Configuration

The following inventory enables strict synchronous replication, which prevents writes when no synchronous replicas respond:

pgedge:
  vars:
    is_ha_cluster: true
    synchronous_mode: true
    synchronous_mode_strict: true

S3 Backup Configuration

The following inventory configures PgBackRest to use an AWS S3 bucket instead of a dedicated SSH backup server:

pgedge:
  vars:
    backup_repo_type: s3
    backup_repo_path: /pgbackrest
    backup_repo_params:
      region: us-west-2
      endpoint: s3.amazonaws.com
      bucket: my-pg-backups
      access_key: "{{ vault_aws_access_key }}"
      secret_key: "{{ vault_aws_secret_key }}"
    full_backup_schedule: "0 2 * * 0"
    diff_backup_schedule: "0 2 * * 1-6"

Ansible Vault Integration Configuration

Use Ansible Vault to protect sensitive variables. The following command creates an encrypted variable file:

ansible-vault create group_vars/pgedge/vault.yml

Place sensitive values in the vault file:

vault_db_password: secure_password_123
vault_pgedge_password: replication_password_456
vault_backup_cipher: encryption_key_789

Reference vault variables in the inventory:

pgedge:
  vars:
    db_password: "{{ vault_db_password }}"
    pgedge_password: "{{ vault_pgedge_password }}"

Run the playbook with the vault password:

ansible-playbook -i inventory.yaml playbook.yaml --ask-vault-pass