简介
私有配送应用需要读取 S3 中的清单。当前请求通过 NAT,但应用需要一条不依赖通用 Internet 出站访问的服务专用路径。你将创建 S3 网关端点,对比实际请求,诊断错误的路由表关联,并恢复预置网络。
请先完成 Give a Private Subnet Outbound Access。本次全新环境独立提供应用、S3 对象、公有和私有子网、NAT 网关及安全规则,CLI 已配置。保留预置资源和参考网络;只创建并最终删除自己的端点,恢复临时删除的私有 NAT 默认路由。
认证相关性
本实验为以下考试主题提供基础实践。
- Cloud Practitioner (CLF-C02) · 任务 3.5:VPC 网关和私有连接的作用。
- Solutions Architect – Associate (SAA-C03) · 任务 1.2:利用 AWS 服务端点和路由表访问私有应用所需的服务。
- CloudOps Engineer – Associate (SOA-C03) · 任务 5.1 和 5.3:配置 VPC 端点并诊断路由表关联。
- Advanced Networking – Specialty (ANS-C01) · 任务 3.1:维护服务路由并验证私有连通性的基础实践。
为私有应用创建 S3 网关端点
本步骤先检查当前 NAT 路径,再识别 S3 的服务地址范围并为私有路由表创建端点。
使用 Terminal 执行命令,在旁边打开 AWS View。应用保留私有地址 10.20.2.10;预置存储桶 parcel-delivery-storage 中的 message.txt 包含 Parcel manifest ready。
cd /home/labex/project
通过 Name 标签选择应用 VPC。过滤器选择资源,查询提取 ID,$(...) 将其保存在变量中供后续使用:
VPC_ID=$(aws ec2 describe-vpcs \
--filters Name=tag:Name,Values=application-network \
--query 'Vpcs[0].VpcId' \
--output text)
分别保存这个 VPC 的私有、公有路由表 ID。它们已有正确的子网关联:
PRIVATE_RT_ID=$(aws ec2 describe-route-tables \
--filters "Name=vpc-id,Values=$VPC_ID" Name=tag:Name,Values=private-routes \
--query 'RouteTables[0].RouteTableId' \
--output text)
PUBLIC_RT_ID=$(aws ec2 describe-route-tables \
--filters "Name=vpc-id,Values=$VPC_ID" Name=tag:Name,Values=public-routes \
--query 'RouteTables[0].RouteTableId' \
--output text)
读取两张表的路由和子网关联:
aws ec2 describe-route-tables \
--route-table-ids "$PRIVATE_RT_ID" "$PUBLIC_RT_ID" \
--query 'RouteTables[].{ID:RouteTableId,Routes:Routes,Associations:Associations}' \
--output json
私有默认路由 0.0.0.0/0 指向预置 NAT,公有默认路由指向 Internet 网关;两张表都保留 VPC 的 local 路由。保存 NAT ID,以便清理时恢复原始路由:
NAT_ID=$(aws ec2 describe-nat-gateways \
--filter "Name=vpc-id,Values=$VPC_ID" Name=state,Values=available \
--query 'NatGateways[0].NatGatewayId' \
--output text)
读取地址,供实际请求对比:
aws ec2 describe-nat-gateways \
--nat-gateway-ids "$NAT_ID" \
--query 'NatGateways[].{State:State,Addresses:NatGatewayAddresses}' \
--output json
在 AWS View 点击 Read storage object。请求返回 Success 和原始清单,Source address 为 NAT 公有地址。点击 Request outbound service,也应成功并报告同一 NAT 地址。这是最终需要恢复的基线。
AWS 托管前缀列表将指定区域的服务网络范围组合起来。S3 网关端点会在关联的路由表中添加指向该列表的路由,不会给应用分配公有地址,也不提供通用 Internet 访问。选出 S3 列表并检查 IPv4 范围:
PREFIX_ID=$(aws ec2 describe-prefix-lists \
--filters Name=prefix-list-name,Values=com.amazonaws.us-east-1.s3 \
--query 'PrefixLists[0].PrefixListId' \
--output text)
aws ec2 get-managed-prefix-list-entries \
--prefix-list-id "$PREFIX_ID" \
--query 'Entries[].Cidr' \
--output json
为 us-east-1 的 S3 服务创建网关端点,只关联私有路由表。--vpc-endpoint-type Gateway 选择基于路由的类型,--service-name 指定区域和服务,--route-table-ids 选择应用使用的表。标签帮助识别自己的练习资源:
ENDPOINT_ID=$(aws ec2 create-vpc-endpoint \
--vpc-id "$VPC_ID" \
--vpc-endpoint-type Gateway \
--service-name com.amazonaws.us-east-1.s3 \
--route-table-ids "$PRIVATE_RT_ID" \
--tag-specifications 'ResourceType=vpc-endpoint,Tags=[{Key=Name,Value=parcel-s3-endpoint},{Key=Project,Value=parcel}]' \
--query 'VpcEndpoint.VpcEndpointId' \
--output text)
读取状态和关联:
aws ec2 describe-vpc-endpoints \
--vpc-endpoint-ids "$ENDPOINT_ID" \
--query 'VpcEndpoints[].{ID:VpcEndpointId,State:State,Type:VpcEndpointType,Service:ServiceName,Tables:RouteTableIds}' \
--output json
等 State 为 available 再继续;若尚未就绪,等待几秒并重复同一查询。Type 应为 Gateway,服务为 S3,唯一关联表为私有表。保持此 Terminal 打开,以保留变量。
再次点击 Read storage object。清单不变,但源地址现在为 10.20.2.10。S3 前缀路由比 NAT 默认路由更具体,所以 S3 使用端点,普通出站流量仍使用 NAT。
没有 NAT 默认路由时仍访问 S3
本步骤删除通用出站路由,验证专用服务路径仍可读取 S3。
只删除私有表中的 NAT 默认路由,保留 NAT 网关、地址、公有路由及端点:
aws ec2 delete-route --route-table-id "$PRIVATE_RT_ID" --destination-cidr-block 0.0.0.0/0
成功删除没有输出。读取私有路由:
aws ec2 describe-route-tables \
--route-table-ids "$PRIVATE_RT_ID" \
--query 'RouteTables[].Routes' \
--output json
VPC 本地路由和 S3 的 DestinationPrefixListId 路由仍存在,默认路由消失。服务路由的 GatewayId 为端点 ID,状态为 active。端点路由通过端点关联管理,不应使用普通路由命令编辑或删除。
在 AWS View 点击 Read storage object:新的请求仍返回 Parcel manifest ready 和私有源地址 10.20.2.10。再点击 Request outbound service,由于 198.51.100.20:9000 不属于 S3 前缀且没有默认路由,请求失败。Request private application from outside 也失败。端点只提供 S3 的私有连接,不为应用分配公有地址或为其他 Internet 目标提供路由。

示例视图中,私有表仅有本地路由和 S3 前缀路由,没有 0.0.0.0/0。实际存储响应包含原始清单和源地址 10.20.2.10。预置 NAT 仍可用,但不在这条 S3 路径上。生成的 ID 和地址可能不同。
观察端点关联到错误路由表的结果
本步骤故意将端点移出应用使用的表,观察为什么可用端点也可能无法访问。
端点与路由表的关联、子网与路由表的关联是两种关系。本次只修改端点关联,不修改任何子网所属的表。将端点移到公有表:
aws ec2 modify-vpc-endpoint \
--vpc-endpoint-id "$ENDPOINT_ID" \
--add-route-table-ids "$PUBLIC_RT_ID" \
--remove-route-table-ids "$PRIVATE_RT_ID"
响应为 Return: true。读取端点:
aws ec2 describe-vpc-endpoints \
--vpc-endpoint-ids "$ENDPOINT_ID" \
--query 'VpcEndpoints[].{State:State,Tables:RouteTableIds}' \
--output json
状态仍为 available,但仅列出公有表。读取两张表:
aws ec2 describe-route-tables \
--route-table-ids "$PRIVATE_RT_ID" "$PUBLIC_RT_ID" \
--query 'RouteTables[].{ID:RouteTableId,Routes:Routes,Associations:Associations}' \
--output json
S3 自动前缀路由移到公有表,私有表因默认路由已删除而仅剩本地路由。原始子网关联保持不变。同处一个 VPC,并不表示所有子网都能使用某条端点路由。
等 AWS View 显示变更后,点击 Read storage object。新请求返回 Connection failed 和 Storage unavailable,因为应用使用的表没有 S3 路径。Request outbound service 也失败。以前成功的读取仅代表历史结果。保留这一故障供本步骤检查,下一步再修复。
恢复私有服务路由
本步骤不重建端点、不增加公有地址、不恢复 NAT 默认路由,只修复端点关联。
将同一个端点移回私有表,移除公有表关联:
aws ec2 modify-vpc-endpoint \
--vpc-endpoint-id "$ENDPOINT_ID" \
--add-route-table-ids "$PRIVATE_RT_ID" \
--remove-route-table-ids "$PUBLIC_RT_ID"
读取关联:
aws ec2 describe-vpc-endpoints \
--vpc-endpoint-ids "$ENDPOINT_ID" \
--query 'VpcEndpoints[].{State:State,Tables:RouteTableIds}' \
--output json
应仅列出私有表。再次检查两张路由表:
aws ec2 describe-route-tables \
--route-table-ids "$PRIVATE_RT_ID" "$PUBLIC_RT_ID" \
--query 'RouteTables[].{ID:RouteTableId,Routes:Routes}' \
--output json
私有 S3 前缀路由自动恢复,公有表中的 S3 端点路由消失,公有 Internet 路由保留。私有默认路由仍不存在。
在 AWS View 发起新的 Read storage object 请求,应成功读取原始清单,源地址为 10.20.2.10。Request outbound service 仍失败:S3 端点不提供通用 Internet 连接。Request private application from outside 也仍被阻断。修复恢复服务路径,并保留应用私有地址和原安全规则。
删除端点并恢复预置 NAT 基线
本步骤删除自己的练习端点,确认自动路由消失,并将私有默认路由恢复到预置 NAT。
只删除自己的端点:
aws ec2 delete-vpc-endpoints --vpc-endpoint-ids "$ENDPOINT_ID"
响应中的 Unsuccessful 列表必须为空。检查完整端点清单,不依赖可删除的标签过滤:
aws ec2 describe-vpc-endpoints \
--query 'VpcEndpoints[].{ID:VpcEndpointId,State:State,Tables:RouteTableIds}' \
--output json
端点可能仍以 deleted 状态列出,但不应有活动的练习端点。删除记录不能转发流量。如果仍为 deleting,等待几秒并重复相同清单查询。读取两张路由表:
aws ec2 describe-route-tables \
--route-table-ids "$PRIVATE_RT_ID" "$PUBLIC_RT_ID" \
--query 'RouteTables[].{ID:RouteTableId,Routes:Routes}' \
--output json
两张表都不应再有 S3 前缀路由。在 AWS View 点击 Read storage object;私有表仅有本地路由时,请求失败,说明没有暗中保留其他服务路径。
使用保存的 NAT ID 恢复原私有默认路由。不要删除预置 NAT、地址、应用或 S3 数据:
aws ec2 create-route \
--route-table-id "$PRIVATE_RT_ID" \
--destination-cidr-block 0.0.0.0/0 \
--nat-gateway-id "$NAT_ID"
读取恢复后的路由:
aws ec2 describe-route-tables \
--route-table-ids "$PRIVATE_RT_ID" \
--query 'RouteTables[].Routes' \
--output json
本地路由和活动 NAT 默认路由与初始状态一致。清单查询失败不能证明删除;认证后的查询必须成功,并确认端点不存在或为 deleted,且自动路由已删除。
再次点击 Read storage object,应通过 NAT 读取原始清单,Source address 为预置 NAT 公有地址。Request outbound service 应使用同一公有地址成功,Request private application from outside 仍失败。保留 VPC、子网、NAT、安全规则、S3 对象和参考网络。
运行本步骤的完成检查。
总结
你在私有应用路由表中创建了 S3 网关端点,实际读取存储时保留私有源地址。删除 NAT 默认路由后,S3 仍可访问,其他出站请求被阻断。错误的公有表关联导致私有 S3 访问失败,恢复私有关联即可修复,无需修改应用或安全规则。
你删除了端点、确认自动路由消失并恢复预置 NAT 基线。



