observability.svc.plus/roles/pgsql/tasks/install.yml
2026-02-01 20:53:55 +08:00

205 lines
11 KiB
YAML

---
#--------------------------------------------------------------#
# Install PostgreSQL Packages & Extensions [pg_pkg]
#--------------------------------------------------------------#
# to install the latest postgres packages, use the `pg_ext` tag
- name: install postgres packages
become: true
tags: pg_pkg
block:
# this task will try to find each item in pg_extension_map first
# if found, the value will be used instead of the key
# if not found, the key will be not modified, and used as raw extension name
- name: lookup pg packages & extensions names
tags: [pg_extension, pg_ext]
become: false
connection: local
set_fact:
pg_packages_list: "{{ pg_packages_list_temp | default('', true) }}"
pg_extension_list: "{{ pg_extension_list_temp | default('', true) }}"
vars:
pg_packages_list_temp: |-
{% set pkg_map = package_map | default({}) %}
{% for pkg_list in pg_packages %}{% for pkg in pkg_list | trim | regex_replace('(,|\\s)+', ',') | regex_findall('([^,\\s]+)') | default([]) %}{% if pkg != '' %}{% if pkg in pkg_map %}{% set pkg = pkg_map[pkg] %}{% endif %}{% if not loop.first %},{% endif %}{{ pkg|replace('${pg_version}', pg_version|string)|replace('$v', pg_version|string) }}{% endif %}{% endfor %}
{% endfor %}
pg_extension_list_temp: |-
{% set pkg_map = package_map | default({}) %}
{% for ext_list in pg_extensions %}{% for ext in ext_list | trim | regex_replace('(,|\\s)+', ',') | regex_findall('([^,\\s]+)') | default([]) %}{% if ext != '' %}{% if ext in pkg_map %}{% set ext = pkg_map[ext] %}{% endif %}{% if not loop.first %},{% endif %}{{ ext|replace('${pg_version}', pg_version|string)|replace('$v', pg_version|string) }}{% endif %}{% endfor %}
{% endfor %}
# postgres pre-install setup: remove conflicting packages on EL 9+
- name: postgres pre-install setup
ignore_errors: true
tags: pg_pre
shell: |
dnf remove -y bpftool python3-perf || /bin/true
when: os_package|default('rpm') == 'rpm' and os_version|default(8)|int >= 9
# the bpftool python3-perf require the system llvm 19 conflict from pgdg-sysupdate llvm20 on el9/el10
# install postgres basic packages
- name: install postgres packages
environment: "{{ proxy_env | default({}) }}"
package: name={{ item }} state=present
with_items: "{{ pg_packages_list | trim | regex_findall('[^\\n]+') | map('replace', '$v', pg_version|string) | list | map('replace', '${pg_version}', pg_version|string) | map('regex_replace', '(,|\\s)+', ',' ) | list }}"
# install postgres extensions
- name: install postgres extensions
tags: [pg_extension, pg_ext]
environment: "{{ proxy_env | default({}) }}"
package: name={{ item }} state=latest
with_items: "{{ pg_extension_list | trim | regex_findall('([^\\n]+)') | map('replace', '$v', pg_version|string) | list | map('replace', '${pg_version}', pg_version|string) | map('regex_replace', '(,|\\s)+', ',' ) | list }}"
# fix rpm trash and unused service file, shut debian default service
- name: postgres post-install cleanup
tags: pg_post
ignore_errors: true
shell: |
{% if os_package|default('rpm') == 'rpm' %}
rm -rf /usr/lib/systemd/system/postgresql-{{ pg_version }}.service # rhel
rm -rf '/%{_sysconfigdir}' # introduced by patroni rpm
rm -rf '/%{_logdir}' # remove these if patroni rpm fixed
chown -R {{ pg_dbsu }}:postgres /var/run/postgresql /var/lib/pgsql || /bin/true;
{% elif os_package|default('rpm') == 'deb' %}
# kill the default debian service
systemctl stop --no-block postgresql # the auto-started debian/ubuntu service
systemctl stop --no-block postgresql@{{ pg_version|default('18') }}-main
systemctl disable --no-block postgresql
systemctl disable --no-block postgresql@{{ pg_version|default('18') }}-main
rm -rf /lib/systemd/system/postgresql.service rm -rf /lib/systemd/system/postgresql@.service
if ps -u postgres -o pid:1,command | grep -E 'postmaster|postgres:|-D' | grep 'config_file=/etc/postgresql/.*/main/postgresql.conf' ; then
{{ pg_bin_dir }}/pg_ctl -D /var/lib/postgresql/{{ pg_version }}/main stop --mode=immediate
fi
if ps -u postgres -o pid:1,command | grep -E 'postmaster|postgres:|-D' | grep 'config_file=/etc/postgresql/.*/main/postgresql.conf' ; then
sleep 2
ps -u postgres -o pid:1,command | grep -E 'postmaster|postgres:|-D' | grep '/etc/postgresql/*/main/postgresql.conf' | awk '{print $1}' | xargs kill -9
fi
rm -rf /lib/systemd/system/postgresql.service /lib/systemd/system/postgresql@.service
chown -R {{ pg_dbsu }}:postgres /var/run/postgresql /var/lib/postgresql /etc/postgresql || /bin/true;
{% endif %}
chown -R {{ pg_dbsu }}:postgres "{{ pg_dbsu_home }}"
systemctl daemon-reload;
/bin/true;
args: { executable: /bin/bash }
#--------------------------------------------------------------#
# Link Binary Dir [pg_link]
#--------------------------------------------------------------#
- name: link postgres home
tags: pg_link
file: src="{{ pg_home_dir }}" dest={{ pg_bin_dir | dirname }} state=link
vars: { pg_home_dir: "{{ pg_home_map[pg_mode] | replace('$v', pg_version) | replace('${pg_version}', pg_version )}}" }
#--------------------------------------------------------------#
# Setup Profile Path [pg_path]
#--------------------------------------------------------------#
# add {{ pg_bin_dir }} to PATH environment variable
- name: setup pgsql path
tags: pg_path
copy:
dest: /etc/profile.d/pgsql.sh
mode: 0755
content: |
export PATH="{{ pg_bin_dir }}:/pg/bin:$PATH"
export PGHOME={{ pg_bin_dir | dirname }}
export PGDATA={{ pg_data }}
export PGPORT={{ pg_port }}
export PGDATABASE={{ pg_primary_db }}
#--------------------------------------------------------------#
# Create Directories [pg_dir]
#--------------------------------------------------------------#
#--------------------------------------------------------------#
# Create Directory
#--------------------------------------------------------------#
# assumption:
# {{ pg_fs_main }} ,default: `/data/postgres` [fast ssd]
# {{ pg_fs_backup }} ,default: `/data/backups` [cheap hdd]
#--------------------------------------------------------------#
# /pg -> /data/postgres/pg-test-18 (soft link)
# /pg/data -> /data/postgres/pg-test-18/data
# /pg/backup -> /data/backups/pg-test-18/backup
#--------------------------------------------------------------#
- name: create pgsql directories
tags: pg_dir
become: true
block:
# assuming that node_data (/data) is already created in the node role
- name: create pgsql directories
file: path={{ item.path }} state=directory owner={{ item.owner|default(pg_dbsu) }} group={{ item.group|default('postgres') }} mode={{ item.mode }}
with_items:
- { path: "{{ pg_fs_main }}" ,mode: "0700" } # /data/postgres the main data dir
- { path: "{{ pg_fs_backup }}" ,mode: "0700" } # /data/backups the backup dir
- { path: "{{ pg_cluster_dir }}" ,mode: "0700" } # /data/postgres/pg-meta-18 the cluster dir
- { path: "{{ pg_cluster_dir }}/bin" ,mode: "0700" } # /data/postgres/pg-meta-18/bin postgres scripts
- { path: "{{ pg_cluster_dir }}/log" ,mode: "0750" } # /data/postgres/pg-meta-18/log log dir for pg components
- { path: "{{ pg_cluster_dir }}/tmp" ,mode: "0700" } # /data/postgres/pg-meta-18/tmp role/db init sql and log
- { path: "{{ pg_cluster_dir }}/cert" ,mode: "0700" } # /data/postgres/pg-meta-18/cert ssl certificates
- { path: "{{ pg_cluster_dir }}/conf" ,mode: "0700" } # /data/postgres/pg-meta-18/conf patroni and config
- { path: "{{ pg_cluster_dir }}/data" ,mode: "0700" } # /data/postgres/pg-meta-18/data main data dir
- { path: "{{ pg_cluster_dir }}/spool" ,mode: "0700" } # /data/postgres/pg-meta-18/spool pgbackrest temp
- { path: "{{ pg_backup_dir }}/backup" ,mode: "0700" } # /data/backups/pg-meta-18/backup local backup dir
- { path: "/var/run/postgresql" ,mode: "0755" } # pid directory for postgresql and pgbouncer
- { path: "/etc/patroni" ,mode: "0700" } # config dir for patroni
- { path: "/etc/pgbackrest" ,mode: "0700" } # config dir for pgbackrest
- { path: "/etc/pgbouncer" ,mode: "0700" } # config dir for pgbouncer
- { path: "/etc/pg_exporter" ,mode: "0700" } # config dir for pg_exporter
# create the `/pg` soft link
- name: link pgsql directories
file: src={{ item.src }} dest={{ item.dest }} state=link
with_items:
- { src: "{{ pg_backup_dir }}/backup" ,dest: "{{ pg_cluster_dir }}/backup" }
- { src: "{{ pg_cluster_dir }}" ,dest: "/pg" }
# do not create log dir inside data dir (create when data dir is not prefix of log dir)
- name: create log directories
file: path={{ item }} state=directory owner={{ pg_dbsu }} group=postgres mode=0750
with_items:
- "{% if not pg_log_dir.startswith(pg_data) %}{{ pg_log_dir }}{% else %}{{ patroni_log_dir }}{% endif %}"
- "{{ patroni_log_dir }}"
- "{{ pgbouncer_log_dir }}"
- "{{ pgbackrest_log_dir }}"
# make sure the /var/run/postgresql is created
- name: create tmpfiles.d for /var/run/postgresql
copy:
dest: /etc/tmpfiles.d/postgresql.conf
content: "d /var/run/postgresql 0755 {{ pg_dbsu }} postgres -"
owner: root
group: root
mode: '0644'
#--------------------------------------------------------------#
# PostgreSQL Bin Scripts [pg_bin]
#--------------------------------------------------------------#
# sync files/postgres -> /pg/bin/
- name: copy /pg/bin scripts
tags: pg_bin
copy: src=postgres/ dest=/pg/bin/ owner=root group=postgres mode=0755
#--------------------------------------------------------------#
# PostgreSQL / PSQL Alias [pg_alias]
#--------------------------------------------------------------#
- name: copy pgsql/psql alias
tags: pg_alias
template: src={{ item.src }} dest={{ item.dest }} owner={{ item.owner }} group={{ item.group }} mode={{ item.mode }}
with_items:
- { src: "pg-alias" ,dest: "/etc/profile.d/pg-alias.sh" ,owner: "root" ,group: "root" ,mode: "0644" }
- { src: "psqlrc" ,dest: "{{ pg_dbsu_home }}/.psqlrc" ,owner: "{{ pg_dbsu }}" ,group: "postgres" ,mode: "0600" }
#--------------------------------------------------------------#
# Create Dummy File [pg_dummy]
#--------------------------------------------------------------#
# reserve dummy file for disk-full emergency
- name: create pgsql dummy file
tags: pg_dummy
command: fallocate -l {{ pg_dummy_filesize|default('64MiB') }} /pg/dummy
...