亚马逊AWS官方博客
使用相同自定义域名实现内外网访问托管在 API 网关的 Restful API
1. 功能背景
1.1 功能需求
客户当前已经在 AWS 中部署了 Lambda 函数对内外部用户提供服务,其中服务访问接口通过 API GW 中的 Restful API 提供,内部用户通过专线的方式可以连接到 AWS 指定 VPC,通过内网的方式调用 Lambda 函数,外部用户通过 Internet 直接调用相同的 Lambda 函数。客户期望使用相同的企业域名对内外部用户提供托管在 Lambda 上的访问服务。本篇博客主要说明具体的实现方法并提供测试代码。
1.2 场景说明
业务场景分为内外网验证两个部分,内网通过相同 VPC 内创建 EC2,通过内网域名调用到 API GW,其中 EC2 部分模拟客户本地数据中心的 VM,不支持 Internet 访问。通过公网域名调用部分直接使用本机电脑模拟。本次测试涉及到的服务主要包含: VPC(子网、Endpoint 等)、EC2、Lambda、API GW、ALB、Route53 以及 Amazon Certificate Manager 等。API GW 当前不支持在 Private API 上使用自定义域名,需要使用配置较为复杂的手工方案,因此在本次测试中会提供配置脚本用于创建带自定义域名的 Private API。在此基础之上在 API GW 中配置用于公网访问的 Regional API。本次测试中使用的 Lambda 仅为演示使用,不包含集成客户真实的 Lambda 函数。
2. 部署架构
2.1 外部用户通过互联网访问(蓝色路径)
- 用户通过访问 Route53 的 Public Zone 解析公网域名
- 访问的域名对应解析到 API GW 服务的 Custom Domain Names 中的 API Gateway 域名,从而将请求转发到 API GW
- API Gateway 调用 ACM 中保存的证书,验证请求的合法性
- 请求被转发给后端 Lambda 处理
2.2 内部用户通过内网访问(黑色路径)
- 处于相同 VPC 的另外一个私有子网内的 EC2 向 Route 53 的 Private Zone 发送请求解析相同的自定义域名
- Private Zone 将访问的域名解析到 ALB 的默认域名,从而将请求转发到 ALB 处理
- ALB 通过调用 ACM 中的证书验证请求的合法性
- ALB 将请求转发到托管在两个子网内的 ENI 网卡
- 请求被转发给 VPC Endpoint(API GW PrivateLink)
- VPC Endpoint 将请求路由到对应的 Private API
- 请求最终被转发到 Lambda 处理
3. 部署过程
3.1 创建基础环境
3.1.1 申请公网域名以及 Route53 Zone
本次测试使用域名 helloworld. xxx.xxx.xxx.org.cn,通过配置后该域名可同时在内网和公网进行解析
创建 Route53 public zone 用于演示解析公网域名
创建 Route53 private zone 用于演示解析通过内网解析相同的域名,两个 Zone 的域名相同
3.1.2 创建 VPC 和子网
VPC 至少需要包含 2 个私有子网和一个公共子网,公共子网用于部署 EC2 跳板机,通过该跳板机可登录到模拟客户本地内网本地 VM 的 EC2。另外两个私有子网用于部署后续的 VPC Endpoint 以及内网 EC2。
3.1.3 创建 VPC Endpoint
创建 Interface 类型的 Endpoint,创建时选择两个私有子网,同时注意安全组建议选择后续创建 ALB 时相同的安全组,端口需要放开 443。详细步骤可参考: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-apis.html#apigateway-private-api-create-interface-vpc-endpoint。
3.2 创建支持自定义域名的 Private API
通过如下 Github 中托管的 project 进行创建:https://github.com/weinick/apigw-private-custom-domain-name。此 Repo 基于 AWS 官方 Sample 中的内容,针对 AWS 中国区作了必要的修改。原始 Repo 请参考: https://github.com/aws-samples/serverless-samples/tree/main/apigw-private-custom-domain-name。
- 在您的电脑安装 AWS CLI 工具并配置必要的权限,参考:https://docs.amazonaws.cn/cli/latest/userguide/getting-started-install.html
- 在您的电脑安装 SAM 工具,参考:https://docs.amazonaws.cn/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html
- 下载 Repo 中的代码
3.2.1 创建 ACM 证书
参考下载的代码中的 README.md 中说明创建 ACM 证书,注意默认的域名验证方式为 DNS,需要您在 Route53 或者域名服务商侧添加 CNAME。您也可以修改 iac/certificate.yaml 中 ValidationMethod 的值为 email,之后可通过注册邮箱的方式验证。使用 make cert 命令完成自动化部署。
3.2.2 创建 API Gateway Endpoint
参考下载的代码中的 README.md 中说明创建私有的 API 接口,使用 make apigw 命令完成自动化部署。默认的资源策略仅允许当前使用的 VPC 调用 API 的接口。
3.2.3 创建 ALB 负载均衡器
参考下载的代码中的 README.md 中说明创建内网 ALB 负载均衡器,使用 make alb 命令完成自动化部署。此部分也可以选择使用 NLB 类型,对应部署命令为 make nlb。
3.2.4 在 Route53 中创建 CNAME 记录
参考下载的代码中的 README.md 中说明在已有的 private zone 中添加 CNAME 记录,使用 make r53 命令完成自动化部署。CNAME 会将自定义域名解析到负载均衡器的默认域名。
3.3 创建 Region API 接口
创建 Regional Restful API 接口并集成到相同的 lambda,具体创建步骤可参考:https://docs.amazonaws.cn/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html。 创建完成后您会有 2 个 Restful API 接口。
在 3.2 部分中创建的 Custom Domain Names 中添加 API 映射,需要注意区分不同的 Path。例如 Public 可访问的 URL 为 https:// helloworld. abc.xxx.xxx.cn/public,Private 可访问的 URL 为 https:// helloworld. abc.xxx.xxx.cn/private。
3.4 Route53 中创建公网 CNAME
在 Public zone 中创建 CNAME 记录,将自定义域名指向 API GW 服务中的自定义域名对应的 API Gateway 域名,该域名以 execute-api.AWSREGION.amazonaws.com.cn 结尾。自定义域名可参考: https://docs.amazonaws.cn/apigateway/latest/developerguide/how-to-custom-domains.html。
3.5 测试调用
使用如下命令分别在本地电脑和 EC2 上测试访问接口。参考命令:curl -s -XGET https://xxx.xxx.xxx.xxx.org.cn/demo。
如下截图证明您已经可以正常访问:
4. 方案总结
本篇博客从客户实际需求出发,实现了使用相同自定义域名从互联网和内部网络(包括云上以及本地数据中心通过 VPN 或专线)访问 API GW 的场景,但由于 API GW 的自定义域名功能仅支持 Regional API,需要在 API GW 配置时使用 Regional 和 Private 两个不同的 API 实现,两个 API 接口连接到相同的 Lambda 函数,同时在 Custom Domain Names 的配置中利用不同的 Path 映射来区分。在域名解析部分,公网部分可以使用 Route53 的 Public Zone 或者是域名提供商的解析服务,内网部分可以使用 Route53 的 Private Zone,如果是跨 VPC 调用的场景,还需要配合 VPC 互联以及支持多 VPC 的 Private Zone。