- 添加 Harbor 快速恢复脚本 (harbor-quick-restore.sh) - 添加完整恢复指南 (HARBOR-RESTORE-GUIDE.md) - 添加版本信息文件 (VERSION.md) - 更新 .gitignore 排除敏感数据 - 配置 harbor git remote - 修复 Cloudflare Tunnel 配置 系统重装后可通过以下命令快速恢复: git clone http://192.168.1.83:33000/gao/ljwx-harbor.git cd ljwx-harbor ./harbor-quick-restore.sh
243 lines
8.8 KiB
YAML
243 lines
8.8 KiB
YAML
# Backup Scripts ConfigMap
|
|
---
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: backup-scripts
|
|
namespace: infra
|
|
labels:
|
|
app: database-backup
|
|
component: scripts
|
|
data:
|
|
backup-mysql.sh: |
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
BACKUP_DIR="/backups/mysql"
|
|
BACKUP_DATE=$(date +%Y-%m-%d-%H%M%S)
|
|
BACKUP_FILE="${BACKUP_DIR}/mysql-backup-${BACKUP_DATE}.sql.gz"
|
|
CHECKSUM_FILE="${BACKUP_FILE}.sha256"
|
|
METADATA_DIR="${BACKUP_DIR}/metadata"
|
|
METADATA_FILE="${METADATA_DIR}/${BACKUP_DATE}.json"
|
|
|
|
echo "========================================="
|
|
echo "MySQL Backup - Production Grade (PVC)"
|
|
echo "========================================="
|
|
echo "Started at: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
echo ""
|
|
|
|
mkdir -p "${BACKUP_DIR}" "${METADATA_DIR}"
|
|
|
|
echo "[1/5] Testing MySQL connection..."
|
|
if mysql -h "${MYSQL_HOST}" -P "${MYSQL_PORT}" -u root -p"${MYSQL_ROOT_PASSWORD}" -e "SELECT 1" &>/dev/null; then
|
|
echo " ✓ Connection successful"
|
|
else
|
|
echo " ✗ Connection failed"
|
|
exit 1
|
|
fi
|
|
|
|
echo ""
|
|
echo "[2/5] Getting database list..."
|
|
DB_LIST=$(mysql -h "${MYSQL_HOST}" -P "${MYSQL_PORT}" -u root -p"${MYSQL_ROOT_PASSWORD}" \
|
|
-e "SHOW DATABASES;" | grep -Ev "^(Database|information_schema|performance_schema|mysql|sys)$" || true)
|
|
DB_COUNT=$(echo "$DB_LIST" | grep -v '^$' | wc -l || echo 0)
|
|
echo " ✓ Found ${DB_COUNT} databases to backup"
|
|
|
|
echo ""
|
|
echo "[3/5] Creating backup..."
|
|
START_TIME=$(date +%s)
|
|
|
|
mysqldump \
|
|
-h "${MYSQL_HOST}" \
|
|
-P "${MYSQL_PORT}" \
|
|
-u root \
|
|
-p"${MYSQL_ROOT_PASSWORD}" \
|
|
--single-transaction \
|
|
--quick \
|
|
--lock-tables=false \
|
|
--all-databases \
|
|
--triggers \
|
|
--routines \
|
|
--events \
|
|
--hex-blob \
|
|
2>&1 | gzip -9 > "${BACKUP_FILE}"
|
|
|
|
END_TIME=$(date +%s)
|
|
DURATION=$((END_TIME - START_TIME))
|
|
BACKUP_SIZE=$(du -h "${BACKUP_FILE}" | cut -f1)
|
|
BACKUP_BYTES=$(stat -c%s "${BACKUP_FILE}" 2>/dev/null || stat -f%z "${BACKUP_FILE}")
|
|
|
|
echo " ✓ Backup created: ${BACKUP_SIZE}"
|
|
echo " ✓ Duration: ${DURATION}s"
|
|
|
|
echo ""
|
|
echo "[4/5] Generating checksum..."
|
|
CHECKSUM=$(sha256sum "${BACKUP_FILE}" | cut -d' ' -f1)
|
|
echo "${CHECKSUM} $(basename ${BACKUP_FILE})" > "${CHECKSUM_FILE}"
|
|
echo " ✓ SHA256: ${CHECKSUM:0:16}..."
|
|
|
|
echo ""
|
|
echo "[5/5] Writing metadata..."
|
|
MYSQL_VERSION=$(mysql -h "${MYSQL_HOST}" -P "${MYSQL_PORT}" -u root -p"${MYSQL_ROOT_PASSWORD}" -e 'SELECT VERSION()' -s -N 2>/dev/null || echo "unknown")
|
|
|
|
echo "{" > "${METADATA_FILE}"
|
|
echo " \"backup_date\": \"${BACKUP_DATE}\"," >> "${METADATA_FILE}"
|
|
echo " \"backup_file\": \"$(basename ${BACKUP_FILE})\"," >> "${METADATA_FILE}"
|
|
echo " \"backup_size_bytes\": ${BACKUP_BYTES}," >> "${METADATA_FILE}"
|
|
echo " \"backup_size_human\": \"${BACKUP_SIZE}\"," >> "${METADATA_FILE}"
|
|
echo " \"database_count\": ${DB_COUNT}," >> "${METADATA_FILE}"
|
|
echo " \"duration_seconds\": ${DURATION}," >> "${METADATA_FILE}"
|
|
echo " \"sha256\": \"${CHECKSUM}\"," >> "${METADATA_FILE}"
|
|
echo " \"mysql_version\": \"${MYSQL_VERSION}\"," >> "${METADATA_FILE}"
|
|
echo " \"hostname\": \"${MYSQL_HOST}\"," >> "${METADATA_FILE}"
|
|
echo " \"status\": \"success\"," >> "${METADATA_FILE}"
|
|
echo " \"backup_type\": \"full\"," >> "${METADATA_FILE}"
|
|
echo " \"storage_tier\": \"pvc-primary\"" >> "${METADATA_FILE}"
|
|
echo "}" >> "${METADATA_FILE}"
|
|
|
|
echo " ✓ Metadata saved"
|
|
echo ""
|
|
echo "========================================="
|
|
echo "✅ MySQL Backup completed successfully"
|
|
echo "========================================="
|
|
echo "File: ${BACKUP_FILE}"
|
|
echo "Size: ${BACKUP_SIZE}"
|
|
echo "Checksum: ${CHECKSUM:0:16}..."
|
|
echo "Finished at: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
echo "========================================="
|
|
|
|
backup-postgres.sh: |
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
export PATH=$PATH:/opt/bitnami/postgresql/bin
|
|
BACKUP_DIR="/backups/postgres"
|
|
BACKUP_DATE=$(date +%Y-%m-%d-%H%M%S)
|
|
BACKUP_FILE="${BACKUP_DIR}/postgres-backup-${BACKUP_DATE}.sql.gz"
|
|
CHECKSUM_FILE="${BACKUP_FILE}.sha256"
|
|
METADATA_DIR="${BACKUP_DIR}/metadata"
|
|
METADATA_FILE="${METADATA_DIR}/${BACKUP_DATE}.json"
|
|
|
|
echo "========================================="
|
|
echo "PostgreSQL Backup - Production Grade (PVC)"
|
|
echo "========================================="
|
|
echo "Started at: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
echo ""
|
|
|
|
mkdir -p "${BACKUP_DIR}" "${METADATA_DIR}"
|
|
|
|
echo "[1/5] Testing PostgreSQL connection..."
|
|
export PGPASSWORD="${POSTGRES_PASSWORD}"
|
|
|
|
if psql -h "${POSTGRES_HOST}" -p "${POSTGRES_PORT}" -U "${POSTGRES_USER}" -c "SELECT 1" &>/dev/null; then
|
|
echo " ✓ Connection successful"
|
|
else
|
|
echo " ✗ Connection failed"
|
|
exit 1
|
|
fi
|
|
|
|
echo ""
|
|
echo "[2/5] Getting database list..."
|
|
DB_LIST=$(psql -h "${POSTGRES_HOST}" -p "${POSTGRES_PORT}" -U "${POSTGRES_USER}" \
|
|
-t -c "SELECT datname FROM pg_database WHERE datistemplate = false AND datname != 'postgres';" | tr -d ' ' || true)
|
|
DB_COUNT=$(echo "$DB_LIST" | grep -v '^$' | wc -l || echo 0)
|
|
echo " ✓ Found ${DB_COUNT} databases to backup"
|
|
|
|
echo ""
|
|
echo "[3/5] Creating backup..."
|
|
START_TIME=$(date +%s)
|
|
|
|
pg_dumpall \
|
|
-h "${POSTGRES_HOST}" \
|
|
-p "${POSTGRES_PORT}" \
|
|
-U "${POSTGRES_USER}" \
|
|
--clean \
|
|
--if-exists \
|
|
2>&1 | gzip -9 > "${BACKUP_FILE}"
|
|
|
|
END_TIME=$(date +%s)
|
|
DURATION=$((END_TIME - START_TIME))
|
|
BACKUP_SIZE=$(du -h "${BACKUP_FILE}" | cut -f1)
|
|
BACKUP_BYTES=$(stat -c%s "${BACKUP_FILE}" 2>/dev/null || stat -f%z "${BACKUP_FILE}")
|
|
|
|
echo " ✓ Backup created: ${BACKUP_SIZE}"
|
|
echo " ✓ Duration: ${DURATION}s"
|
|
|
|
echo ""
|
|
echo "[4/5] Generating checksum..."
|
|
CHECKSUM=$(sha256sum "${BACKUP_FILE}" | cut -d' ' -f1)
|
|
echo "${CHECKSUM} $(basename ${BACKUP_FILE})" > "${CHECKSUM_FILE}"
|
|
echo " ✓ SHA256: ${CHECKSUM:0:16}..."
|
|
|
|
echo ""
|
|
echo "[5/5] Writing metadata..."
|
|
PG_VERSION=$(psql -h "${POSTGRES_HOST}" -p "${POSTGRES_PORT}" -U "${POSTGRES_USER}" -t -c "SELECT version()" 2>/dev/null | head -1 | tr -d ' ' || echo "unknown")
|
|
|
|
echo "{" > "${METADATA_FILE}"
|
|
echo " \"backup_date\": \"${BACKUP_DATE}\"," >> "${METADATA_FILE}"
|
|
echo " \"backup_file\": \"$(basename ${BACKUP_FILE})\"," >> "${METADATA_FILE}"
|
|
echo " \"backup_size_bytes\": ${BACKUP_BYTES}," >> "${METADATA_FILE}"
|
|
echo " \"backup_size_human\": \"${BACKUP_SIZE}\"," >> "${METADATA_FILE}"
|
|
echo " \"database_count\": ${DB_COUNT}," >> "${METADATA_FILE}"
|
|
echo " \"duration_seconds\": ${DURATION}," >> "${METADATA_FILE}"
|
|
echo " \"sha256\": \"${CHECKSUM}\"," >> "${METADATA_FILE}"
|
|
echo " \"postgres_version\": \"${PG_VERSION}\"," >> "${METADATA_FILE}"
|
|
echo " \"hostname\": \"${POSTGRES_HOST}\"," >> "${METADATA_FILE}"
|
|
echo " \"status\": \"success\"," >> "${METADATA_FILE}"
|
|
echo " \"backup_type\": \"full\"," >> "${METADATA_FILE}"
|
|
echo " \"storage_tier\": \"pvc-primary\"" >> "${METADATA_FILE}"
|
|
echo "}" >> "${METADATA_FILE}"
|
|
|
|
echo " ✓ Metadata saved"
|
|
echo ""
|
|
echo "========================================="
|
|
echo "✅ PostgreSQL Backup completed successfully"
|
|
echo "========================================="
|
|
echo "File: ${BACKUP_FILE}"
|
|
echo "Size: ${BACKUP_SIZE}"
|
|
echo "Checksum: ${CHECKSUM:0:16}..."
|
|
echo "Finished at: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
echo "========================================="
|
|
|
|
cleanup-old-backups.sh: |
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
RETENTION_DAYS=${RETENTION_DAYS:-7}
|
|
BACKUP_BASE="/backups"
|
|
|
|
echo "========================================="
|
|
echo "Cleanup Old Backups"
|
|
echo "Retention: ${RETENTION_DAYS} days"
|
|
echo "========================================="
|
|
|
|
for DB_TYPE in mysql postgres; do
|
|
BACKUP_DIR="${BACKUP_BASE}/${DB_TYPE}"
|
|
|
|
if [ ! -d "${BACKUP_DIR}" ]; then
|
|
echo "Skipping ${DB_TYPE} (directory not found)"
|
|
continue
|
|
fi
|
|
|
|
echo ""
|
|
echo "Cleaning ${DB_TYPE} backups..."
|
|
|
|
DELETED=0
|
|
while IFS= read -r file; do
|
|
rm -f "$file"
|
|
DELETED=$((DELETED + 1))
|
|
done < <(find "${BACKUP_DIR}" -name "*.sql.gz" -type f -mtime +${RETENTION_DAYS} 2>/dev/null || true)
|
|
|
|
find "${BACKUP_DIR}" -name "*.sha256" -type f -mtime +${RETENTION_DAYS} -delete 2>/dev/null || true
|
|
find "${BACKUP_DIR}/metadata" -name "*.json" -type f -mtime +${RETENTION_DAYS} -delete 2>/dev/null || true
|
|
|
|
echo " ✓ Deleted ${DELETED} old backups"
|
|
CURRENT=$(find "${BACKUP_DIR}" -name "*.sql.gz" -type f 2>/dev/null | wc -l)
|
|
echo " ✓ Current backups: ${CURRENT}"
|
|
done
|
|
|
|
echo ""
|
|
echo "========================================="
|
|
echo "✅ Cleanup completed"
|
|
echo "========================================="
|