**发布时间:** 2025-11-10
**厂商:** AWS
**类型:** BLOG
**原始链接:** https://aws.amazon.com/blogs/networking-and-content-delivery/use-amazon-vpc-lattice-to-streamline-and-secure-tcp-resource-connectivity-across-multiple-aws-accounts/
---
<!-- AI_TASK_START: AI标题翻译 -->
[解决方案] 使用 Amazon VPC Lattice 简化并保护跨 AWS 账户的 TCP 资源连接
<!-- AI_TASK_END: AI标题翻译 -->
<!-- AI_TASK_START: AI竞争分析 -->
# 解决方案分析
## 解决方案概述
该解决方案详细阐述了如何使用 **Amazon VPC Lattice** 在 **AWS Organizations** 环境中,为跨多个AWS账户的 **TCP资源** (如数据库) 建立精简且安全的连接。其核心目标是解决在多账户架构下,安全访问中心化共享资源(如 **Amazon RDS** 数据库)的普遍难题,同时避免采用复杂的传统网络方案,如VPC Peering或Transit Gateway。
该方案适用于企业将不同环境(如开发、测试、生产)或不同业务单元隔离在独立AWS账户下的场景。其技术原理是:在一个中心化的“网络账户”中创建 **VPC Lattice 服务网络 (Service Network)** 作为逻辑边界,并通过 **AWS RAM** 将其共享给其他成员账户。资源提供方(如“数据库账户”)通过 **资源网关 (Resource Gateway)** 和 **资源配置 (Resource Configuration)** 将RDS数据库实例安全地发布到服务网络中。而资源消费方(如“应用账户”)则在其VPC内创建 **服务网络VPC终端节点 (Service Network VPC Endpoint)** 来接入该服务网络,并通过VPC Lattice的 **私有DNS集成** 功能,使用数据库的原始DNS名称透明地访问资源。
## 实施步骤
1. **环境准备与配置**
- 在所有相关AWS账户的VPC中,确认已启用 **DNS主机名** (`EnableDnsHostnames`) 和 **DNS解析** (`EnableDnsSupport`) 属性。
- 在AWS Organizations管理账户中启用 **AWS Resource Access Manager (RAM)**,以支持跨账户资源共享。
2. **创建并共享服务网络 (在中心网络账户中操作)**
- 在专用的“Networks”账户中,使用AWS CLI创建一个 **VPC Lattice服务网络**,作为跨账户连接的中心枢纽。
- 使用 **AWS RAM** 创建一个资源共享,将上一步创建的服务网络共享给资源所在的“Databases”账户以及需要访问资源的“Applications”和“Tools”账户。
3. **发布TCP资源 (在数据库账户中操作)**
- 部署目标资源,例如创建一个私有的 **Amazon RDS for MySQL** 实例,并为其配置专用的安全组和子网组。
- 创建一个 **资源网关 (Resource Gateway)** 作为VPC Lattice流量的入口,并为其配置一个严格的安全组,该安全组的出站规则仅允许流量流向RDS实例的安全组及特定端口(如TCP 3306)。
- 创建一个 **资源配置 (Resource Configuration)**,通过指定RDS实例的 **ARN** 来定义要暴露的资源。使用ARN的优势在于客户端可以继续使用数据库的原始DNS终端节点进行访问。
- 将此资源配置与从中心网络账户共享而来的服务网络进行关联,使其对服务网络内的其他成员可见。
4. **创建接入点并消费资源 (在应用账户中操作)**
- 在“Applications”账户的VPC中,创建一个类型为 `ServiceNetwork` 的 **VPC终端节点**,并将其关联到共享的服务网络ARN。
- 为该终端节点配置一个安全组,以实现精细的访问控制。文档演示了一种安全最佳实践:添加入站规则,仅允许来自拥有相同安全组的资源的流量访问数据库端口,从而实现严格的客户端隔离。
- 创建终端节点时启用 **私有DNS (`PrivateDnsEnabled`)** 功能。这使得VPC Lattice能够拦截发往RDS原始DNS名称的请求,并将其路由到服务网络,对客户端应用完全透明。
5. **连接与验证**
- 在应用账户的VPC内启动一个客户端环境(如 **AWS CloudShell**),并确保其网络配置中包含了VPC终端节点的安全组。
- 使用标准的MySQL客户端和RDS的原始私有DNS名称发起连接,验证跨账户数据库访问是否成功。
- 可在其他消费方账户(如“Tools”账户)重复步骤4,以验证多账户访问能力。
## 方案客户价值
- **简化网络管理**
- 彻底消除了传统跨账户连接所需的复杂配置,如 **VPC Peering**、**Transit Gateway路由表** 和网络ACLs。VPC Lattice将连接管理从网络层(IP/CIDR)提升到应用层(服务),显著降低了运维复杂度。
- **增强零信任安全性**
- 通过集中的服务网络策略和在资源网关、VPC终端节点层面的 **精细化安全组控制**,构建了强大的安全边界。
- 连接不依赖于IP地址,天然避免了VPC CIDR重叠问题,并大幅减少了网络攻击面。
- **提升开发敏捷性**
- 开发者无需关注底层网络拓扑,通过 **服务发现** 和 **私有DNS集成**,可以使用稳定、统一的资源终端节点(如RDS的DNS名称)进行连接,实现了应用与网络基础设施的解耦。
- _运维效率得到提升_,因为网络连接的配置和权限管理被集中在VPC Lattice服务网络中,而非分散在各个VPC的网络组件上。
- **构建可扩展架构**
- 该模式具备良好的可扩展性,可以轻松地将更多TCP资源(如其他数据库、缓存服务)发布到同一个服务网络,并共享给新的消费方账户,形成一个可扩展、易于管理的服务网格。
## 涉及的相关产品
- **Amazon VPC Lattice**: 解决方案的核心,提供服务网络、资源网关等组件,用于构建跨VPC和跨账户的应用层网络。
- **Amazon RDS**: 作为被安全访问的目标TCP资源示例。
- **AWS Organizations**: 用于集中管理多账户环境,是实现跨账户资源共享的基础。
- **AWS Resource Access Manager (RAM)**: 用于在AWS账户之间安全地共享VPC Lattice服务网络等资源。
- **Amazon VPC**: 提供基础网络环境,包括VPC、子网、安全组和VPC终端节点。
- **AWS CLI** & **AWS CloudShell**: 用于自动化部署、管理和测试该解决方案的命令行工具。
## 技术评估
- **优势**
- **高层抽象**: VPC Lattice工作在比传统网络原语(如路由表、Peering)更高的抽象层,关注“服务”而非“IP”,从根本上简化了多账户服务通信的管理。
- **原生安全集成**: 与IAM、AWS RAM和VPC安全组等AWS原生服务深度集成,提供了强大的、分层的安全控制能力。特别是通过ARN引用RDS资源和精细的安全组策略,实现了非常严格的访问控制。
- **透明客户端体验**: 私有DNS集成是该方案的一大亮点。客户端应用程序无需任何代码或配置修改,即可使用资源的原始DNS名称进行连接,极大地降低了应用的迁移和采用成本。
- **可能的限制**
- **协议支持**: 该方案明确针对TCP资源。VPC Lattice虽然也支持HTTP/HTTPS/gRPC,但对于其他协议(如UDP)则不适用。
- **成本考量**: 作为一项全托管服务,VPC Lattice会产生相应的费用(例如,数据处理费、终端节点小时费等)。客户在采用前,需将其总体拥有成本与Transit Gateway等传统方案进行比较。
- **区域性服务**: VPC Lattice是一项区域性服务。若要实现跨区域的服务连接,需要结合其他AWS全球网络服务(如Cloud WAN或跨区VPC Peering)。
<!-- AI_TASK_END: AI竞争分析 -->
<!-- AI_TASK_START: AI全文翻译 -->
# 使用 Amazon VPC Lattice 简化并保护跨多个 AWS 账户的 TCP 资源连接
**原始链接:** [https://aws.amazon.com/blogs/networking-and-content-delivery/use-amazon-vpc-lattice-to-streamline-and-secure-tcp-resource-connectivity-across-multiple-aws-accounts/](https://aws.amazon.com/blogs/networking-and-content-delivery/use-amazon-vpc-lattice-to-streamline-and-secure-tcp-resource-connectivity-across-multiple-aws-accounts/)
**发布时间:** 2025-11-10
**厂商:** AWS
**类型:** BLOG
---
本指南将演示如何使用 [Amazon VPC Lattice](https://aws.amazon.com/vpc/lattice/) 在 Amazon Web Services (AWS) [Organizations](https://aws.amazon.com/organizations/) 环境中的多个 AWS 账户之间建立安全的 TCP 资源连接。我们将展示如何在一个集中式网络账户中创建一个服务网络,并将其与其他账户共享,以实现安全的跨账户数据库访问。
## 准备工作
在本文中,我们将在一个 Organization 内使用多个 AWS 账户,并假设您对以下服务有基本的了解:
- [Amazon Virtual Private Cloud (Amazon VPC)](https://aws.amazon.com/vpc/)
- AWS [Organizations](https://aws.amazon.com/organizations/)
- [AWS Resource Access Manager](https://aws.amazon.com/ram/) (AWS RAM)
- [Amazon Relational Database Service](https://aws.amazon.com/rds/) (Amazon RDS)
- [AWS Command Line Interface](https://aws.amazon.com/cli/) (AWS CLI)
- [AWS CloudShell](https://aws.amazon.com/cloudshell/)
- [安全组 (Security Groups)](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-security-groups.html)
此外,为成功完成设置,还需要进行以下预配置:
- [启用 VPC DNS 属性](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns-updating.html) — DNS 主机名和 DNS 解析
- 在 Organization 级别 [启用 Resource Access Manager](https://docs.aws.amazon.com/ram/latest/userguide/getting-started-sharing.html#getting-started-sharing-orgs)
## 用于跨账户访问的 VPC Lattice 组件
以下各节概述了在 VPC Lattice 中实现跨账户访问的关键组件。
### 服务网络
服务网络 (service network) 是大规模实现跨账户连接的基础组件。它充当您资源的逻辑容器。其主要特性包括:
1. 服务网络帮助您对相关的服务或资源配置进行分组。
2. 服务网络提供一致的安全策略。
3. 服务网络可以使用 AWS RAM 与其他 AWS 账户共享。
VPC 有两种方式可以连接到服务网络:
4. *服务网络 VPC 关联 (Service network VPC association, SN-A)*:允许部署在 VPC 中的客户端访问服务网络。服务网络无法从关联的 VPC 外部访问。一个 VPC 只能有一个服务网络关联。
5. *服务网络 VPC 终端节点 (Service network VPC endpoint, SN-E)*:与 SN-A 相比,它允许部署在 VPC 中的客户端以更多方式访问服务网络。如果客户端与 VPC 具有网络连接,它还允许 VPC 外部的客户端访问相应的服务网络 VPC 终端节点。例如,客户端可以通过 [AWS Cloud WAN](https://aws.amazon.com/cloud-wan/) 或 [AWS Transit Gateway](https://aws.amazon.com/transit-gateway/) 从对等的 VPC 访问服务网络 VPC 终端节点,或者通过 [AWS Direct Connect](https://aws.amazon.com/directconnect/) 或 [AWS Site-to-Site VPN](https://aws.amazon.com/vpn/site-to-site-vpn/) 从本地访问。
### VPC Lattice 服务
一个 [VPC Lattice 服务](https://docs.aws.amazon.com/vpc-lattice/latest/ug/services.html) 由侦听器 (协议和端口号)、用于控制应用程序流的路由规则 (例如,基于路径、方法、标头或加权路由) 以及一个或多个目标组 (target groups) 组成,这些目标组定义了您的应用程序基础设施。
VPC Lattice 服务代表了需要跨账户访问的应用程序和 API。其主要特性包括:
1. 支持多种协议:HTTP、HTTPS、gRPC 和 TLS。
2. 可配置的路由规则。
3. 可使用 AWS RAM 跨账户共享。
4. 内置身份验证和授权功能。
### VPC 资源
资源可以是一个 IP 地址、一个域名 (DNS) 目标,或一个 RDS 数据库的 [Amazon 资源名称 (Amazon Resource Name, ARN)](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html) 。该资源被封装在一个 [资源配置 (resource configuration)](https://docs.aws.amazon.com/vpc-lattice/latest/ug/resource-configuration.html) 中,并通过一个 [资源网关 (resource gateway)](https://docs.aws.amazon.com/vpc-lattice/latest/ug/resource-gateway.html) 使用 TCP 协议进行连接。在 RDS 数据库的资源配置中使用 ARN 的好处是,消费者 VPC 中的客户端可以使用其实际终端节点访问该数据库。
资源网关是进入资源所在 VPC 的入口点。资源配置定义了您的 TCP 资源如何在 VPC Lattice 网络中被暴露和访问。其主要特性包括:
1. 支持的协议是 TCP。
2. 多个资源配置可以附加到单个资源网关。
3. 资源配置可以使用 AWS RAM 跨账户共享。或者,如果您共享一个服务网络,那么该服务网络内的所有资源配置都将与另一个 AWS 账户共享。
在下一节中,我们将通过使用资源配置和资源网关,展示 SN-E 终端节点如何连接到 VPC Lattice 服务网络中的资源。
## 架构概览
下图展示了您将在本文中构建的跨账户网络连接的高层架构示例。

图 1: VPC Lattice 服务网络在 AWS 区域内跨多个账户共享的高层架构。
## 设置跨账户访问:分步指南
在本节中,我们提供了一个使用 AWS CLI 的分步流程,以安全地从多个账户 (即 “Applications” 和 “Tools” 账户) 访问位于 “Databases” 账户中的 RDS 数据库。为了集中管理 VPC Lattice 服务网络,您将在一个专用的 “Networks” 账户中创建服务网络,并将其与其他账户共享。为了完整性,我们还将展示创建 RDS 数据库的步骤。该数据库不应公开访问,并且应使用仅包含私有子网的数据库子网组。
### 步骤 1:检查所有 AWS 账户是否已启用 DNS 设置
您可以使用以下命令检查 VPC 级别的 DNS 设置:`EnableDnsSupport` 和 `EnableDnsHostnames` 是否已启用。在下面的代码块中为您的账户设置正确的 “VPC_ID” 值。请为您将用于此演示的所有账户检查此项。
列出您账户中的 VPC
```bash
aws ec2 describe-vpcs --query "Vpcs[].[VpcId,CidrBlock]" \
--output text vpc-04d98b8b24aab7e20 172.31.0.0/16
```
将 vpc id 设置在一个变量中 `VPC_ID=”vpc-04d98b8b24aab7e20″`
打印是否启用了 DNS 支持
```bash
aws ec2 describe-vpc-attribute \
--vpc-id ${VPC_ID} --attribute enableDnsSupport \
--output text vpc-04d98b8b24aab7e20
ENABLEDNSSUPPORT False
```
打印是否启用了 DNS 主机名
```bash
aws ec2 describe-vpc-attribute \
--vpc-id ${VPC_ID} --attribute enableDnsHostnames \
--output text vpc-04d98b8b24aab7e20
ENABLEDNSHOSTNAMES False
```
如果 DNS 解析设置未启用,请使用以下 AWS CLI 命令启用它们。
仅当 DNS 属性未处于启用状态时才运行这些命令。
将您的 vpc id 保存在一个变量中
```bash
VPC_ID="vpc-04d98b8b24aab7e20"
```
启用 DNS 主机名
```bash
aws ec2 modify-vpc-attribute \
--vpc-id ${VPC_ID} \
--enable-dns-hostnames "{\"Value\":true}"
```
启用 DNS 解析
```bash
aws ec2 modify-vpc-attribute \
--vpc-id ${VPC_ID} \
--enable-dns-support "{\"Value\":true}"
```
### 步骤 2:在网络账户中设置服务网络
我们正在使用一些变量,以便您可以在本节的所有命令中一致地使用重要的属性值。在此示例中,我们使用 `DB_ACCT_ID` 来指定 RDS 资源所在的数据库账户的账户 ID。`APP_ACCT_ID` 和 `TOOLS_ACCT_ID` 是我们为需要访问 RDS 资源的客户端应用程序所在的账户 ID 指定的两个变量。
指定您的数据库账户
```bash
DB_ACCT_ID=1234567890
```
指定您的应用程序账户 id
```bash
APP_ACCT_ID=3456789012
```
指定您的工具账户 id
```bash
TOOLS_ACCT_ID=5678901234
```
您要创建的服务网络的名称
```bash
SVC_NW_NAME="prod-services"
```
RAM 资源共享的名称
```bash
RAM_SHARE_NAME="prod-services-share"
```
在网络账户中创建服务网络。
创建服务网络并将服务网络 ARN 保存在 SVC_NW_ARN 变量中。
```bash
SVC_NW_ARN=$(aws vpc-lattice create-service-network /
--name ${SVC_NW_NAME} /tags Key=Environment,Value=Production /
query 'arn' --output text)
```
与其他账户共享服务网络:数据库、应用程序和工具。
与所需账户共享服务网络
```bash
aws ram create-resource-share \
--name ${RAM_SHARE_NAME} \
--resource-arns ${SVC_NW_ARN} \
--principals ${DB_ACCT_ID} ${APP_ACCT_ID} ${TOOLS_ACCT_ID}
```
### 步骤 3:在数据库账户中创建 RDS 资源和资源配置
在创建资源配置之前,您需要一个 RDS 数据库。在本文中,创建一个新的 RDS 数据库,并为其配置自己的数据库子网组和安全组。首先,我们设置一些重要的变量,以便您可以在所有命令中一致地使用它们。您应该为数据库子网组使用私有子网。指定 RDS 子网 ID 和 VPC ID 的变量。
列出可用于数据库子网组的 VPC 子网
```bash
aws ec2 describe-subnets \
--query 'Subnets[].[VpcId,SubnetId,CidrBlock,AvailabilityZone]' \
--output table
---------------------------------------------------------------------------------------
| DescribeSubnets |
+------------------------+----------------------------+-----------------+-------------+
| vpc-054a89f1743629a5a | subnet-00e9566065f274aa0 | 172.31.32.0/20 | us-east-1a |
| vpc-054a89f1743629a5a | subnet-0265a446d8838de07 | 172.31.48.0/20 | us-east-1e |
| vpc-054a89f1743629a5a | subnet-02bd22ba455d2b292 | 172.31.80.0/20 | us-east-1c |
| vpc-054a89f1743629a5a | subnet-062da40b8991dc44e | 172.31.64.0/20 | us-east-1f |
| vpc-054a89f1743629a5a | subnet-0f40c436b91246b36 | 172.31.16.0/20 | us-east-1d |
| vpc-054a89f1743629a5a | subnet-0d2d7b6f1e0dcc563 | 172.31.0.0/20 | us-east-1b |
+------------------------+----------------------------+-----------------+-------------+
```
设置一个变量以列出您要用于数据库子网组的私有子网标识符
```bash
RDS_SUBNET_IDS="subnet-00e9566065f274aa0 subnet-0265a446d8838de07"
```
指定子网的 VPC id
```bash
DB_VPC_ID=vpc-0fcf941a64cbb74e7
```
设置我们用于本节其余命令的其余变量。
设置您将创建的 RDS 子网组的名称
```bash
RDS_SUBNET_GRP_NAME=rds-subnet-group
```
设置您将创建的 RDS 安全组的名称
```bash
RDS_SECURITY_GROUP=rds-security-group
```
设置您将创建的 RDS 参数组的名称
```bash
RDS_PARAM_GROUP_NAME=mysql-params
```
设置您将创建的 RDS 数据库的名称
```bash
RDS_NAME=mysql-prod
```
为您将创建的资源网关的安全组设置一个名称
```bash
RESGW_SECGRP_NAME=resource-gw-sec-grp
```
为您将创建的资源网关设置一个名称
```bash
RESOURCE_GATEWAY=prod-resource-gateway
```
设置您将创建的资源配置的名称
```bash
RES_CONFIG_NAME=rds-config
```
设置由网络账户共享的服务网络的名称
```bash
SERVICE_NETWORK_NAME=prod-services
```
为数据库创建一个安全组,并为数据库目标端口添加入站规则。对于以下入站规则的 `CidrIp` 属性,请确保您使用适用于数据库账户中 VPC 的有效源 IP 地址范围。
创建安全组并将返回的安全组 id 保存在一个变量中
```bash
RDS_SG_ID=$(aws ec2 create-security-group \
--group-name ${RDS_SECURITY_GROUP} \
--description "Security group for RDS instance" \
--vpc-id ${DB_VPC_ID} \
--query 'GroupId' --output text)
```
向安全组添加入站规则
```bash
aws ec2 authorize-security-group-ingress \
--group-id ${RDS_SG_ID} \
--ip-permissions '[{"IpProtocol": "tcp", "FromPort": 3306, "ToPort": 3306, "IpRanges": [{"CidrIp": "172.31.0.0/16"}], "Ipv6Ranges": []}]
```
创建数据库子网组。
创建数据库子网组
```bash
aws rds create-db-subnet-group \
--db-subnet-group-name "${RDS_SUBNET_GRP_NAME}" \
--db-subnet-group-description "Subnet group for RDS" \
--subnet-ids ${RDS_SUBNET_IDS}
```
创建数据库参数组。
创建 RDS 参数组
```bash
aws rds create-db-parameter-group \
--db-parameter-group-family mysql8.0 \
--db-parameter-group-name "${RDS_PARAM_GROUP_NAME}" \
--description "MySQL parameter group"
```
您可以使用刚刚创建的 RDS 安全组、子网组和参数组来创建 RDS 实例。
创建 MySQL RDS 实例
```bash
aws rds create-db-instance \
--db-instance-identifier ${RDS_NAME} \
--db-instance-class db.t3.medium \
--engine mysql \
--engine-version "8.0" \
--master-username admin \
--master-user-password "YourSecurePassword123!" \
--allocated-storage 20 \
--storage-type gp3 \
--vpc-security-group-ids ${RDS_SG_ID} \
--db-subnet-group-name "${RDS_SUBNET_GRP_NAME}" \
--db-parameter-group-name "${RDS_PARAM_GROUP_NAME}" \
--backup-retention-period 7 \
--no-multi-az \
--port 3306 \
--no-publicly-accessible \
--tags Key=Environment,Value=Production
```
等待 RDS 实例可用并查看其 ARN 标识符
```bash
aws rds describe-db-instances \
--db-instance-identifier ${RDS_NAME} \
--query "DBInstances[].DBInstanceArn" \
--output textarn:aws:rds:us-east-1:1234567890:db:mysql-prod
```
等待几分钟,直到 RDS 实例变为可用状态。
现在 RDS 实例已经创建,您可以按照 VPC Lattice 的配置步骤进行操作。
为资源网关创建一个安全组。为了演示严格的安全性,我们移除了默认的出站规则,并添加了一条严格的出站规则,仅允许从资源网关到数据库安全组 ID 的流量。这限制了流量只能从资源网关流向 RDS 数据库。在下面的代码块中,将 cidr IP 地址范围替换为您创建的资源网关安全组中的范围。
为资源网关创建安全组并将安全组 id 保存在一个变量中。
```bash
RESGW_SG_ID=$(aws ec2 create-security-group \
--group-name ${RESGW_SECGRP_NAME} \
--description "Security group for RDS instance" \
--vpc-id ${DB_VPC_ID} \
--query 'GroupId' \
--output text)
```
从资源网关安全组中删除默认的出站规则
```bash
aws ec2 revoke-security-group-egress \
--group-id ${RESGW_SG_ID} \
--protocol all\
--port all \
--cidr 172.31.0.0/16
```
向 RDS 安全组添加限制性出站规则
```bash
aws ec2 authorize-security-group-egress \
--group-id ${RESGW_SG_ID} \
--ip-permissions '[{"IpProtocol": "tcp", "FromPort": 3306, "ToPort": 3306, "UserIdGroupPairs": [{"GroupId": "'${RDS_SG_ID}'"}], "Ipv6Ranges": []}]'
```
创建一个资源网关并将网关 id 保存在一个变量中
```bash
RES_GW_ID=$(aws vpc-lattice create-resource-gateway \
--name "${RESOURCE_GATEWAY}" \
--vpc-identifier ${DB_VPC_ID} \
--security-group-ids ${RESGW_SG_ID} \
--subnet-ids ${RDS_SUBNET_IDS} \
--tags Key=Environment,Value=Production \
--query "id" \
--output text)
```
接下来,使用刚刚创建的资源网关和 RDS 安全组的 ARN 创建资源配置。
获取 RDS ARN 标识符
```bash
RDS_ARN=$(aws rds describe-db-instances \
--db-instance-identifier ${RDS_NAME} \
--query "DBInstances[].DBInstanceArn" \
--output text)
```
使用 RDS arn 创建资源配置并将资源配置 id 保存在一个变量中。
```bash
RES_CFG_ID=$(aws vpc-lattice create-resource-configuration \
--name ${RES_CONFIG_NAME} \
--allow-association-to-shareable-service-network \
--resource-gateway-identifier ${RES_GW_ID} \
--type ARN \
--resource-configuration-definition "arnResource={arn=${RDS_ARN}}" \
--tags Key=Environment,Value=Production \
--query 'id' \
--output text)
```
最后,将资源配置添加到共享的服务网络中,以便消费者应用程序可以通过我们稍后在工具账户中创建的 VPC 终端节点访问它。
根据 SERVICE_NETWORK_NAME 变量中指定的共享服务网络名称获取共享服务网络 id。
```bash
SVC_NW_ID=$(aws vpc-lattice list-service-networks --query "items[?name=='$SERVICE_NETWORK_NAME'].id" --output text)
```
将共享服务网络与资源配置关联
```bash
aws vpc-lattice create-service-network-resource-association \
--service-network-identifier ${SVC_NW_ID} \
--resource-configuration-identifier
${RES_CFG_ID}{ "arn": "arn:aws:vpc-lattice:us-east-1:9012345678:servicenetworkresourceassociation/snra-004e578511aed83c0", "createdBy": "9012345678", "id": "snra-004e578511aed83c0", "status": "CREATE_IN_PROGRESS"}
```
几秒钟后,您可以运行以下命令以确认资源配置关联状态为 ACTIVE。
```bash
aws vpc-lattice list-service-network-resource-associations --query
"items[].{serviceNetworkName:serviceNetworkName,id:id,status:status,privateDnsEntry:privateDnsEntry}" --output text snra-004e578511aed83c0 None prod-services ACTIVEsnra-0c6221d3131abd168 {'domainName': 'mysql-prod.czqq4qaoegqb.us-east-1.rds.amazonaws.com'} prod-services ACTIVE
```
### 步骤 4:在应用程序账户中设置服务网络终端节点
在此步骤中,我们设置本节命令所需的一些重要变量。
获取我们消费者账户的 VPC id 并保存在一个变量中
```bash
APP_VPC_ID=$(aws ec2 describe-vpcs --query "Vpcs[].VpcId" --output text)
```
打印并确认 VPC id 是否正确
```bash
echo $APP_VPC_ID
```
为您将创建的 VPC 终端节点的安全组设置一个名称
```bash
ENDPT_SECGRP_NAME=endpt_secgrp
```
获取共享服务网络的 arn 并保存在一个变量中
```bash
SHARED_SVC_NW_ARN=$(aws vpc-lattice list-service-networks --query "items[].arn" --output text)
```
# 验证服务网络 arn 是否已分配给变量
```bash
echo $SHARED_SVC_NW_ARN
arn:aws:vpc-lattice:us-east-1:9012345678:servicenetwork/sn-0c68c9e9d598dacd5
```
列出所有子网
```bash
aws ec2 describe-subnets --query "Subnets[].[VpcId,AvailabilityZoneId,SubnetId,CidrBlock]" --output text
use1-az3 172.31.48.0/20 subnet-008486d18c8ffb93f
use1-az5 172.31.64.0/20 subnet-0b66ff1bdd5755f78
use1-az4 172.31.16.0/20 subnet-0c2ca46dee76f4192
use1-az2 172.31.80.0/20 subnet-0ad4d61ccd3b1f7c6
use1-az6 172.31.32.0/20 subnet-07157df629136dd87
use1-az1 172.31.0.0/20 subnet-0d9da76ade9981c13
```
设置我们想用于终端节点的私有子网。
```bash
ENDPT_SUBNET_IDS="subnet-0ad4d61ccd3b1f7c6 subnet-0b66ff1bdd5755f78 subnet-0c2ca46dee76f4192"
```
首先,我们创建安全组来控制对终端节点的入站访问。为实现严格的安全性,我们移除了默认的出站规则,并添加了一条限制性入站规则,只允许来自同样关联了终端节点安全组的资源的数据库端口访问。因此,只有同样拥有资源网关安全组的客户端资源才能通过 VPC 终端节点连接到数据库端口。这使我们能够通过简单地在其安全组设置中添加或移除终端节点安全组,来快速启用或禁用 VPC 中哪些客户端可以通过终端节点连接到 RDS ARN。
为终端节点创建一个安全组并将安全组名称保存在一个变量中
```bash
ENDPT_SG_ID=$(aws ec2 create-security-group \
--group-name ${ENDPT_SECGRP_NAME} \
--description "Secgrp for vpc lattice endpoint" \
--vpc-id ${APP_VPC_ID} \
--query 'GroupId' \
--output text)
```
从资源网关安全组中删除默认的出站规则
```bash
aws ec2 revoke-security-group-egress \
--group-id ${ENDPT_SG_ID} \
--protocol all\
--port all \
--cidr 0.0.0.0/0
```
向终端节点安全组添加限制性入站规则
```bash
aws ec2 authorize-security-group-ingress \
--group-id ${ENDPT_SG_ID} \
--ip-permissions '[{"IpProtocol": "tcp", "FromPort": 3306, "ToPort": 3306, "UserIdGroupPairs": [{"GroupId": "'${ENDPT_SG_ID}'"}], "Ipv6Ranges": []}]'
```
我们可以使用刚刚创建的安全组来创建服务网络 VPC 终端节点。
创建类型为服务网络且启用私有 dns 的 vpc 终端节点
```bash
aws ec2 create-vpc-endpoint \
--vpc-id ${APP_VPC_ID} \
--subnet-ids ${ENDPT_SUBNET_IDS} \
--security-group-ids ${ENDPT_SG_ID} \
--vpc-endpoint-type ServiceNetwork \
--service-network-arn ${SHARED_SVC_NW_ARN} \
--private-dns-enabled \
--tag-specifications "ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=prod-rds-endpoint}]"
{ "VpcEndpoint":
{ "VpcEndpointId": "vpce-09f574bdc289d2c48", "VpcEndpointType": "ServiceNetwork",
"VpcId": "vpc-0625d6567a455ba29",
"State": "Pending",
"SubnetIds": [
"subnet-0ad4d61ccd3b1f7c6", "subnet-0b66ff1bdd5755f78", "subnet-0c2ca46dee76f4192" ],
"Groups": [
{
"GroupId": "sg-00b013fceee153870", "GroupName": "endpt_secgrp"
} ],
"IpAddressType": "IPV4", "PrivateDnsEnabled": true, "CreationTimestamp": "2025-05-17T15:50:12.729000+00:00",
"Tags": [
{ "Key": "Name", "Value": "prod-rds-endpoint" }
],
"OwnerId": "3456789012",
"ServiceNetworkArn": "arn:aws:vpc-lattice:us-east-1:9012345678:servicenetwork/sn-0c68c9e9d598dacd5" }}
```
几秒钟后,检查终端节点是否处于 `Available` 状态。
验证终端节点状态
```bash
aws ec2 describe-vpc-endpoints --query "VpcEndpoints[?VpcEndpointType == 'ServiceNetwork'].{VpcEndpointId:VpcEndpointId,State:State}" --output textAvailable
vpce-09f574bdc289d2c48
```
如果终端节点状态正常,则打印终端节点详细信息以验证 RDS 终端节点的私有 DNS 名称是否可见。
将 VPC 终端节点 id 设置在一个变量中
```bash
ENDPT_ID=$(aws ec2 describe-vpc-endpoints --query "VpcEndpoints[?VpcEndpointType == 'ServiceNetwork'].VpcEndpointId" --output text)
```
打印 RDS 的私有 DNS 条目已列出且对该终端节点是 ‘Accessible’ (可访问的)。
```bash
aws ec2 describe-vpc-endpoint-associations --query "VpcEndpointAssociations[?VpcEndpointId == '${ENDPT_ID}'].{ServiceNetworkName:ServiceNetworkName,AssociatedResourceAccessibility:AssociatedResourceAccessibility,PrivateDnsEntry:PrivateDnsEntry.DnsName}" --output textAccessible
mysql-prod.czqq4qaoegqb.us-east-1.rds.amazonaws.com prod-services
```
最后,在 VPC 环境中打开一个 CloudShell,如下图所示,同时将 `endpt_secgrp` 安全组也附加到它上面,这样您就可以连接到 VPC 服务网络终端节点而不会被终端节点的安全组阻止。

图 2: 在 VPC 环境中启动 CloudShell,并同时选择 VPC 终端节点的安全组
使用 MySQL 命令,如下面的屏幕截图所示,并使用 RDS 数据库的私有 DNS 条目。

图 3: 跨账户使用其私有 DNS 条目连接到 MySQL RDS 数据库。
可选地,在 **Tools** 账户中也重复本节中的相同步骤,以创建一个服务网络终端节点,并从运行在 [Amazon Elastic Compute Cloud (Amazon EC2)](https://aws.amazon.com/ec2/) 、[Amazon Elastic Kubernetes Service (Amazon EKS)](https://aws.amazon.com/eks/) 或 [Amazon Elastic Container Service (Amazon ECS)](https://aws.amazon.com/ecs/) 等资源上的应用程序进行连接。这可以帮助您确认同一个 RDS 资源可以从 **Tools** 账户以及 **Applications** 账户访问。
至此,设置过程结束。您可以按照下一节中的清理步骤删除您在本文中创建的所有资源。
## 清理步骤
我们将在所有三个 AWS 账户中清理资源。
### 清理应用程序账户
删除为测试创建的 CloudShell。

从应用程序账户中删除服务网络终端节点和安全组。
如有必要,确认类型为服务网络的 vpc 终端节点 id
```bash
ENDPT_ID=$(aws ec2 describe-vpc-endpoints --query "VpcEndpoints[?VpcEndpointType == 'ServiceNetwork'].VpcEndpointId" --output text)
```
验证终端节点 id
```bash
echo $ENDPT_ID
```
通过提供正确的终端节点 id 删除终端节点
```bash
aws ec2 delete-vpc-endpoints --vpc-endpoint-ids ${ENDPT_ID}
```
终端节点删除后,删除安全组
```bash
aws ec2 delete-security-group --group-name endpt_secgrp
```
如果您在 “Tools” 账户中也创建了终端节点,请在该账户中重复相同的清理步骤。
### 清理数据库账户
删除资源配置及相关资源。
列出资源配置服务网络关联标识符
```bash
SNRA_ID=$(aws vpc-lattice list-service-network-resource-associations --query "items[?resourceConfigurationName=='rds-config'].{id:id}" --output text)
```
验证 snra id 已设置
```bash
echo $SNRA_IDsnra-004e578511aed83c0
```
删除资源配置的服务网络关联。这可能需要几秒钟才能完成。
```bash
aws vpc-lattice delete-service-network-resource-association --service-network-resource-association-identifier ${SNRA_ID}{ "arn": "arn:aws:vpc-lattice:us-east-1:1234567890:servicenetworkresourceassociation/snra-004e578511aed83c0", "id": "snra-004e578511aed83c0", "status": "DELETE_IN_PROGRESS"}
```
获取要删除的资源配置标识符。
```bash
RES_CONFIG_ID=$(aws vpc-lattice list-resource-configurations --query "items[?name=='rds-config'].{id:id}" --output text)
```
打印资源配置 id 已设置
```bash
echo $RES_CONFIG_IDrcfg-0e7bfee3c5ef076b8
```
删除给定标识符的资源配置
```bash
aws vpc-lattice delete-resource-configuration --resource-configuration-identifier ${RES_CONFIG_ID}
```
获取要删除的资源网关的 id
```bash
RES_GW_ID=$(aws vpc-lattice list-resource-gateways --query "items[?name=='prod-resource-gateway'].{id:id}" --output text)
```
打印资源网关 id
```bash
echo $RES_GW_IDrgw-0888984b57580c3b8
```
删除给定标识符的资源网关
```bash
aws vpc-lattice delete-resource-gateway --resource-gateway-identifier ${RES_GW_ID}{ "arn": "arn:aws:vpc-lattice:us-east-1:1234567890:resourcegateway/rgw-0888984b57580c3b8", "id": "rgw-0888984b57580c3b8", "name": "prod-resource-gateway", "status": "DELETE_IN_PROGRESS"}
```
接下来的步骤如下。
列出要删除的资源网关安全组的 id
```bash
RES_SEC_GRP=$(aws ec2 describe-security-groups --query "SecurityGroups[?GroupName=='resource-gw-sec-grp'].{GroupId:GroupId}" --output text)
```
打印安全组名称已设置
```bash
echo $RES_SEC_GRPsg-000e5efb581214111
```
删除资源网关的安全组
```bash
aws ec2 delete-security-group --group-id ${RES_SEC_GRP}{ "Return": true, "GroupId": "sg-000e5efb581214111"}
```
删除 RDS。这可能需要几分钟才能完成。
```bash
aws rds delete-db-instance --db-instance-identifier mysql-prod --skip-final-snapshot
```
删除 RDS 参数组
```bash
aws rds delete-db-parameter-group –db-parameter-group-name mysql-params
```
删除 RDS 子网组
```bash
aws rds delete-db-subnet-group –db-subnet-group-name rds-subnet-group
```
设置要删除的 RDS 安全组的 id
```bash
RDS_SEC_GRP=$(aws ec2 describe-security-groups --query "SecurityGroups[?GroupName=='rds-security-group'].{GroupId:GroupId}" --output text)
```
检查安全组 id 是否已设置
```bash
echo $RDS_SEC_GRPsg-09edb207c44bfc884
```
删除 RDS 的安全组
```bash
aws ec2 delete-security-group –group-id ${RDS_SEC_GRP}
```
### 清理网络账户
删除 AWS RAM 共享和服务网络。
如有必要,获取资源共享 ARN
```bash
RAM_SHARE_ARN=$(aws ram get-resource-shares --resource-owner SELF --query "resourceShares[?name=='prod-services-share'].{resourceShareArn:resourceShareArn}" --output text)
```
打印 ram 共享 arn
```bash
echo $RAM_SHARE_ARNarn:aws:ram:us-east-1:9012345678:resource-share/ab2dab3f-f47c-4d0b-bfeb-ea23ca09d58f
```
删除给定 ARN 的资源共享
```bash
aws ram delete-resource-share --resource-share-arn ${RAM_SHARE_ARN}{ "returnValue": true}
```
获取要删除的服务网络的 id
```bash
SVC_NW_ID=$(aws vpc-lattice list-service-networks –query “items[?name==’prod-services’].{id:id}” –output text)
```
验证服务网络 id 已设置
```bash
echo $SVC_NW_IDsn-0c68c9e9d598dacd5
```
删除给定 id 的服务网络
```bash
aws vpc-lattice delete-service-network --service-network-identifier ${SVC_NW_ID}
```
## 结论
在本文中,我们展示了如何让运行在服务器或容器上的应用程序访问共享服务网络中的跨账户资源。这种设计模式可用于通过一个通用的服务网络来扩展更多资源的跨账户共享。
## 关于作者

### Rajesh Ambadi
Rajesh Ambadi 是媒体与娱乐 (M&E) 领域的技术客户经理。他喜欢通过创新的 AWS 解决方案来解决客户问题。

### Hammad Ausaf
Hammad Ausaf 是媒体与娱乐 (M&E) 领域的首席解决方案架构师。他是一位充满热情的构建者,并致力于为 AWS 客户提供最佳解决方案。
<!-- AI_TASK_END: AI全文翻译 -->