From d7d7f4838a387b56eda1da5eae4dee796bea1a5c Mon Sep 17 00:00:00 2001 From: ace Date: Fri, 11 Aug 2023 10:01:30 +0300 Subject: [PATCH] first commit --- .gitignore | 2 ++ README.md | 36 +++++++++++++++++++ ansible-roles.yaml | 6 ++++ ansible.cfg | 10 ++++++ inventory/group_vars/all.yaml | 15 ++++++++ inventory/hosts | 2 ++ postgresql.yaml | 68 +++++++++++++++++++++++++++++++++++ requirements.txt | 28 +++++++++++++++ requirements.yaml | 49 +++++++++++++++++++++++++ vars/postgresql.yaml | 30 ++++++++++++++++ 10 files changed, 246 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 ansible-roles.yaml create mode 100644 ansible.cfg create mode 100644 inventory/group_vars/all.yaml create mode 100644 inventory/hosts create mode 100644 postgresql.yaml create mode 100644 requirements.txt create mode 100644 requirements.yaml create mode 100644 vars/postgresql.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1a9ecc7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.galaxy_install_info +roles diff --git a/README.md b/README.md new file mode 100644 index 0000000..b942d4e --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +Deploy PostgreSQL + +## Install ansible and requirements in virtualenv + + mkvirtualenv ansible-7.6.0 + pip install -r requirements.txt + deactivate + workon ansible-7.6.0 + +## Install roles + + ansible-playbook ansible-roles.yaml + +## Install PostgreSQL + + ansible-playbook -i inventory/hosts postgresql.yaml -u almalinux + +## PostgreSQL options example + + postgresql_custom_parameters: + max_connections: '2000' + +## Backup options example + + postgresql_wal_g_install: true + wal_g_config: >- + {{ + { + "AWS_ACCESS_KEY_ID": "YOUR_ACCESS_KEY_ID", + "AWS_SECRET_ACCESS_KEY": "YOUR_SECRET_ACCESS_KEY", + "AWS_ENDPOINT": "https://s3.amazon.com", + "WALG_S3_PREFIX": "s3://wal-g/pgsql-1", + "WALG_LIBSODIUM_KEY": "29b43e2f46adcaf9f0d635d9fe4934e3227b3cbd13e2b19c7b28c16a581cc15c" + "AWS_S3_FORCE_PATH_STYLE": "true" + } + }} diff --git a/ansible-roles.yaml b/ansible-roles.yaml new file mode 100644 index 0000000..cdabefb --- /dev/null +++ b/ansible-roles.yaml @@ -0,0 +1,6 @@ +- hosts: localhost + gather_facts: false + tasks: + - name: Install roles + local_action: ansible.builtin.command ansible-galaxy install -r requirements.yaml -p roles + diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..f2b2b4a --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,10 @@ +[defaults] +host_key_checking = False +pipelining = True +callback_whitelist = timer, profile_tasks +forks = 50 +roles_path = roles + +[ssh_connection] +pipelining = True +ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null diff --git a/inventory/group_vars/all.yaml b/inventory/group_vars/all.yaml new file mode 100644 index 0000000..61c3ecc --- /dev/null +++ b/inventory/group_vars/all.yaml @@ -0,0 +1,15 @@ +postgresql_wal_g_install: false +wal_g_config: >- + {{ + { + "AWS_ACCESS_KEY_ID": "YOUR_ACCESS_KEY_ID", + "AWS_SECRET_ACCESS_KEY": "YOUR_SECRET_ACCESS_KEY", + "AWS_ENDPOINT": "https://s3.amazon.com", + "WALG_S3_PREFIX": "s3://wal-g/pgsql-1", + "WALG_LIBSODIUM_KEY": "29b43e2f46adcaf9f0d635d9fe4934e3227b3cbd13e2b19c7b28c16a581cc15c", + "AWS_S3_FORCE_PATH_STYLE": "true" + } + }} + +postgresql_custom_parameters: + max_connections: '2000' diff --git a/inventory/hosts b/inventory/hosts new file mode 100644 index 0000000..2bc611b --- /dev/null +++ b/inventory/hosts @@ -0,0 +1,2 @@ +[postgresql] +postgresql-1 ansible_host=192.168.79.37 diff --git a/postgresql.yaml b/postgresql.yaml new file mode 100644 index 0000000..4801bab --- /dev/null +++ b/postgresql.yaml @@ -0,0 +1,68 @@ +- hosts: localhost + gather_facts: false + tasks: + - name: Print Ansible version + debug: + msg: "{{ ansible_version }}" + +- hosts: all,!localhost + gather_facts: false + tasks: + - name: Wait 300 seconds + ansible.builtin.wait_for_connection: + timeout: 300 + +- hosts: all,!localhost + tasks: + - name: Include PostgreSQL vars + ansible.builtin.include_vars: "{{ lookup('first_found', params) }}" + vars: + params: + files: + - "{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_major_version'] }}.yaml" + - "{{ ansible_facts['distribution'] }}-{{ ansible_facts['distribution_version'] }}.yaml" + - "{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_major_version'] }}.yaml" + - "{{ ansible_facts['os_family'] }}-{{ ansible_facts['distribution_version'] }}.yaml" + - '{{ ansible_distribution }}.yaml' + - '{{ ansible_os_family }}.yaml' + - postgresql.yaml + paths: + - 'vars' + +- hosts: all,!localhost + become: true + tasks: + - name: Debian based repository + when: ansible_facts['os_family'] == "Debian" + block: + - name: Add repository for Debian + copy: + dest: /etc/apt/sources.list.d/mirror.0xace.cc.list + content: | + deb [trusted=yes] https://mirror.0xace.cc/debian/consul/ default all + deb [trusted=yes] https://mirror.0xace.cc/debian/custom/ default all + + - name: RHEL based repository + when: ansible_facts['os_family'] == "RedHat" + block: + - name: Add custom 0xace.cc repository for RHEL + ansible.builtin.yum_repository: + name: "rhel-custom" + description: "RHEL custom 0xace.cc repository" + file: "mirror.0xace.cc" + baseurl: "https://mirror.0xace.cc/rhel/$releasever/custom" + gpgcheck: false + enabled: true + +- hosts: postgresql + gather_facts: true + become: true + tasks: + - import_role: + name: postgresql + - import_role: + name: pgbouncer + - import_role: + name: postgres-exporter + - import_role: + name: node-exporter diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1347991 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,28 @@ +ansible==7.6.0 +ansible-core==2.14.7 +awscli==1.28.0 +awscli-plugin-endpoint==0.4 +botocore==1.30.0 +certifi==2023.5.7 +cffi==1.15.1 +charset-normalizer==3.1.0 +colorama==0.4.4 +cryptography==41.0.1 +docutils==0.16 +hvac==1.1.1 +idna==3.4 +Jinja2==3.1.2 +jmespath==1.0.1 +MarkupSafe==2.1.3 +packaging==23.1 +pyasn1==0.5.0 +pycparser==2.21 +pyhcl==0.4.4 +python-dateutil==2.8.2 +PyYAML==5.4.1 +requests==2.31.0 +resolvelib==0.8.1 +rsa==4.7.2 +s3transfer==0.6.1 +six==1.16.0 +urllib3==1.26.16 diff --git a/requirements.yaml b/requirements.yaml new file mode 100644 index 0000000..5f8535e --- /dev/null +++ b/requirements.yaml @@ -0,0 +1,49 @@ +--- +- src: https://gitea.geekhome.org/ansible-galaxy/podman.git + scm: git + name: podman +- src: https://gitea.geekhome.org/ansible-galaxy/docker.git + scm: git + name: docker +- src: https://gitea.geekhome.org/ansible-galaxy/hostname.git + scm: git + name: hostname +- src: https://gitea.geekhome.org/ansible-galaxy/hosts.git + scm: git + name: hosts +- src: https://gitea.geekhome.org/ansible-galaxy/haproxy.git + scm: git + name: haproxy +- src: https://gitea.geekhome.org/ansible-galaxy/selinux.git + scm: git + name: selinux +- src: https://gitea.geekhome.org/ansible-galaxy/postgresql.git + scm: git + name: postgresql +- src: https://gitea.geekhome.org/ansible-galaxy/patroni.git + scm: git + name: patroni +- src: https://gitea.geekhome.org/ansible-galaxy/wal-g.git + scm: git + name: wal-g +- src: https://gitea.geekhome.org/ansible-galaxy/pgbouncer.git + scm: git + name: pgbouncer +- src: https://gitea.geekhome.org/ansible-galaxy/consul.git + scm: git + name: consul +- src: https://gitea.geekhome.org/ansible-galaxy/keepalived.git + scm: git + name: keepalived +- src: https://gitea.geekhome.org/ansible-galaxy/bird.git + scm: git + name: bird +- src: https://gitea.geekhome.org/ansible-galaxy/cacert.git + scm: git + name: cacert +- src: https://gitea.geekhome.org/ansible-galaxy/node-exporter.git + scm: git + name: node-exporter +- src: https://gitea.geekhome.org/ansible-galaxy/postgres-exporter.git + scm: git + name: postgres-exporter diff --git a/vars/postgresql.yaml b/vars/postgresql.yaml new file mode 100644 index 0000000..a224dc2 --- /dev/null +++ b/vars/postgresql.yaml @@ -0,0 +1,30 @@ +pgbouncer_client_tls_key_file: "{{ pgbouncer_postgresql_ssl_path }}/cert.key" +pgbouncer_client_tls_cert_file: "{{ pgbouncer_postgresql_ssl_path }}/cert.crt" +pgbouncer_systemd_user: "postgres" +pgbouncer_systemd_group: "postgres" +pgbouncer_postgresql_major_version: "{{ postgresql_major_version }}" +pgbouncer_postgresql_superuser_username: "{{ postgresql_superuser_username }}" +pgbouncer_postgresql_superuser_password: "{{ postgresql_superuser_password }}" + +postgresql_backup_parameters: + archive_command: "{{ postgresql_archive_command if postgresql_wal_g_install else 'cd .' }}" + restore_command: "{{ postgresql_restore_command if postgresql_wal_g_install else 'cd .' }}" + archive_mode: "on" + archive_timeout: "1800s" + +postgresql_archive_command: "{{ 'http_proxy=' ~ wal_g_http_proxy ~ ' ' if wal_g_http_proxy is defined else '' }}{{ 'https_proxy=' ~ wal_g_https_proxy ~ ' ' if wal_g_https_proxy is defined else 'https_proxy=' ~ wal_g_http_proxy ~ ' ' if wal_g_http_proxy is defined else '' }}{{ wal_g_pg_binary_name ~ ' --config ' ~ wal_g_pg_home_dir ~ '/' ~ wal_g_config_name ~ ' wal-push %p' if postgresql_wal_g_install else '' }}" +# "restore_command" written to recovery.conf when configuring follower (create replica) +postgresql_restore_command: "{{ 'http_proxy=' ~ wal_g_http_proxy ~ ' ' if wal_g_http_proxy is defined else '' }}{{ 'https_proxy=' ~ wal_g_https_proxy ~ ' ' if wal_g_https_proxy is defined else 'https_proxy=' ~ wal_g_http_proxy ~ ' ' if wal_g_http_proxy is defined else '' }}{{ wal_g_pg_binary_name ~ ' --config ' ~ wal_g_pg_home_dir ~ '/' ~ wal_g_config_name ~ ' wal-fetch %f %p' if postgresql_wal_g_install else '' }}" +postgresql_restore_dbs_from_backup_command: "{{ 'http_proxy=' ~ wal_g_http_proxy ~ ' ' if wal_g_http_proxy is defined else '' }}{{ 'https_proxy=' ~ wal_g_https_proxy ~ ' ' if wal_g_https_proxy is defined else 'https_proxy=' ~ wal_g_http_proxy ~ ' ' if wal_g_http_proxy is defined else '' }}{{ postgresql_wal_g_binary_name ~ ' --config ' ~ postgresql_home_dir ~ '/' ~ postgresql_wal_g_restore_config_name ~ ' backup-fetch ' ~ postgresql_data_dir ~ ' ' ~ postgresql_wal_g_restore_backup_name }}" +postgresql_restore_wals_from_backup_command: "{{ 'http_proxy=' ~ wal_g_http_proxy ~ ' ' if wal_g_http_proxy is defined else '' }}{{ 'https_proxy=' ~ wal_g_https_proxy ~ ' ' if wal_g_https_proxy is defined else 'https_proxy=' ~ wal_g_http_proxy ~ ' ' if wal_g_http_proxy is defined else '' }}{{ postgresql_wal_g_binary_name ~ ' --config ' ~ postgresql_home_dir ~ '/' ~ postgresql_wal_g_restore_config_name ~ ' wal-fetch %f %p' }}" + +# postgresql_restore_command: "wal-g wal-fetch %f %p" # restore WAL-s using WAL-G +# postgresql_restore_command: "pgbackrest --stanza={{ pgbackrest_stanza }} archive-get %f %p" # restore WAL-s using pgbackrest +# postgresql_restore_command: "pg_probackup-{{ pg_probackup_version }} archive-get -B {{ pg_probackup_dir }} --instance {{ pg_probackup_instance }} --wal-file-path=%p --wal-file-name=%f" # restore WAL-s using pg_probackup + +# WAL-G +wal_g_pg: "{{ postgresql_wal_g_install }}" +wal_g_pg_binary_name: "wal-g-pg" +wal_g_config_name: ".walg.json" +wal_g_restore_config_name: ".walg-restore.json" +wal_g_pg_home_dir: "{{ postgresql_home_dir }}"