亚马逊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 如下:
  4. 选择 Next,直至 AWS 资源开始创建
  5. 最终运行结果如下:
  6. 创建的 Subnet 如下:

    公共子网路由表:

  7. 打开 AWS 控制台,并选择 CloudFormation,选择存储在本地的 json 文件 json,运行 CloudFormation 模板。
  8. 输入 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
  9. 这将创建6个子网,其中 Web、APP 和 DB 各2个子网,分布在2个 AZ 中:

  10. 运行结果如下:
  11. 创建的子网:



    内部子网路由表:

    外部子网路由表:

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

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

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