aboutsummaryrefslogtreecommitdiff
path: root/docker
diff options
context:
space:
mode:
Diffstat (limited to 'docker')
-rw-r--r--docker/mariadb/mariadb-server/Dockerfile.j25
-rw-r--r--docker/mariadb/mariadb-server/backup_replica.sh135
2 files changed, 139 insertions, 1 deletions
diff --git a/docker/mariadb/mariadb-server/Dockerfile.j2 b/docker/mariadb/mariadb-server/Dockerfile.j2
index 2be384f6d..b0f49ac09 100644
--- a/docker/mariadb/mariadb-server/Dockerfile.j2
+++ b/docker/mariadb/mariadb-server/Dockerfile.j2
@@ -39,9 +39,12 @@ COPY mariadb_sudoers /etc/sudoers.d/kolla_mariadb_sudoers
COPY extend_start.sh /usr/local/bin/kolla_extend_start
COPY security_reset.expect /usr/local/bin/kolla_security_reset
COPY backup.sh /usr/local/bin/kolla_mariadb_backup.sh
+COPY backup_replica.sh /usr/local/bin/kolla_mariadb_backup_replica.sh
RUN chmod 644 /usr/local/bin/kolla_extend_start \
- && chmod 755 /usr/local/bin/kolla_security_reset /usr/local/bin/kolla_mariadb_backup.sh \
+ && chmod 755 /usr/local/bin/kolla_security_reset \
+ /usr/local/bin/kolla_mariadb_backup.sh \
+ /usr/local/bin/kolla_mariadb_backup_replica.sh \
&& chmod 750 /etc/sudoers.d \
&& chmod 440 /etc/sudoers.d/kolla_mariadb_sudoers \
&& rm -rf /var/lib/mysql/*
diff --git a/docker/mariadb/mariadb-server/backup_replica.sh b/docker/mariadb/mariadb-server/backup_replica.sh
new file mode 100644
index 000000000..7f86a18a7
--- /dev/null
+++ b/docker/mariadb/mariadb-server/backup_replica.sh
@@ -0,0 +1,135 @@
+#!/usr/bin/env bash
+
+set -eu
+set -o pipefail
+
+BACKUP_DIR=/backup/
+DEFAULT_MY_CNF="/etc/mysql/my.cnf"
+REPLICA_MY_CNF="$(mktemp)"
+RETRY_INTERVAL=5 # Interval between retries (in seconds)
+MAX_RETRIES=12 # Max retries (12 retries * 5 seconds = 60 seconds)
+
+# Cleanup function to remove the REPLICA_MY_CNF file
+cleanup() {
+ rm -f "${REPLICA_MY_CNF}"
+}
+
+# Set trap to ensure cleanup occurs on exit or error
+trap cleanup EXIT
+
+cd "${BACKUP_DIR}"
+
+# Execute a full backup
+backup_full() {
+ echo "Taking a full backup"
+ LAST_FULL_DATE=$(date +%d-%m-%Y-%s)
+ mariabackup \
+ --defaults-file="${REPLICA_MY_CNF}" \
+ --backup \
+ --stream=mbstream \
+ --history="${LAST_FULL_DATE}" | gzip > \
+ "${BACKUP_DIR}/mysqlbackup-${LAST_FULL_DATE}.qp.mbc.mbs.gz" && \
+ echo "${LAST_FULL_DATE}" > "${BACKUP_DIR}/last_full_date"
+}
+
+# Execute an incremental backup
+backup_incremental() {
+ if [ -r "${BACKUP_DIR}/last_full_date" ]; then
+ LAST_FULL_DATE=$(cat "${BACKUP_DIR}/last_full_date")
+ else
+ LAST_FULL_DATE=""
+ fi
+ if [ ! -z "${LAST_FULL_DATE}" ]; then
+ echo "Taking an incremental backup"
+ mariabackup \
+ --defaults-file="${REPLICA_MY_CNF}" \
+ --backup \
+ --stream=mbstream \
+ --incremental-history-name="${LAST_FULL_DATE}" \
+ --history="${LAST_FULL_DATE}" | gzip > \
+ "${BACKUP_DIR}/incremental-$(date +%H)-mysqlbackup-${LAST_FULL_DATE}.qp.mbc.mbs.gz"
+ else
+ echo "Error: Full backup don't exist."
+ exit 1
+ fi
+}
+
+# Retry logic for database queries
+retry_mysql_query() {
+ local query="$1"
+ local result=""
+ local attempt=1
+
+ while [ ${attempt} -le ${MAX_RETRIES} ]; do
+ result=$(mysql -h "${HOST}" -u "${USER}" -p"${PASS}" -s -N -e "${query}" 2>/dev/null || true)
+ if [ -n "${result}" ]; then
+ echo "${result}"
+ return 0
+ fi
+ echo "Attempt ${attempt}/${MAX_RETRIES} failed. Retrying in ${RETRY_INTERVAL} seconds..."
+ sleep "${RETRY_INTERVAL}"
+ attempt=$((attempt + 1))
+ done
+
+ echo "Error: Failed to execute the query after ${MAX_RETRIES} attempts."
+ return 1
+}
+
+get_and_set_replica_server() {
+ HOST="$(grep '^host' "${DEFAULT_MY_CNF}" | awk -F '=' '{print $2}' | xargs)"
+ USER="$(grep '^user' "${DEFAULT_MY_CNF}" | awk -F '=' '{print $2}' | xargs)"
+ PASS="$(grep '^password' "${DEFAULT_MY_CNF}" | awk -F '=' '{print $2}' | xargs)"
+
+ ALL_HOSTS_SELECT="SELECT REGEXP_REPLACE(VARIABLE_VALUE, ':[0-9]*','') FROM information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses';"
+ ALL_HOSTS=$(retry_mysql_query "${ALL_HOSTS_SELECT}")
+ if [ -z "${ALL_HOSTS}" ]; then
+ echo "Backup failed due to inability to fetch a list of servers."
+ exit 1
+ fi
+
+ ACTIVE_HOST_SELECT='SELECT @@hostname;'
+ ACTIVE_HOST=$(retry_mysql_query "${ACTIVE_HOST_SELECT}" | xargs getent hosts | awk '{print $1}')
+ if [ -z "${ACTIVE_HOST}" ]; then
+ echo "Backup failed due to inability to fetch active host."
+ exit 1
+ fi
+
+ # Multinode
+ if echo "${ALL_HOSTS}" | grep -q ','; then
+ for server in $(echo "${ALL_HOSTS}" | tr ',' '\n'); do
+ if [[ "${server}" != "${ACTIVE_HOST}" ]]; then
+ REPLICA_HOST="${server}"
+ break
+ fi
+ done
+ # Single node
+ else
+ REPLICA_HOST="${ALL_HOSTS}"
+ fi
+ if [ -z "${REPLICA_HOST}" ]; then
+ echo "Backup failed due to inability to determine replica host."
+ exit 1
+ fi
+
+ cp "${DEFAULT_MY_CNF}" "${REPLICA_MY_CNF}"
+ sed -i "s/${HOST}/${REPLICA_HOST}/g" "${REPLICA_MY_CNF}"
+}
+
+if [ -n "${BACKUP_TYPE}" ]; then
+ get_and_set_replica_server
+ case "${BACKUP_TYPE}" in
+ "full")
+ backup_full
+ ;;
+ "incremental")
+ backup_incremental
+ ;;
+ *)
+ echo "Only full or incremental options are supported."
+ exit 1
+ ;;
+ esac
+else
+ echo "You need to specify either full or incremental backup options."
+ exit 1
+fi