pglift
PostgreSQL Automation Made Easy
About me π§
- Damien Clochard
- Co-founder of Dalibo π
- Active member of PostgreSQLFr Association
- Main developer of PostgreSQL Anonymizer
Dalibo π
- Open Source company
- Worker cooperative (SCOP)
- 20 years of PostgreSQL expertise
- Weβre hiring !
Why is PostgreSQL Automation so hard ? π€
- A new Postgres major version every year
- The full Postgres stack is complex
- SELinux is hard to implement
- Idempotency is a nightmare
pglift π
- Python library, independent from automation tools
- Works with all major version of Postgres
- Works on RHEL / Debian / Ubuntu
An interface between two worlds π
- A modern CLI
- A collection of Ansible modules
- Possibly more interfaces in the future ( k8s, Terraform/OpenTofu
)
The project ποΈ
- First commit in 2021 / In v1.x since 2023
- Key component of the Β« Dalibo Postgres Platform Β» product
- Fully open-source, No Enterprise Edition
- Transparent development (issues, MRs and exchanges
on GitLab)
https://gitlab.com/dalibo/pglift/
Contributors π₯
- Visible : (commits): Dalibo members
- Indirect : Dalibo members (βintegratorsβ)
- Invisible : our clients /
users
Components and scopes π―
An βinstanceβ, in pglift terminology, is composed of a
PostgreSQL cluster complemented by a number of satellite
components providing additional services such as backup or
monitoring.
The Stack π₯
- Adminstration : temBoard
- Backups : pgbackrest
- Monitoring : prometheus postgres exporter
- HA : Patroni
- Perf : PoWA
- β¦
Security π‘οΈ
- Services are launched with systemd user mode
- No need to be root
- No need to use sudo
- SELinux works out of the box
Configuration π
Highly Configurable
behavior guided by Daliboβs expertise or
upstream.
A global YAML configuration file
(settings.yaml
)
Environment variables
Config file templates ( postgresql.conf
,
pgbackrest.conf
, β¦)
Create an instance πͺ
$ pglift instance create foo --version 14 --port 5224
Create a standby node π
pglift instance create foo_standby \
--standby-for "host=foo.prod port=5224 user=replication" \
--standby-password
Password for the replication user:
Repeat for confirmation:
List the instances ποΈ
Instance info π
$ pglift instance get foo --output-format json
{
"name": "foo",
"version": "15",
"standby": null,
"port": 5224,
"settings": {
"shared_buffers": "8 GB",
...
}
Exec and Shell env π
Connect with exec
$ pglift instance exec foo -- psql
...
[14/foo] postgres@~=#
or connect with a shell env
$ pglift instance shell foo
$ psql
...
[14/foo] postgres@~=#
Modify the config βοΈ
$ pglift pgconf --instance foo set 'shared_buffers=3 GB'
or
$ pglift pgconf --instance foo edit
Clone a database π¬
$ pglift database create foo_db \
--clone-from "postgresql://postgres@prod_srv:5224/foo_db"
Major Upgrade π
$ pglift instance upgrade 14/foo --version 16
Setup a HA cluster β¨
$ pglift instance create foo \
--patroni-cluster=foocluster \
--patroni-node=foo1
Ansible - pglift modules π€
pglift offers an interface (collection of modules) for Ansible, it
allows management of these objects:
- database
- dsn_info
- instance ( Postgres + components )
- postgres_exporter
- role (in PostgreSQL)
Available on Galaxy π«
$ ansible-galaxy collection install dalibo.pglift
Describe an instance βοΈ
- name: my foo instances
hosts: all
become: true
become_user: postgres
tasks:
- name: production instance
dalibo.pglift.instance:
name: foo
state: started
port: 5224
# [...]
Run ! π
$ ansible-playbook -i inventory foo.yaml
Alter the shared buffers π€
- name: production instance
dalibo.pglift.instance:
name: foo
# [...]
restart_on_changes: true
settings:
max_connections: 150
shared_buffers: 2GB
unix_socket_directories: /tmp
Run Again ! π
$ ansible-playbook -i inventory foo.yaml
Declare a Database π’οΈ
- name: A database named pagila, owned by bob
dalibo.pglift.database:
instance: foo
name: pagila
owner: bob
settings:
work_mem: 3MB
Build a HA cluster β¨
- name: A foo instance on each host, managed by Patroni
dalibo.pglift.instance:
name: foo
version: 14
[...]
patroni:
cluster: foo-cluster
node: "{{ inventory_hostname }}"
postgresql:
connect_host: "{{ inventory_hostname }}"
restapi:
connect_address: "{{ inventory_hostname }}:8008"
listen: "{{ inventory_hostname }}:8008"
In a nutshell π°
- Operations are consistent wether you use the CLI or Ansible
- Idempotency !!!!!
- Rootless by default
- Continuous Developments
- Battle tested in large scale production environments
- Easy to integrate with AAP / Ansible Tower
Questions ? π
Letβs meet at the DALIBO booth !