支持OSS托管加密
This commit is contained in:
@@ -111,8 +111,8 @@ BACKUP_OSS_URI=oss://hfb-backup
|
||||
# 客户端加密密码短语(独立保管,与业务密钥一同纳入 KMS/密码管理)。
|
||||
# 生成方式:openssl rand -hex 32
|
||||
BACKUP_PASSPHRASE=change-to-random-backup-passphrase
|
||||
# OSS 服务端 KMS 加密 Key ID,备份脚本强制使用,不可留空。
|
||||
BACKUP_KMS_KEY_ID=change-kms-key-id
|
||||
# 可选:自有 KMS Key ID。留空时 Bucket 必须开启“OSS 完全托管”服务器端加密。
|
||||
BACKUP_KMS_KEY_ID=
|
||||
# XtraBackup 专用 MySQL 账号,部署脚本会幂等创建并授予最小备份权限。
|
||||
BACKUP_MYSQL_USER=hfb_backup
|
||||
# 生成方式:openssl rand -hex 24。不要和 MySQL 应用账号或 root 密码复用。
|
||||
|
||||
+2
-3
@@ -40,7 +40,6 @@ BACKUP_DIR
|
||||
BACKUP_RESTORE_DIR
|
||||
BACKUP_OSS_URI
|
||||
BACKUP_PASSPHRASE
|
||||
BACKUP_KMS_KEY_ID
|
||||
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。
|
||||
|
||||
备份 Bucket 必须独立于业务 Bucket,备份 RAM 身份仅授予该 Bucket 的列举、读写对象及指定 KMS Key 的加解密权限。推荐 Bucket 开启版本控制和不可变保留策略。
|
||||
备份 Bucket 必须独立于业务 Bucket,开启“OSS 完全托管”服务器端加密和版本控制。备份 RAM 身份仅授予该 Bucket 的列举、读写对象权限;若填写 `BACKUP_KMS_KEY_ID`,再授予该 Key 的加解密权限。推荐配置不可变保留策略。
|
||||
|
||||
部署机需安装 `ossutil`、`openssl` 和 `flock`,并使用与 cron 相同的业务用户完成 `ossutil` 凭证配置;部署脚本会在启动服务前检查这些依赖。
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ require_archive_config() {
|
||||
backup_require_env BACKUP_DIR >/dev/null
|
||||
backup_require_env BACKUP_OSS_URI >/dev/null
|
||||
backup_require_env BACKUP_PASSPHRASE >/dev/null
|
||||
backup_require_env BACKUP_KMS_KEY_ID >/dev/null
|
||||
}
|
||||
|
||||
closed_binlogs() {
|
||||
@@ -91,10 +90,10 @@ archive_one() {
|
||||
printf 'created_at=%s\n' "$(date -Iseconds)"
|
||||
} > "${work_dir}/${object_id}.complete.env"
|
||||
|
||||
backup_oss_upload_kms "${cipher_file}" "${remote_dir}/binlog.enc"
|
||||
backup_oss_upload_kms "${work_dir}/${object_id}.enc.sha256" "${remote_dir}/binlog.enc.sha256"
|
||||
backup_oss_upload "${cipher_file}" "${remote_dir}/binlog.enc"
|
||||
backup_oss_upload "${work_dir}/${object_id}.enc.sha256" "${remote_dir}/binlog.enc.sha256"
|
||||
# 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}"
|
||||
rm -f -- "${raw_file}" "${cipher_file}" "${work_dir}/${object_id}.enc.sha256" "${work_dir}/${object_id}.complete.env"
|
||||
}
|
||||
|
||||
@@ -153,13 +153,18 @@ backup_decrypt_file() {
|
||||
unset passphrase
|
||||
}
|
||||
|
||||
backup_oss_upload_kms() {
|
||||
backup_oss_upload() {
|
||||
local source="$1"
|
||||
local destination="$2"
|
||||
local kms_key_id
|
||||
kms_key_id="$(backup_require_env BACKUP_KMS_KEY_ID)"
|
||||
kms_key_id="$(backup_env_value BACKUP_KMS_KEY_ID)"
|
||||
if [[ -n "${kms_key_id}" ]]; then
|
||||
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() {
|
||||
|
||||
@@ -22,7 +22,6 @@ require_backup_config() {
|
||||
backup_require_env BACKUP_DIR >/dev/null
|
||||
backup_require_env BACKUP_OSS_URI >/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_PASSWORD >/dev/null
|
||||
}
|
||||
@@ -36,11 +35,11 @@ upload_backup_set() {
|
||||
local remote_dir="${oss_uri}/mysql/full/${level}/${server_uuid}/${ts}"
|
||||
|
||||
backup_log "上传 ${level} 全量备份到 ${remote_dir}"
|
||||
backup_oss_upload_kms "${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_kms "${local_dir}/mysql-full.tgz.enc.sha256" "${remote_dir}/mysql-full.tgz.enc.sha256"
|
||||
backup_oss_upload "${local_dir}/mysql-full.tgz.enc" "${remote_dir}/mysql-full.tgz.enc"
|
||||
backup_oss_upload "${local_dir}/manifest.env" "${remote_dir}/manifest.env"
|
||||
backup_oss_upload "${local_dir}/mysql-full.tgz.enc.sha256" "${remote_dir}/mysql-full.tgz.enc.sha256"
|
||||
# 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() {
|
||||
|
||||
@@ -165,7 +165,6 @@ validate_env() {
|
||||
backup_restore_dir="$(require_env BACKUP_RESTORE_DIR)"
|
||||
backup_oss_uri="$(require_env BACKUP_OSS_URI)"
|
||||
require_env BACKUP_PASSPHRASE >/dev/null
|
||||
require_env BACKUP_KMS_KEY_ID >/dev/null
|
||||
backup_user="$(require_env BACKUP_MYSQL_USER)"
|
||||
require_env BACKUP_MYSQL_PASSWORD >/dev/null
|
||||
backend_uid="$(require_env BACKEND_UID)"
|
||||
|
||||
Reference in New Issue
Block a user