AWS环境下Postgres逻辑数据库pg_dumps自动化的最佳方案
RDS PostgreSQL全库pg_dump自动备份到S3实现方案
以下方案优先规避复杂Lambda逻辑,降低学习成本:
轻量本地调度方案(完全不用Lambda,上手门槛最低)
该方案用EC2定时任务实现,不需要学习任何陌生服务:
- 前置准备
- 启动1台最小配置EC2(如t2.micro,符合免费 tier 要求),放在和RDS相同的VPC下,安全组放行EC2到RDS的5432端口访问权限
- 实例内安装对应RDS大版本的PostgreSQL客户端、awscli、jq工具,以Amazon Linux 2为例:
sudo yum install postgresql15 awscli jq -y - 给EC2实例绑定IAM角色,开放3类最小权限:RDS实例列表只读权限、目标S3备份桶的写入权限、SecretsManager读权限(如果用凭据存储密码)
- 备份脚本核心逻辑
- 拉取当前账号下所有PostgreSQL类型的RDS实例:
aws rds describe-db-instances --query "DBInstances[?Engine=='postgres'].{Endpoint:Endpoint.Address,Id:DBInstanceIdentifier}" --output text - 遍历每个实例,拉取实例下所有非模板逻辑库:
psql -h <RDS实例端点> -U <数据库账号> -d postgres -t -c "SELECT datname FROM pg_database WHERE datistemplate = false;" - 逐库执行备份,压缩后直接上传到S3,无需占用本地存储:
pg_dump -h <RDS实例端点> -U <数据库账号> <数据库名> | gzip | aws s3 cp - s3://<备份桶名称>/rds-backup/<实例ID>/<数据库名>_$(date +%Y%m%d%H%M).sql.gz
- 密码安全优化:数据库密码可以存在AWS Secrets Manager中,脚本内动态拉取,无需明文写在脚本里,拉取命令:
aws secretsmanager get-secret-value --secret-id <密码凭据ID> --query SecretString --output text | jq -r '.password' - 无密码登录优化:如果RDS开启了IAM数据库认证,可以直接生成认证令牌登录,不需要存储任何密码:
pg_dump "host=<RDS实例端点> port=5432 dbname=<数据库名> user=<数据库账号> password=$(aws rds generate-db-auth-token --hostname <RDS实例端点> --port 5432 --username <数据库账号>)" | gzip | aws s3 cp - s3://<备份桶名称>/rds-backup/<实例ID>/<数据库名>_$(date +%Y%m%d%H%M).sql.gz
- 拉取当前账号下所有PostgreSQL类型的RDS实例:
- 定时执行配置
用crontab设置定时规则,比如每天凌晨2点执行备份:0 2 * * * /path/to/backup_script.sh >> /var/log/rds_backup.log 2>&1 - 成本优化
给S3备份桶配置生命周期规则,超过保留周期的备份自动转入低频存储或者直接删除,降低存储成本。
AWS Batch无服务器方案(最低程度使用Lambda,无复杂代码)
如果不想长期持有EC2资源,可以选择该方案,Lambda仅做任务触发,无需处理备份逻辑:
- 前置准备
- 把上面的备份脚本打包进Docker镜像,镜像内预装PostgreSQL客户端、awscli、jq,打包后上传到Amazon ECR
- 创建AWS Batch计算环境、作业队列、作业定义,作业指定使用ECR中的备份镜像,作业执行角色绑定和上述EC2相同的IAM权限
- 触发逻辑配置
Lambda仅需要写3行核心代码,作用是收到定时触发信号后提交AWS Batch作业,无需处理任何备份相关逻辑:
最后用Amazon EventBridge设置定时规则,到点触发Lambda即可,整个流程不需要手动维护服务器,仅备份时产生计算费用。import boto3 batch_client = boto3.client('batch') def lambda_handler(event, context): batch_client.submit_job( jobName='rds-pg-backup-job', jobQueue='<你的作业队列名称>', jobDefinition='<你的作业定义名称>:latest' )
内容的提问来源于stack exchange,提问作者Chase Mitchell
相关产品推荐
相关产品推荐

