亚马逊AWS官方博客

建立 VPC 并基于参数动态创建子网的 CloudFormation 模板

 

创建 Subnet

在大型企业云迁移项目组,经常会遇到企业将线下数据中心的子网迁移到 AWS 云上。线下的子网划分一般会根据子网的使用功能不同进行划分,例如防火墙子网、负载均衡器子网、配合部署高可用架构的心跳线子网、应用系统子网等。不同企业的子网划分规则、子网的掩码大小和路由规则均不相同,并且在迁移后的系统上线后,企业还会经常划分新的网段以部署新的应用系统,这就需要有一个通用的模板来协助网络管理人员简化工作流程,提高工作效率。在我所经历过的一个项目中,生产 VPC 的子网划分有47个之多,且子网掩码有/24, /25, /26. 27/, /28等不同,在添加新的子网时,需要仔细计算新的子网 CIDR 以及为新建子网配置路由表。

动态创建子网的方案概述

因为 CloudFormation 不支持程序逻辑,只支持静态资源的创建,所以在本方案中采用 AWS Lambda 来基于输入参数动态创建不同类型的子网。我们定义了3种不同类型的子网:公共子网 (Public Subnet), 外部子网 (External Subnet),内部子网 (Internal Subnet) Subnet。
公共子网的路由表有如下路由信息:

Destination Target
0.0.0.0/0 igw-xxxxx (Internet Gateway)

部署在公共子网中的服务器可以直接与 Internet 进行通信(缺省分配 Internet IP 地址,并且有指向 Internet Gateway 的缺省路由)。
外部子网的路由表有如下路由信息:

Destination Target
0.0.0.0/0 nat-xxxxx (NAT gateway)
pl-xxxxxx (com.amazonaws.cn-north-1.s3) vpce-xxxxxxx
pl-xxxx (com.amazonaws.cn-north-1.dynamodb) vpce-xxxx

部署在外部子网的服务器可以通过 NAT Gateway 与 Internet 进行通信,并且可以不通过互联网访问 S3 和 dynamodb。
内部子网的路由表有如下路由信息:

Destination Target
pl-xxxxxx (com.amazonaws.cn-north-1.s3) vpce-xxxxxxx
pl-xxxx (com.amazonaws.cn-north-1.dynamodb) vpce-xxxx

部署在内部子网的服务器不能访问 Internet,但是能直接访问 S3 和 dynamodb。
本方案使用2个 CloudFomation 模板, 第一个模板(CreateBaseVpc.json)创建共享资源,例如 VPC、Internet Gateway、公共子网 (Public Subnet) 路由表、在各个可用区内创建公共子网、NAT Gateway、 VPC Endpoint (S3 endpoint和DynamoDB endpoint)和创建外部子网路由表。在这个模板中还创建了3个 Lambda 功能函数:

    • SharedInfra – 对应 python 程序 create_shared_infra.zip

功能:根据输入的参数,在程序运行的AWS Region的每个AZ内创建公共子网,将在 CreateBaseVpc.json 模板中建立的公共子网路由表关联到每个公共子网。 在每个公共子网内创建 NAT Gateway 和VPC endpoint,创建内部子网路由表,创建外部子网路由表。删除已经创建完成的资源,包括:子网、路由表、vpc endpoint、NAT Gateway、Elastic IP。

    • CreateExternalRoute – 对应 python 程序 create_external_route.zip

功能:创建外部子网路由表中的路由。因为 NAT Gateway 的创建速度比较慢,创建路由时一定要等待 NAT Gateway 的状态变成 available 后才可以成功。如果将此功能与 SharedInfra 放在一起,在执行的时候容易发生 Lambda 运行超时错误。删除已经创建的路由信息。

    • SubnetAutomation – 对应 python 程序 subnet_creation.zip

功能:根据输入的参数,计算网路的子网掩码,创建公共子网、外部子网和内部子网,并将在公共子网路由表、内部子网路由表和外部子网路由表关联到相应的子网上。删除已经创建完成子网。在 CreateBaseVpc.json 模板运行时,通过创建用户定义资源 ExternalRouteCreation和SharedInfraCreation 分别触发 Lambda 功能 CreateExternalRoute 和 SharedInfra,从而完成共享资源的创建。并提供了 SubnetAutomation 的功能函数 ARN,供运行第二个模板时调用。

第二个模板 (SubnetAuto.json) 创建动态资源,例如根据输入参数的不同计算子网掩码、创建子网并分配路由表。

本方案中创建子网时的输入参数并不需要 CIDR,只需要指定子网要提供的可用 IP 地址的个数即可,程序在计算可用 IP 地址时已经排除了 AWS 子网子网中保留的5个 IP 地址。例如:如果要创建有50个 IP 的子网,则子网掩码是/26,共计有64-5=59个可用IP地址;如果要创建有16个 IP 的子网,则子网掩码是/27,共计有32-5=27个可用 IP 地址。

创建子网的参数输入规则如下:

  1. 每个子网包含4个部分,之间使用“:”分隔 – 功能: IP 地址数量:可用区:子网类型
  2. 可用区根据Region的不同可选项为:1a,1b,1c,1d,1e等
  3. 子网类型的可选项为:p(公共子网),e(外部子网)或者 i(内部子网)
  4. 不同子网之间使用“,”分隔。

安装和运行

    1. 在浏览器中输入:https://github.com/shaneliuyx/autosubnet_creation, 下载2个 json 文件和3个 zip 文件。将3个 zip 文件上传到一个 S3 存储桶中。
    2. 打开 AWS 控制台,并选择 CloudFormation,选择存储在本地的 json 文件 json,运行 CloudFormation 模板。
    3. 假设输入缺省的 PublicSubnetCapacity 和 VpcCidr 如下:

    1. 选择 Next,直至 AWS 资源开始创建
    2. 最终运行结果如下:

创建的 Subnet 如下:

公共子网路由表:

    1. 打开 AWS 控制台,并选择 CloudFormation,选择存储在本地的 json 文件 json,运行 CloudFormation 模板。
    2. 输入 SubnetParameters:web1:50:1a:p,web1:50:1b:p,app1:50:1a:e,app1:50:1b:e,db1:50:1a:i,db1:50:1b:i

这将创建6个子网,其中 Web、APP 和 DB 各2个子网,分布在2个 AZ 中:

    1. 运行结果如下:

创建的子网:



内部子网路由表:

外部子网路由表:

假设现在还要创建一个包含16个有效 IP 的公共子网用于部署网络设备,可以再运行一次SubnetAuto.json,输出参数:net1:16:1a:p,net1:16:1b:p
则可以创建出如下子网:

与其他 CloudFormation 模板配合使用,进行 Landing Zone 部署

Landing Zone 中文名称翻译成着陆区,是指 AWS 的基本环境,用户在其上部署安全和运维流程。Landing Zone 的内容包含:账户结构、账户安全基线、网络结构和AWS用户访问管理。下面简单的介绍一下 AWS Landing Zone 的最佳实践。

    • 账户结构

AWS 建议账户的划分与企业的组织架构和运维部门的组织架构一致。例如按照如下结构划分账户:

    • 账户安全基线

AWS 建议在所有账户内打开 CloudTrail 和 AWS Config 功能。所有日志信息要复制到安全账户内的 S3 存储桶中。建立跨账户访问的 Auditor 角色。

    • 网络结构

AWS 建议删除缺省 VPC,建立客户自己定义的 VPC。建立共享 VPC(包含目录服务、邮件服务器等),应用 VPC 与共享 VP C建立 Peer 关系。通过 VPN 或者 Direct Connect 与线下的数据中心建立网络连接,或者采用 Transit VPC(参考 https://thinkwithwp.com/answers/networking/aws-global-transit-network/https://thinkwithwp.com/blogs/aws/aws-solution-transit-vpc/ )建立集中的网络控制机制。网络输入输出的安全控制(建立堡垒机,建立 Security Group、网络 ACL 或者第三方的防火墙工具)

    • AWS 用户访问管理

包括建议基于 SAML 的单点登录,建立跨账户角色访问机制等。

上述介绍的建立 VPC 和子网的方法可以看成建立 Landing Zone 的基础,在此之上,我们还可以使用 CloudFormation 建立堡垒机,打开 CloudTrail 和 AWS config,建立不同账户间的日志(log)复制机制,建立 Config Rule 进行合规性检查等等。 AWS 已经开发出多个 QuickStart CloudFormation 脚本协助用户完成上述工作,但是这些脚本在中国区(BJS)运行时需要做一些修改。下表列出了一些可用的资源,其中中国区部署模板是我针对中国区的特点修改过的,可以在BJS正常运行。

原始代码 参考 AWS 中国区部署模板
账户安全基线 配置 AWS config 和 CloudTrail https://github.com/aws-quickstart/quickstart-compliance-pci https://s3.cn-north-1.amazonaws.com.cn/shane/quickstart-security/logging.template
配置 IAM 角色 https://s3.cn-north-1.amazonaws.com.cn/shane/quickstart-security/iam.template
配置 Config rules https://s3.cn-north-1.amazonaws.com.cn/shane/quickstart-security/config-rules.template
将 CloudWatch Log 转储到S3存储桶 https://github.com/alertlogic/cloudwatch-logs-s3-export#setup

https://s3.cn-north-1.amazonaws.com.cn/shane/cwl-s3-export-new.template

使用说明:https://s3.cn-north-1.amazonaws.com.cn/shane/User+Guide+-+Copy+VPC+Flow+Logs+to+S3+CloudFormation+Templates.docx

将一个账户下的 S3 存储桶复制到另一个账户的 S3

https://s3.cn-north-1.amazonaws.com.cn/shane/s3-to-s3/1source.json https://s3.cn-north-1.amazonaws.com.cn/shane/s3-to-s3/2target.json https://s3.cn-north-1.amazonaws.com.cn/shane/s3-to-s3/3source.json

使用说明:https://s3.cn-north-1.amazonaws.com.cn/shane/s3-to-s3/User+Guide+-+S3+to+S3+Replication+CloudFormation+Templates.docx

网络结构 配置 Linux Bastion https://github.com/aws-quickstart/quickstart-linux-bastion https://s3.cn-north-1.amazonaws.com.cn/shane/linux-bastion.template 不支持 CentOS
建立 VPC 和分配 Subnet https://github.com/aws-quickstart/quickstart-aws-vpc https://github.com/shaneliuyx/autosubnet_creation

本篇作者

刘育新

AWS云架构高级咨询顾问,获得AWS解决方案架构师专业级认证和DevOps工程师专业级认证,专注于云迁移解决方案。目前已为多家跨国公司及本土公司、合作伙伴提供上云迁移的咨询设计和实施服务,在加入AWS之前有近20年的IT架构设计和项目管理经验。