

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 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*

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

備份 PostgreSQL 資料庫是一項重要的任務，通常可以使用 [pg\$1dump 公用程式](https://www.postgresql.org/docs/current/app-pgdump.html)完成，該公用程式預設使用 COPY 命令來建立 PostgreSQL 資料庫的結構描述和資料傾印。不過，如果您需要定期備份多個 PostgreSQL 資料庫，此程序可能會變得重複。如果您的 PostgreSQL 資料庫託管在雲端，您也可以利用 Amazon Relational Database Service (Amazon RDS) for 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 函數必須能夠存取您的資料庫。

以時間為基礎的 Amazon CloudWatch Events 事件會啟動 Lambda 函數，以搜尋[套用至 Amazon RDS 上 PostgreSQL 資料庫執行個體中繼資料的特定備份標籤](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Tagging.html)。 PostgreSQL 如果 PostgreSQL 資料庫執行個體具有 **bkp：AutomatedDBDump = Active** 標籤和其他必要的備份標籤，Lambda 函數會將每個資料庫備份的個別任務提交至 AWS Batch。 

AWS Batch 會處理這些任務，並將備份資料上傳至 Amazon Simple Storage Service (Amazon S3) 儲存貯體。此模式使用 Dockerfile 和 entrypoint.sh 檔案來建置 Docker 容器映像，用於在 AWS Batch 任務中進行備份。備份程序完成後，AWS Batch 會將備份詳細資訊記錄到 Amazon DynamoDB 上的清查資料表。此外，CloudWatch Events 事件會在 AWS Batch 中的任務失敗時啟動 Amazon Simple Notification Service (Amazon SNS) 通知。 

## 先決條件和限制
<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 Command Line Interface (CLI) 第 2 版 Docker 映像](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-docker.html)。
+ 現有的 Amazon RDS for PostgreSQL 資料庫執行個體。 
+ 現有的 S3 儲存貯體。 
+ 在 Linux、macOS 或 Windows 上安裝和設定 [Docker](https://www.docker.com/)。
+ 熟悉 Lambda 中的編碼。 

## Architecture
<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_tw/prescriptive-guidance/latest/patterns/images/pattern-img/3283f739-980b-43d4-aca0-9d77a2ce3b85/images/352e2eab-1b7d-44ec-840a-a772a175e873.png)


 

**技術堆疊**
+ Amazon CloudWatch Events
+ 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 Events](https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/WhatIsCloudWatchEvents.html) – CloudWatch 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 服務，可讓您更輕鬆地在 AWS 雲端中設定、操作和擴展關聯式資料庫。
+ [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 雲端上執行批次運算工作負載。
+ [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) – Lambda 是一種運算服務，可協助您執行程式碼，而無需佈建或管理伺服器。
+ [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/index.html) – Secrets Manager 可協助您以 API 呼叫 Secrets Manager，以程式設計方式擷取秘密，取代程式碼中的硬式編碼登入資料，包括密碼。
+ [Docker](https://www.docker.com/) – Docker 可協助開發人員輕鬆封裝、運送和執行任何應用程式，做為輕量、可攜式且自給自足的容器。

Amazon RDS 上的 PostgreSQL 資料庫執行個體必須將[標籤套用至其中繼資料](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Tagging.html)。Lambda 函數會搜尋標籤以識別應備份的資料庫執行個體，並通常會使用下列標籤。


| 
| 
| Tag | Description | 
| --- |--- |
| bkp：AutomatedDBDump = 作用中 | 將 Amazon RDS 資料庫執行個體識別為備份的候選項目。 | 
| bkp：AutomatedBackupSecret = <secret\$1name > | 識別包含 Amazon RDS 登入憑證的 Secrets Manager 秘密。 | 
| bkp：AutomatedDBDumpS3Bucket = <s3\$1bucket\$1name> | 識別要傳送備份的 S3 儲存貯體。 | 
| bkp：AutomatedDBDumpFrequencybkp：AutomatedDBDumpTime | 識別應備份資料庫的頻率和時間。  | 
| 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>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 在 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>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 SNS 主題。 | 開啟 Amazon SNS 主控台，選擇**主題**，然後使用名稱 建立 SNS 主題`JobFailedAlert`。訂閱作用中的電子郵件地址至主題，並檢查您的電子郵件收件匣，以確認來自 AWS Notifications 的 SNS 訂閱電子郵件。 | 雲端管理員 | 
| 為 AWS Batch 建立失敗的任務事件規則。 | 開啟 Amazon CloudWatch 主控台，選擇**事件**，然後選擇**建立規則**。選擇**顯示進階選項**，然後選擇**編輯**。對於**建立模式以選取事件供目標處理**，請將現有文字取代為*其他資訊*區段中的「任務事件失敗」程式碼。此程式碼定義了 CloudWatch Events 規則，會在 AWS Batch 有`Failed`事件時啟動。 | 雲端管理員 | 
| 新增事件規則目標。 | 在**目標**中，選擇**新增目標**，然後選擇 `JobFailedAlert` SNS 主題。設定其餘詳細資訊並建立 Cloudwatch Events 規則。 | 雲端管理員 | 

### 建置 Docker 映像並將其推送至 Amazon ECR 儲存庫
<a name="build-a-docker-image-and-push-it-to-an-amazon-ecr-repository"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 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>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 AWS Batch 任務定義。 | 開啟 AWS Batch 主控台，並建立任務定義，其中包含 Amazon ECR 儲存庫的統一資源識別符 (URI) 做為 屬性 `Image`。 | 雲端管理員 | 
| 設定 AWS Batch 任務佇列。 | 在 AWS Batch 主控台上，選擇**任務佇列**，然後選擇**建立佇列**。建立任務佇列來存放任務，直到 AWS Batch 在運算環境中的資源上執行任務為止。重要：請務必為 AWS Batch 編寫邏輯，將備份詳細資訊記錄到 DynamoDB 清查資料表。 | 雲端管理員 | 

### 建立和排程 Lambda 函數
<a name="create-and-schedule-a-lambda-function"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 Lambda 函數以搜尋標籤。 | 建立 Lambda 函數，在 PostgreSQL 資料庫執行個體上搜尋標籤並識別備份候選項目。確保您的 Lambda 函數可以識別`bkp:AutomatedDBDump = Active`標籤和所有其他必要的標籤。重要：Lambda 函數也必須能夠將任務新增至 AWS Batch 任務佇列。 | DevOps 工程師 | 
| 建立以時間為基礎的 CloudWatch Events 事件。 | 開啟 Amazon CloudWatch 主控台並建立 CloudWatch Events 事件，該事件使用 Cron 表達式定期執行 Lambda 函數。重要：所有排程事件都使用 UTC 時區。 | 雲端管理員 | 

### 測試備份自動化
<a name="test-the-backup-automation"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 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)
+ [搭配 DynamoDB 使用 Lambda](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html)

 

**建立 CloudWatch Events 事件**
+ [建立以時間為基礎的 CloudWatch Events 事件](https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/Create-CloudWatch-Events-Scheduled-Rule.html)   
+ [在 Cloudwatch Events 中使用 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 "$@"
```