From 1ee3ce8401e36bab041688abaaed855edcfb299a Mon Sep 17 00:00:00 2001 From: yohan <783b8c87@scimetis.net> Date: Sun, 14 Apr 2024 19:39:49 +0200 Subject: [PATCH] Use duplicity directly on volumes to improve performance and benefit from reduced incremental backup sizes. --- backup_ovh1.yml | 29 ++++++----------------------- tasks/backup_mysql_db.yml | 24 ++++++++++++++++++++++++ tasks/backup_volume.yml | 19 +++++++++++++++++++ 3 files changed, 49 insertions(+), 23 deletions(-) create mode 100755 tasks/backup_mysql_db.yml create mode 100755 tasks/backup_volume.yml diff --git a/backup_ovh1.yml b/backup_ovh1.yml index cc8d2bb..47436da 100755 --- a/backup_ovh1.yml +++ b/backup_ovh1.yml @@ -13,32 +13,15 @@ path: "{{ WORKDIR }}/backup" state: directory - - name: Archive volumes - ansible.builtin.command: "tar -czf {{ WORKDIR }}/backup/{{ item }}.tar.gz -C /mnt/volumes {{ item }}" - with_items: "{{ BACKUP_OVH1_VOLUMES }}" - - - name: Find lastest MySQL DB dump - ansible.builtin.shell: "cd /mnt/volumes; ls -tr mysql-server_dumps/data/mysql_dump-mysql_*" - register: MySQL_dump - - - name: Find lastest applications DB dump - ansible.builtin.shell: "cd /mnt/volumes; ls -tr mysql-server_dumps/data/mysql_dump_*" - register: DBs_dump - - - name: Archive DB dumps - ansible.builtin.command: "tar -czf {{ WORKDIR }}/backup/mysql-server_dumps.tar.gz -C /mnt/volumes {{ MySQL_dump.stdout_lines | last }} {{ DBs_dump.stdout_lines | last }}" - with_items: "{{ BACKUP_OVH1_VOLUMES }}" - -# python3-swiftclient is a requirement of duplicity + # python3-swiftclient is a requirement of duplicity - name: Install python3-swiftclient ansible.builtin.package: name: python3-swiftclient state: present - - name: Backup with duplicity - ansible.builtin.command: "duplicity --num-retries 3 --full-if-older-than 1M --progress --archive-dir {{ ARCHIVE_DIR }} --name {{ lookup('env','BACKUP_WORKFLOW') }} --allow-source-mismatch '{{ WORKDIR }}/backup' swift://{{ lookup('env','BACKUP_WORKFLOW') }}" - environment: "{{ DUPLICITY_ENVIRONMENT }}" + - name: Archive volume + ansible.builtin.include_tasks: "tasks/backup_volume.yml" + with_items: "{{ BACKUP_OVH1_VOLUMES }}" - - name: Clean old duplicity backups - ansible.builtin.command: "duplicity remove-older-than 2M --archive-dir {{ ARCHIVE_DIR }} --name {{ lookup('env','BACKUP_WORKFLOW') }} --allow-source-mismatch --force swift://{{ lookup('env','BACKUP_WORKFLOW') }}" - environment: "{{ DUPLICITY_ENVIRONMENT }}" + - name: Archive MySQL DB + ansible.builtin.include_tasks: "tasks/backup_mysql_db.yml" diff --git a/tasks/backup_mysql_db.yml b/tasks/backup_mysql_db.yml new file mode 100755 index 0000000..b79cb69 --- /dev/null +++ b/tasks/backup_mysql_db.yml @@ -0,0 +1,24 @@ +--- +- name: Create backup directory + ansible.builtin.file: + path: "{{ WORKDIR }}/backup/MySQL_DB" + state: directory + +- name: Find lastest MySQL DB dump + ansible.builtin.shell: "cd /mnt/volumes; ls -tr mysql-server_dumps/data/mysql_dump-mysql_*" + register: MySQL_dump + +- name: Find lastest applications DB dump + ansible.builtin.shell: "cd /mnt/volumes; ls -tr mysql-server_dumps/data/mysql_dump_*" + register: DBs_dump + +- name: Archive DB dumps + ansible.builtin.command: "cp -a /mnt/volumes/{{ MySQL_dump.stdout_lines | last }} /mnt/volumes/{{ DBs_dump.stdout_lines | last }} {{ WORKDIR }}/backup/MySQL_DB/" + +- name: Backup with duplicity + ansible.builtin.command: "duplicity --num-retries 3 --full-if-older-than 1M --progress --archive-dir {{ ARCHIVE_DIR }} --name MySQL_DB --allow-source-mismatch '{{ WORKDIR }}/backup/MySQL_DB' swift://{{ lookup('env','BACKUP_WORKFLOW') }}" + environment: "{{ DUPLICITY_ENVIRONMENT }}" + +- name: Clean old duplicity backups + ansible.builtin.command: "duplicity remove-older-than 2M --archive-dir {{ ARCHIVE_DIR }} --name MySQL_DB --allow-source-mismatch --force swift://{{ lookup('env','BACKUP_WORKFLOW') }}" + environment: "{{ DUPLICITY_ENVIRONMENT }}" diff --git a/tasks/backup_volume.yml b/tasks/backup_volume.yml new file mode 100755 index 0000000..7cb4ae7 --- /dev/null +++ b/tasks/backup_volume.yml @@ -0,0 +1,19 @@ +--- +- name: Find hard links + ansible.builtin.command: "find '/mnt/volumes/{{ item }}' -type f -links +1" + register: find_hard_links + +# Duplicity does not support hard links +- name: Assert that there is no hard links in /mnt/volumes/{{ item }} + ansible.builtin.assert: + that: + - find_hard_links.stdout | length = 0 + msg: "Duplicity does not support hard links." + +- name: Backup with duplicity + ansible.builtin.command: "duplicity --num-retries 3 --full-if-older-than 1M --progress --archive-dir {{ ARCHIVE_DIR }} --name {{ item }} --allow-source-mismatch '/mnt/volumes/{{ item }}' swift://{{ lookup('env','BACKUP_WORKFLOW') }}" + environment: "{{ DUPLICITY_ENVIRONMENT }}" + +- name: Clean old duplicity backups + ansible.builtin.command: "duplicity remove-older-than 2M --archive-dir {{ ARCHIVE_DIR }} --name {{ item }} --allow-source-mismatch --force swift://{{ lookup('env','BACKUP_WORKFLOW') }}" + environment: "{{ DUPLICITY_ENVIRONMENT }}"