本文详细介绍了如何在AWS上实现跨区域的冷备方案,可以在不增加额外闲置成本的情况下恢复因区域故障导致的生产宕机。在此套环境下,除了网络基础架构预配置外,只做数据定期快照向灾备环境拷贝,其余所有的组件都是灾难发生后通过脚本动态创建,一旦某个生产区域出现故障,用户通过预先定义好的灾备脚本做灾备切换,在灾备区域快速构建 AWS 资源恢复生产环境。
该方案是模拟一个 WordPress cluster 部署在 AWS 上进行 multi-region pilot light 灾备的方案。生产区域组件选择如下。本文也提供了一键部署的模板可以用来进行方案验证。
为了实现冷备环境的搭建以及自动化启动,我们将分别从数据库,应用层,文件服务,自动化脚本这几个方面做展开。
Amazon RDS 在数据库实例的备份窗口中创建数据库自动备份的事件, 可以发送到CloudWatch Event。自动化解决方案可以通过CloudWatch Rule定时触发Lambda, 调用AWS API定时进行数据库快照拍摄并将新创建的 Snapshot 自动拷贝到灾备区域。
Amazon RDS 创建数据库实例的存储卷快照,并备份整个数据库实例而不仅仅是单个数据库。可通过从该数据库快照还原来创建数据库实例。还原数据库实例时,需要提供用于还原的数据库快照的名称,然后提供还原后所新建的数据库实例的名称。无法从数据库快照还原到现有数据库实例;在还原时,将创建一个新的数据库实例。 
当北京区域新建AMI后,可以按时对实例进行快照拍摄,并将新建的AMI复制到宁夏区域。有两种方式可以实现AMI的复制。

在EC2的启动配置中设置 user-data,使 EC2 内应用程序在启动后能够获取所需的配置,例如 RDS Mysql 和 Redis 的endpoint 等等。启动配置已经包含在灾难恢复的脚本中。
静态文件及其它需要同步到灾备region的文件存放在S3上。开启S3 Cross Region Replication,实现S3文件的跨Region自动复制。S3 通过S3FS挂载到 EC2, 作为 WorkPress 媒体文件库。
按照上述方案,在GitHub aws-dr-samples repo上提供了基于Terraform的可执行脚本,该套脚本可以帮助用户快速构建灾备环境。用户根据所需创建的资源写成脚本文件。执行脚本时,Terraform 通过调用 AWS API 来快速构建 AWS 资源。下文有如何使用的详细步骤描述。 在本方案中,设定Redis不包含持久化数据。因此无需实现复制,只需在灾难恢复时通过脚本创建新实例即可。 当灾难发生后,按照以下顺序进行灾难恢复:
接下来,我们会详细描述该方案的实施步骤和脚本运行执行过程。
以宁夏区为例,按照上述灾备方案,假定需要的灾备资源及产生的费用为:
服务 |
类型 |
单价 |
1 年价格 |
|---|---|---|---|
| AMI 20G | 0.277/GB/月 | 66.48 | |
| S3 不频繁访问 1T | 0.1030029/GB/月 | 1265.7 | |
| 跨区域流量 200 G | 0.6003/GB | 120.06 | |
| Total | 1452.24 | ||
| Total with tax | 1539.3744 |
以上仅做参考,实际配置情况,应该根据工作负载合理配置。
terraform脚本请点击此处获取。 项目内有三个文件夹,basic, database, app 。以下为此repo的目录说明。
LockID,类型为 string。在本环境中,该 DynamoDB Table名称 为tf-state。请勿在生产环境部署灾备切换需要的 S3 bucket和DynamoDB指定的Table,防止 Region Down 之后,无法使用 Terraform。由于 WordPress 会记录域名,请勿使用ELB的域名直接访问, 为 WordPress 配置自定义域名。
<project>/index.tf 和 <project>/variables.tf. <project>代表basic, database, app三个相应folder的泛指,请分别进行修改。
aws provider 会比较慢,可提前手动下载, 并解压到<project>/.terraform/plugins/<arch>/ 目录下。<arch> 为本机的系统和CPU架构, 如 darwin_amd64, linux_amd64。 >>>点击此处手动下载 Terraform AWS Provider<<<Note: 如果对现有生产环境进行操作,直接跳过此步骤。
该步骤创建模拟的生产环境,用于演示。可以选择手动创建,或者利用脚本快速创建。使用脚本的好处是, 在演示结束后,我们可以快速销毁演示环境。 创建基础环境
basic/variables.tf 和 basic/index.tfterraform initterraform workspace new prod 创建 模拟生产环境的 workspace. 我们使用 workspace 来区分是模拟生产环境或者灾备环境terraform apply 创建基础网络环境创建数据库
database/variables.tf 和 database/index.tfterraform initterraform workspace new prod 创建 模拟生产环境的 workspace.terraform apply 创建数据库相关资源创建应用层
app/variables.tf 和 app/index.tfterraform initterraform workspace new prod 创建模拟生产环境的 workspaceterraform apply 创建APP相关资源我们需要提前在灾备环境创建基础网络架构,来使得灾难发生时可以快速切换。推荐使用脚本创建,这样可以提高自动化的水平。在使用以下脚本的时候注意参数的配置。 如果已经在第一步 创建模拟生产环境 中修改了 index.tf 文件,无需修改该文件。 拷贝镜像

import json
import boto3
import time
def lambda_handler(event, context):
# TODO implement
clientEC2 = boto3.client('ec2')
name='testami'+time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
instanceId = "i-07a15e9a0d139ee5f"
response = clientEC2.create_image(
InstanceId=instanceId,
Name = name
)
ImageId=response['ImageId']
time.sleep(60)
clientbej = boto3.client('ec2','cn-north-1')
newname='bejtestami'+time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
response = clientbej.copy_image(
Name=newname,
SourceImageId=ImageId,
SourceRegion='cn-northwest-1'
)
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}



创建基础环境
basic/dr.tfvars 和 basic/index.tfterraform initterraform workspace new dr 创建灾备环境的 workspace. 我们使用 workspace 来区分是模拟生产环境或者灾备环境terraform apply --var-file=dr.tfvars 创建基础网络环境开启 S3 Cross Region Replication 进行数据同步
aws s3 sync s3://SOURCE_BUCKET_NAME s3://TARGET_BUCKET_NAME
开启 S3 Cross Region Replication 的更多资料,请参考这里。
RDS 数据备份 RDS默认每24h在备份时段打一次快照,本章节介绍如何自定义备份时间间距(如每2h)并通过serverless的方式自动化打快照。

MAX_SNAPSHOTS : 您想保存最大的副本数量(最大100)DB_INSTANCE_NAME :您想应用该脚本的RDS实例名称, 或者一组名称然后选择右上角 保存。
import boto3
import time
def lambda_handler(event, context):
MAX_SNAPSHOTS = 5
DB_INSTANCE_NAMES = ['your_db_name']
clientRDS = boto3.client('rds')
for DB_INSTANCE_NAME in DB_INSTANCE_NAMES:
db_snapshots = clientRDS.describe_db_snapshots(
SnapshotType='manual',
DBInstanceIdentifier= DB_INSTANCE_NAME
)['DBSnapshots']
for i in range(0, len(db_snapshots) - MAX_SNAPSHOTS + 1):
oldest_snapshot = db_snapshots[0]
for db_snapshot in db_snapshots:
if oldest_snapshot['SnapshotCreateTime'] > db_snapshot['SnapshotCreateTime']:
oldest_snapshot = db_snapshot
clientRDS.delete_db_snapshot(DBSnapshotIdentifier=oldest_snapshot['DBSnapshotIdentifier'])
db_snapshots.remove(oldest_snapshot)
DBSnapshot=clientRDS.create_db_snapshot(
DBSnapshotIdentifier=DB_INSTANCE_NAME + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()),
DBInstanceIdentifier=DB_INSTANCE_NAME
)
newarn=DBSnapshot['DBSnapshot']['DBSnapshotArn']
bejclientRDS = boto3.client('rds','cn-north-1')
time.sleep(180)
response = bejclientRDS.copy_db_snapshot(
SourceDBSnapshotIdentifier=newarn,
TargetDBSnapshotIdentifier="rds_snapshot_bej"+ time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()),
SourceRegion='cn-northwest-1'
)
直接使用可能会有缩进问题,建议在编译器当中先确保没有缩进问题之后再copy到lambda当中



修改灾备应用脚本启动参数
app/dr.tfvarsapp/dr.tfvars, app/index.tf(如之前未修改)terraform initterraform workspace new dr 创建灾备环境的 workspace.修改灾备脚本参数时,要谨慎核对参数。
强烈建议在完成数据同步之后,进行一次故障转移的演练。
basic/variables.tf 和 basic/index.tf


app 目录下的 terraform workspace 是 dr。terraform workspace list 来确认当前 workspace, 或者通过 terraform workspcae select dr来切换到 dr workspace。terraform apply --var-file=dr.tfvars 来启动资源灾后恢复请务必咨询架构师!!! 灾后的恢复工作非常重要,当灾难过后,需要制定好恢复的计划,执行脚本等等。灾后恢复的大致过程和 灾备切换 的过程相同。
可以通过以下步骤快速销毁演示环境。 销毁灾备环境 以下都是 dr terraform workspace
terraform destroy --var-file=dr.tfvarsterraform destroy --var-file=dr.tfvars, 请在数据库实例删除后执行销毁演示生产环境 以下都是 prod terraform workspace, 可以通过 terraform workspace select prod 切换。
terraform destoryterraform destroyterraform destory如需要,可手动删除 WordPress Media 文件 S3 Bucket, 以及 Terraform backend.
Terraform 故障排查 可以通过在 Terraform 命令之前添加环境变量,来使 Terraform 输出更多的日志信息来帮助故障排查,如:
TF_LOG=DEBUG terraform init
本文详细介绍了如何在AWS上实现跨区域的cold backup的灾备方案,并提供了terraform模板进行可行性验证。利用本文所述方法,在主区域发生故障后,自动化脚本会自动执行,完成新区域整套环境的启动,以最大程度的节省成本。