

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用 AWS Batch 自动备份 Amazon RDS for PostgreSQL 数据库实例
<a name="automate-backups-for-amazon-rds-for-postgresql-db-instances-by-using-aws-batch"></a>

*Kirankumar Chandrashekar，Amazon Web Services*

## Summary
<a name="automate-backups-for-amazon-rds-for-postgresql-db-instances-by-using-aws-batch-summary"></a>

备份 PostgreSQL 数据库是一项重要的任务，通常可以使用 [pg\$1dump utility](https://www.postgresql.org/docs/current/app-pgdump.html) 完成，该实用程序默认使用 COPY 命令创建 PostgreSQL 数据库的架构和数据转储。但是，如果您需要定期备份多个 PostgreSQL 数据库，则此进程可能会变得重复。如果您的 PostgreSQL 数据库托管在云端，您也可以利用Amazon Relational Database Service (Amazon RDS) 为 PostgreSQL 提供的[自动备份](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithAutomatedBackups.html)功能。此示例介绍了如何使用 pg\$1dump 实用程序自动执行适用于 Amazon RDS for PostgreSQL 数据库实例的定期备份。

注意：这些说明假定您使用的是 Amazon RDS。但是，您也可以对托管在 Amazon RDS 外部的 PostgreSQL 数据库采用这种方法。若要进行备份，AWS Lambda 函数必须能访问您的数据库。

基于时间的亚马逊 CloudWatch 事件会启动 Lambda 函数，该函数搜索[应用于 Amazon RDS 上 PostgreSQL 数据库实例元数据的特定备份标签](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Tagging.html)。如果 **DBDump PostgreSQL 数据库实例具有 bkp: Automated =** Active 标签和其他必需的备份标签，则 Lambda 函数将每个数据库备份的单个任务提交到 AWS Batch。 

AWS Batch 会处理这些任务，并将备份数据上至到 Amazon Simple Storage Service（Amazon S3）存储桶。此模式使用 Dockerfile 和 entrypoint.sh 文件构建 Docker 容器映像，该映像用于在 AWS Batch 作业中进行备份。备份过程完成后，AWS Batch 会将备份详细信息记录至 Amazon DynamoDB 的库存表。作为一项额外的保护措施，如果任务在 AWS Batch 中失败， CloudWatch 事件事件会启动亚马逊简单通知服务 (Amazon SNS) Simple Notification Service 通知。 

## 先决条件和限制
<a name="automate-backups-for-amazon-rds-for-postgresql-db-instances-by-using-aws-batch-prereqs"></a>

**先决条件**
+ 一个活跃的 AWS 账户。
+ 现有托管或非托管计算环境。有关更多信息，请参阅 AWS Batch 文档中的[托管和非托管计算环境](https://docs.aws.amazon.com/batch/latest/userguide/compute_environments.html)。 
+ [AWS 命令行界面（CLI）版本 2 Docker 映像](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-docker.html)，已安装并配置。
+ 现有的 Amazon RDS for PostgreSQL 数据库实例。 
+ 现有的 S3 存储桶。 
+ [Docker](https://www.docker.com/)，已在 Linux、macOS 或 Windows 上安装并配置。
+ 熟悉 Lambda 编码。 

## 架构
<a name="automate-backups-for-amazon-rds-for-postgresql-db-instances-by-using-aws-batch-architecture"></a>

![\[使用 pg_dump 实用程序备份 Amazon RDS for PostgreSQL 数据库实例的架构。\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/images/pattern-img/3283f739-980b-43d4-aca0-9d77a2ce3b85/images/352e2eab-1b7d-44ec-840a-a772a175e873.png)


 

**技术堆栈**
+ 亚马逊 CloudWatch 活动
+ Amazon DynamoDB
+ Amazon Elastic Container Registry (Amazon ECR)
+ Amazon RDS
+ Amazon SNS
+ Amazon S3
+ AWS Batch
+ AWS Key Management Service（AWS KMS）
+ AWS Lambda
+ AWS Secrets Manager
+ Docker

## 工具
<a name="automate-backups-for-amazon-rds-for-postgresql-db-instances-by-using-aws-batch-tools"></a>
+ [Amazon CloudWatch ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/WhatIsCloudWatchEvents.html) Ev CloudWatch ents — Events 提供近乎实时的系统事件流，这些事件描述了 AWS 资源的变化。
+ [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html) - DynamoDB 是一种全托管 NoSQL 数据库服务，提供快速而可预测的性能，能够实现无缝扩展。
+ [Amazon ECR](https://docs.aws.amazon.com/ecr/index.html) - Amazon Elastic Container Registry (Amazon ECR) 是一项安全、可靠且可扩展的 AWS 托管容器映像注册表服务。
+ [Amazon RDS](https://docs.aws.amazon.com/rds/index.html) - Amazon Relational Database Service (Amazon RDS) 是一项 Web 服务，让用户能够在 Amazon Web Services Cloud 中轻松设置、操作和扩展关系数据库。
+ [Amazon SNS](https://docs.aws.amazon.com/sns/latest/dg/welcome.html) - Amazon Simple Notification Service（Amazon SNS）是一项托管服务，提供从发布者至订阅用户的消息传输。
+ [Amazon S3](https://docs.aws.amazon.com/s3/index.html) – Amazon Simple Storage Service (Amazon S3) 是一项面向互联网的存储服务。
+ [AWS Batch](https://docs.aws.amazon.com/batch/index.html) – AWS Batch 可帮助您在 AWS Cloud上运行批量计算工作负载。
+ [AWS KMS](https://docs.aws.amazon.com/kms/index.html) - AWS Key Management Service（AWS KMS）是一项托管服务，可让您轻松创建和控制加密您的数据所用的加密密钥。
+ [AWS Lambda](https://docs.aws.amazon.com/lambda/index.html) – AWS Lambda 是一项计算服务，可使您无需预置或管理服务器即可运行代码。
+ [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/index.html) - Secrets Manager 帮助您将代码中的硬编码凭证（包括密码）替换为对 Secrets Manager 的 API 调用，以便以编程方式检索密钥。
+ [Docker](https://www.docker.com/) - Docker 有助于开发人员轻松打包、交付和运行任何应用程序，将其作为轻量级、便携且自给自足的容器。

您在 Amazon RDS 上的 PostgreSQL 数据库实例必须[为其元数据应用标签](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Tagging.html)。Lambda 函数搜索标签以识别应备份的数据库实例，这通常使用以下标签。


| 
| 
| Tag | 说明 | 
| --- |--- |
| BKP: 自动 = 激活 DBDump  | 将 Amazon RDS 数据库实例标识为备份候选实例。 | 
| bkp: = AutomatedBackupSecret <secret\$1name > | 标识 Secrets Manager 密钥，其中包含 Amazon RDS 登录凭证。 | 
| bkp: 自动 S3Bucket = DBDump <s3\$1bucket\$1name> | 标识要向其发送备份的目标 S3 存储桶。 | 
| bkpDBDump: 自动频率bkpDBDump: 自动时间 | 确定数据库备份的频率和时间。  | 
| bkp:pgdumpcommand = <pgdump\$1command> | 标识需要对其执行备份的数据库。 | 

## 操作说明
<a name="automate-backups-for-amazon-rds-for-postgresql-db-instances-by-using-aws-batch-epics"></a>

### 在 DynamoDB 中创建清单表
<a name="create-an-inventory-table-in-dynamodb"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 在 DynamoDB 中创建表。 | 登录 AWS 管理控制台，打开 Amazon DynamoDB 控制台，然后创建表。要获取有关此操作和其他操作的帮助，请参阅*相关资源*部分。 | 云管理员、数据库管理员 | 
| 确认已创建表格。 | 运行 `aws dynamodb describe-table --table-name <table-name> \| grep TableStatus`命令。如果该表存在，则该命令将返回 `"TableStatus": "ACTIVE",` 结果。 | 云管理员、数据库管理员 | 

### 在 AWS Batch 中为失败作业事件创建 SNS 主题
<a name="create-an-sns-topic-for-failed-job-events-in-aws-batch"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 创建一个 SNS 主题。 | 打开 Amazon SNS 控制台，选择**主题**，然后创建名为 `JobFailedAlert` 的 SNS 主题。以有效电子邮箱地址订阅此主题，并查看您的电子邮件收件箱以确认来自 AWS Notifications 的 SNS 订阅电子邮件。 | 云管理员 | 
| 为 AWS Batch 创建失败作业事件规则。 | 打开 Amazon CloudWatch 控制台，选择**事件**，然后选择**创建规则**。选择**显示高级选项**，并选择**编辑**。对于**构建模式，选择按您的目标处理的事件**，将现有文本替换为*其他信息*部分的“失败作业事件”代码。此代码定义了在 A CloudWatch WS Batch 有`Failed`事件时启动的事件规则。 | 云管理员 | 
| 添加事件规则目标。 | 在**目标**中，选择**添加目标**，然后选择 `JobFailedAlert` SNS 主题。配置其余详细信息，并创建 Cloudwatch Events 规则。 | 云管理员 | 

### 推送 Docker 映像到 Amazon ECR 存储库
<a name="build-a-docker-image-and-push-it-to-an-amazon-ecr-repository"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 创建 Amazon ECR 存储库。 | 打开 Amazon ECR 控制台，选择要在其中创建存储库的 AWS 区域。选择**存储库**，然后选择**创建存储库**。根据要求配置存储库。 | 云管理员 | 
| 撰写 Dockerfile。 | 登录 Docker，使用*其他信息*部分中的“示例 Dockerfile”和“示例 entrypoint.sh 文件”构建 Dockerfile。 | DevOps 工程师 | 
| 创建 Docker 映像并将其推送到 Amazon ECR 存储库。 | 将 Dockerfile 构建至 Docker 映像，并将其推送至 Amazon ECR 存储库。有关此步骤的帮助，请参阅*相关资源*部分。 | DevOps 工程师 | 

### 创建 AWS Batch 组件
<a name="create-the-aws-batch-components"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 创建 AWS Batch 作业定义。 | 打开 AWS Batch 控制台，创建作业定义，其将 Amazon ECR 存储库的 Uniform Resource Identifier (URI) 包含为 `Image` 属性。 | 云管理员 | 
| 配置 AWS Batch 作业队列。 | 在 AWS Batch 控制台，选择**作业队列**，然后选择**创建队列**。创建作业存储队列，直至 AWS Batch 在您的计算环境资源中运行这些任务。重要提示：请务必为 AWS Batch 编写逻辑，以将备份详细信息记录至 DynamoDB 清单表。 | 云管理员 | 

### 创建并计划 Lambda 函数
<a name="create-and-schedule-a-lambda-function"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 创建 Lambda 函数以搜索标签。 | 创建 Lambda 函数，用于在您的 PostgreSQL 数据库实例上搜索标签并识别备用备份。确保您的 Lambda 函数可以识别 `bkp:AutomatedDBDump = Active` 标签和所有其他必需的标签。重要提示：Lambda 函数还必须能够将任务添加至 AWS Batch 作业队列中。 | DevOps 工程师 | 
| 创建基于时间 CloudWatch 的事件事件。 | 打开 Amazon CloudWatch 控制台并创建一个 CloudWatch 事件事件，该事件使用 cron 表达式定期运行您的 Lambda 函数。重要提示：所有计划的事件都使用 UTC 时区。 | 云管理员 | 

### 测试备份自动化
<a name="test-the-backup-automation"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 创建 Amazon KMS 密钥。 | 打开 Amazon KMS 控制台并创建 KMS 密钥，该密钥可用于加密存储在 AWS Secrets Manager 中的 Amazon RDS 证书。 | 云管理员 | 
| 创建 AWS Secrets Manager 密钥。 | 打开 AWS Secrets Manager 控制台，将您的 Amazon RDS for PostgreSQL 数据库证书存储为机密。 | 云管理员 | 
| 向 PostgreSQL 数据库实例添加所需标签。 | 打开 Amazon RDS 控制台，为要自动备份的 PostgreSQL 数据库实例添加标签。您可以使用*工具*部分表格中的标签。如果您需要从同一 Amazon RDS 实例中的多个 PostgreSQL 数据库进行备份，请使用 `-d test:-d test1` 作为 `bkp:pgdumpcommand` 标签值。`test` 和 `test1` 是数据库名称。确保冒号 (:) 后没有空格。 | 云管理员 | 
| 验证备份自动化。 | 若要验证备份自动化，您可以调用 Lambda 函数或等待备份计划开始。备份过程完成后，请检查 DynamoDB 清单表中是否包含适用于 PostgreSQL 数据库实例的有效备份条目。如果其匹配，则表示备份自动化过程成功。 | 云管理员 | 

## 相关资源
<a name="automate-backups-for-amazon-rds-for-postgresql-db-instances-by-using-aws-batch-resources"></a>

**在 DynamoDB 中创建清单表**
+ [创建 Amazon DynamoDB 表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/getting-started-step-1.html)

 

**在 AWS Batch 中为失败作业事件创建 SNS 主题**
+ [创建 Amazon SNS 主题](https://docs.aws.amazon.com/sns/latest/dg/sns-tutorial-create-topic.html)
+ [在 AWS Batch 中针对失败作业事件发送 SNS 提醒](https://docs.aws.amazon.com/batch/latest/userguide/batch_sns_tutorial.html)

 

**推送 Docker 映像到 Amazon ECR 存储库**
+ [创建 Amazon ECR 存储库](https://docs.aws.amazon.com/AmazonECR/latest/userguide/repository-create.html)    
+ [编写 Dockerfile，创建 Docker 映像，然后将其推送至 Amazon ECR](https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html)

 

**创建 AWS Batch 组件**
+ [创建 AWS Batch 作业定义](https://docs.aws.amazon.com/batch/latest/userguide/Batch_GetStarted.html#first-run-step-1)    
+ [配置您的计算环境和 AWS Batch 作业队列](https://docs.aws.amazon.com/batch/latest/userguide/Batch_GetStarted.html#first-run-step-2)   
+ [在 AWS Batch 中创建作业队列](https://docs.aws.amazon.com/batch/latest/userguide/create-job-queue.html)

 

**创建 Lambda 函数**
+ [创建 Lambda 函数和编写代码](https://docs.aws.amazon.com/lambda/latest/dg/getting-started-create-function.html)
+ [将 Lambda 与 DynamoDB 共同使用](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html)

 

**创建 CloudWatch 活动事件**
+ [创建基于时间 CloudWatch 的事件事件](https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/Create-CloudWatch-Events-Scheduled-Rule.html)   
+ [在 Cloudwatch 事件中采用 cron 表达式](https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html)

 

**测试备份自动化**
+ [创建 Amazon KMS 密钥](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html)    
+ [创建 Secrets Manager 密钥](https://docs.aws.amazon.com/secretsmanager/latest/userguide/tutorials_basic.html)
+ [为 Amazon RDS 实例添加标签](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Tagging.html)

## 附加信息
<a name="automate-backups-for-amazon-rds-for-postgresql-db-instances-by-using-aws-batch-additional"></a>

**失败作业事件：**

```
{
  "detail-type": [
    "Batch Job State Change"
  ],
  "source": [
    "aws.batch"
  ],
  "detail": {
    "status": [
      "FAILED"
    ]
  }
}
```

**示例 Dockerfile：**

```
FROM alpine:latest
RUN apk --update add py-pip postgresql-client jq bash && \
pip install awscli && \
rm -rf /var/cache/apk/*
ADD entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
```

**entrypoint.sh 文件示例：**

```
 #!/bin/bash
set -e
DATETIME=`date +"%Y-%m-%d_%H_%M"`
FILENAME=RDS_PostGres_dump_${RDS_INSTANCE_NAME}
FILE=${FILENAME}_${DATETIME}

aws configure --profile new-profile set role_arn arn:aws:iam::${TargetAccountId}:role/${TargetAccountRoleName}
aws configure --profile new-profile set credential_source EcsContainer

echo "Central Account access provider IAM role is: "
aws sts get-caller-identity

echo "Target Customer Account access provider IAM role is: "
aws sts get-caller-identity --profile new-profile

securestring=$(aws secretsmanager get-secret-value --secret-id $SECRETID --output json --query 'SecretString' --region=$REGION --profile new-profile)

if [[ ${securestring} ]]; then
    echo "successfully accessed secrets manager and got the credentials"
    export PGPASSWORD=$(echo $securestring | jq --raw-output | jq -r '.DB_PASSWORD')
    PGSQL_USER=$(echo $securestring | jq --raw-output | jq -r '.DB_USERNAME')
    echo "Executing pg_dump for the PostGres endpoint ${PGSQL_HOST}"
    # pg_dump -h $PGSQL_HOST -U $PGSQL_USER -n dms_sample | gzip -9 -c  | aws s3 cp - --region=$REGION  --profile new-profile s3://$BUCKET/$FILE
    # in="-n public:-n private"
    IFS=':' list=($EXECUTE_COMMAND);
    for command in "${list[@]}";
      do
        echo $command;
        pg_dump -h $PGSQL_HOST -U $PGSQL_USER ${command} | gzip -9 -c  | aws s3 cp - --region=$REGION --profile new-profile s3://${BUCKET}/${FILE}-${command}".sql.gz"
        echo $?;
        if  [[ $? -ne 0 ]]; then
            echo "Error occurred in database backup process. Exiting now....."
            exit 1
        else
            echo "Postgresql dump was successfully taken for the RDS endpoint ${PGSQL_HOST} and is uploaded to the following S3 location s3://${BUCKET}/${FILE}-${command}.sql.gz"
            #write the details into the inventory table in central account
            echo "Writing to DynamoDB inventory table"
            aws dynamodb put-item --table-name ${RDS_POSTGRES_DUMP_INVENTORY_TABLE} --region=$REGION --item '{ "accountId": { "S": "'"${TargetAccountId}"'" }, "dumpFileUrl": {"S": "'"s3://${BUCKET}/${FILE}-${command}.sql.gz"'" }, "DumpAvailableTime": {"S": "'"`date +"%Y-%m-%d::%H::%M::%S"` UTC"'"}}'
            echo $?
            if  [[ $? -ne 0 ]]; then
                echo "Error occurred while putting item to DynamoDb Inventory Table. Exiting now....."
                exit 1
            else
                echo "Successfully written to DynamoDb Inventory Table ${RDS_POSTGRES_DUMP_INVENTORY_TABLE}"
            fi
        fi
      done;
else
    echo "Something went wrong {$?}"
    exit 1
fi

exec "$@"
```