支持OSS托管加密

This commit is contained in:
yml2213
2026-08-16 22:38:31 +08:00
parent 7b7d23c743
commit eb06ec3c5f
6 changed files with 20 additions and 19 deletions
+2 -2
View File
@@ -111,8 +111,8 @@ BACKUP_OSS_URI=oss://hfb-backup
# 客户端加密密码短语(独立保管,与业务密钥一同纳入 KMS/密码管理)。 # 客户端加密密码短语(独立保管,与业务密钥一同纳入 KMS/密码管理)。
# 生成方式:openssl rand -hex 32 # 生成方式:openssl rand -hex 32
BACKUP_PASSPHRASE=change-to-random-backup-passphrase BACKUP_PASSPHRASE=change-to-random-backup-passphrase
# OSS 服务端 KMS 加密 Key ID,备份脚本强制使用,不可留空 # 可选:自有 KMS Key ID。留空时 Bucket 必须开启“OSS 完全托管”服务器端加密
BACKUP_KMS_KEY_ID=change-kms-key-id BACKUP_KMS_KEY_ID=
# XtraBackup 专用 MySQL 账号,部署脚本会幂等创建并授予最小备份权限。 # XtraBackup 专用 MySQL 账号,部署脚本会幂等创建并授予最小备份权限。
BACKUP_MYSQL_USER=hfb_backup BACKUP_MYSQL_USER=hfb_backup
# 生成方式:openssl rand -hex 24。不要和 MySQL 应用账号或 root 密码复用。 # 生成方式:openssl rand -hex 24。不要和 MySQL 应用账号或 root 密码复用。
+2 -3
View File
@@ -40,7 +40,6 @@ BACKUP_DIR
BACKUP_RESTORE_DIR BACKUP_RESTORE_DIR
BACKUP_OSS_URI BACKUP_OSS_URI
BACKUP_PASSPHRASE BACKUP_PASSPHRASE
BACKUP_KMS_KEY_ID
BACKUP_MYSQL_PASSWORD BACKUP_MYSQL_PASSWORD
``` ```
@@ -72,11 +71,11 @@ RAM 凭证只授予该 Bucket 的列举、读取、写入对象权限,不要
### 数据库在线备份与时间点恢复 ### 数据库在线备份与时间点恢复
生产 MySQL 开启了 `ROW` 格式 binlog 和崩溃安全刷盘。备份期间业务持续读写:每日用 XtraBackup 做物理全量备份,每分钟轮转并归档已关闭的 binlog。备份对象先做客户端加密,再强制以 OSS KMS 加密上传;远端仅在 payload、checksum 和 manifest 都上传成功后写入 `complete.env` 生产 MySQL 开启了 `ROW` 格式 binlog 和崩溃安全刷盘。备份期间业务持续读写:每日用 XtraBackup 做物理全量备份,每分钟轮转并归档已关闭的 binlog。备份对象先做客户端加密,再由 Bucket 的服务器端加密保护;远端仅在 payload、checksum 和 manifest 都上传成功后写入 `complete.env`
部署脚本会创建或更新 `BACKUP_MYSQL_USER`,该用户只有 XtraBackup 所需的全局备份权限和业务库只读权限,不开放远程 root。 部署脚本会创建或更新 `BACKUP_MYSQL_USER`,该用户只有 XtraBackup 所需的全局备份权限和业务库只读权限,不开放远程 root。
备份 Bucket 必须独立于业务 Bucket,备份 RAM 身份仅授予该 Bucket 的列举、读写对象及指定 KMS Key 的加解密权限。推荐 Bucket 开启版本控制和不可变保留策略。 备份 Bucket 必须独立于业务 Bucket开启“OSS 完全托管”服务器端加密和版本控制。备份 RAM 身份仅授予该 Bucket 的列举、读写对象权限;若填写 `BACKUP_KMS_KEY_ID`,再授予该 Key 的加解密权限。推荐配置不可变保留策略。
部署机需安装 `ossutil``openssl``flock`,并使用与 cron 相同的业务用户完成 `ossutil` 凭证配置;部署脚本会在启动服务前检查这些依赖。 部署机需安装 `ossutil``openssl``flock`,并使用与 cron 相同的业务用户完成 `ossutil` 凭证配置;部署脚本会在启动服务前检查这些依赖。
+3 -4
View File
@@ -22,7 +22,6 @@ require_archive_config() {
backup_require_env BACKUP_DIR >/dev/null backup_require_env BACKUP_DIR >/dev/null
backup_require_env BACKUP_OSS_URI >/dev/null backup_require_env BACKUP_OSS_URI >/dev/null
backup_require_env BACKUP_PASSPHRASE >/dev/null backup_require_env BACKUP_PASSPHRASE >/dev/null
backup_require_env BACKUP_KMS_KEY_ID >/dev/null
} }
closed_binlogs() { closed_binlogs() {
@@ -91,10 +90,10 @@ archive_one() {
printf 'created_at=%s\n' "$(date -Iseconds)" printf 'created_at=%s\n' "$(date -Iseconds)"
} > "${work_dir}/${object_id}.complete.env" } > "${work_dir}/${object_id}.complete.env"
backup_oss_upload_kms "${cipher_file}" "${remote_dir}/binlog.enc" backup_oss_upload "${cipher_file}" "${remote_dir}/binlog.enc"
backup_oss_upload_kms "${work_dir}/${object_id}.enc.sha256" "${remote_dir}/binlog.enc.sha256" backup_oss_upload "${work_dir}/${object_id}.enc.sha256" "${remote_dir}/binlog.enc.sha256"
# complete.env 最后上传,恢复程序只使用有该文件的 binlog。 # complete.env 最后上传,恢复程序只使用有该文件的 binlog。
backup_oss_upload_kms "${work_dir}/${object_id}.complete.env" "${remote_dir}/complete.env" backup_oss_upload "${work_dir}/${object_id}.complete.env" "${remote_dir}/complete.env"
write_state "${state_dir}" "${filename}" "${binlog_index}" "${raw_sha}" "${cipher_sha}" "${remote_dir}" write_state "${state_dir}" "${filename}" "${binlog_index}" "${raw_sha}" "${cipher_sha}" "${remote_dir}"
rm -f -- "${raw_file}" "${cipher_file}" "${work_dir}/${object_id}.enc.sha256" "${work_dir}/${object_id}.complete.env" rm -f -- "${raw_file}" "${cipher_file}" "${work_dir}/${object_id}.enc.sha256" "${work_dir}/${object_id}.complete.env"
} }
+9 -4
View File
@@ -153,13 +153,18 @@ backup_decrypt_file() {
unset passphrase unset passphrase
} }
backup_oss_upload_kms() { backup_oss_upload() {
local source="$1" local source="$1"
local destination="$2" local destination="$2"
local kms_key_id local kms_key_id
kms_key_id="$(backup_require_env BACKUP_KMS_KEY_ID)" kms_key_id="$(backup_env_value BACKUP_KMS_KEY_ID)"
ossutil cp "${source}" "${destination}" \ if [[ -n "${kms_key_id}" ]]; then
--encryption KMS --kms-master-key-id "${kms_key_id}" ossutil cp "${source}" "${destination}" \
--encryption KMS --kms-master-key-id "${kms_key_id}"
return
fi
# 未配置 KMS 时依赖 Bucket 已启用的 OSS 托管服务器端加密;备份载荷仍会先经过客户端加密。
ossutil cp "${source}" "${destination}"
} }
backup_validate_oss_uri() { backup_validate_oss_uri() {
+4 -5
View File
@@ -22,7 +22,6 @@ require_backup_config() {
backup_require_env BACKUP_DIR >/dev/null backup_require_env BACKUP_DIR >/dev/null
backup_require_env BACKUP_OSS_URI >/dev/null backup_require_env BACKUP_OSS_URI >/dev/null
backup_require_env BACKUP_PASSPHRASE >/dev/null backup_require_env BACKUP_PASSPHRASE >/dev/null
backup_require_env BACKUP_KMS_KEY_ID >/dev/null
backup_require_env BACKUP_MYSQL_USER >/dev/null backup_require_env BACKUP_MYSQL_USER >/dev/null
backup_require_env BACKUP_MYSQL_PASSWORD >/dev/null backup_require_env BACKUP_MYSQL_PASSWORD >/dev/null
} }
@@ -36,11 +35,11 @@ upload_backup_set() {
local remote_dir="${oss_uri}/mysql/full/${level}/${server_uuid}/${ts}" local remote_dir="${oss_uri}/mysql/full/${level}/${server_uuid}/${ts}"
backup_log "上传 ${level} 全量备份到 ${remote_dir}" backup_log "上传 ${level} 全量备份到 ${remote_dir}"
backup_oss_upload_kms "${local_dir}/mysql-full.tgz.enc" "${remote_dir}/mysql-full.tgz.enc" backup_oss_upload "${local_dir}/mysql-full.tgz.enc" "${remote_dir}/mysql-full.tgz.enc"
backup_oss_upload_kms "${local_dir}/manifest.env" "${remote_dir}/manifest.env" backup_oss_upload "${local_dir}/manifest.env" "${remote_dir}/manifest.env"
backup_oss_upload_kms "${local_dir}/mysql-full.tgz.enc.sha256" "${remote_dir}/mysql-full.tgz.enc.sha256" backup_oss_upload "${local_dir}/mysql-full.tgz.enc.sha256" "${remote_dir}/mysql-full.tgz.enc.sha256"
# complete.env 必须最后上传,作为远端原子完成标识。 # complete.env 必须最后上传,作为远端原子完成标识。
backup_oss_upload_kms "${local_dir}/complete.env" "${remote_dir}/complete.env" backup_oss_upload "${local_dir}/complete.env" "${remote_dir}/complete.env"
} }
full_backup() { full_backup() {
-1
View File
@@ -165,7 +165,6 @@ validate_env() {
backup_restore_dir="$(require_env BACKUP_RESTORE_DIR)" backup_restore_dir="$(require_env BACKUP_RESTORE_DIR)"
backup_oss_uri="$(require_env BACKUP_OSS_URI)" backup_oss_uri="$(require_env BACKUP_OSS_URI)"
require_env BACKUP_PASSPHRASE >/dev/null require_env BACKUP_PASSPHRASE >/dev/null
require_env BACKUP_KMS_KEY_ID >/dev/null
backup_user="$(require_env BACKUP_MYSQL_USER)" backup_user="$(require_env BACKUP_MYSQL_USER)"
require_env BACKUP_MYSQL_PASSWORD >/dev/null require_env BACKUP_MYSQL_PASSWORD >/dev/null
backend_uid="$(require_env BACKEND_UID)" backend_uid="$(require_env BACKEND_UID)"