AWS 的 gateway endpoint 和 interface endpoint 怎么选
目录
默认那条路:出 VPC 走 IGW 或 NAT#
私有子网里的实例访问 AWS 服务,默认只有一条路:0.0.0.0/0 指向 NAT Gateway,出 VPC。AWS 的文档里,服务的默认 endpoint 是公网接口:
The default service endpoints are public interfaces, so you must add an internet gateway to your VPC so that traffic can get from the VPC to the AWS service.
域名形态是 https://<service_code>.<region_code>.amazonaws.com,解析出来是公网 IP,于是公有子网这条路直接指向 IGW,私有子网中间要多一跳 NAT。这里有个词容易读错:包确实离开了你的 VPC,但并没有离开 AWS 的网络,IGW 这个名字里带 internet,它不等于出了 AWS 内网。按 GB 收的那笔钱出在 NAT 上,公有子网直连 IGW 没有这笔。
这笔的单价和计费口径在 NAT Gateway 那篇里按东京区算过:目的地在同一个可用区还是地球另一端单价一样,所以私有子网里拉一个 S3 大对象也要按 GB 付钱。安全这一侧,服务看到的仍是实例的公网出口地址,你能控制的只有出站规则。
VPC endpoint 把这条路的出口收进 VPC 边界:AWS 在你 VPC 里放一个私有访问点,到指定服务的流量在那里终结,不再经过 NAT。省掉 NAT 的费用只是结果之一。另外三件事跟着来:不再依赖公网出口,服务侧看到的是你的私有地址,而且 endpoint 本身能挂一层策略,控制点从实例侧挪到了出口这一侧。AWS 提供这个私有访问点的方式有两种,而且不是每个服务都给你选。
两种形态从一条命令里就能看见#
aws ec2 describe-vpc-endpoint-services 会把一个区里能建 endpoint 的服务名都列出来,每条带一个 ServiceType。CLI 文档里这个字段的取值只有三个,Interface、Gateway 和 GatewayLoadBalancer,它同时也能当过滤条件用:
aws ec2 describe-vpc-endpoint-services --region ap-northeast-1 \
--filters Name=service-type,Values=Gateway \
--query 'ServiceDetails[].ServiceName' --output text
这条命令能在自己的区里核一遍,能过滤出 Gateway 的服务只有 S3 和 DynamoDB 两个。gateway endpoint 文档开篇把范围限定在这两个服务上,同时交代了它和 PrivateLink 的关系:
Gateway VPC endpoints provide reliable connectivity to Amazon S3 and DynamoDB without requiring an internet gateway or a NAT device for your VPC. Gateway endpoints do not use AWS PrivateLink, unlike other types of VPC endpoints.
PrivateLink 是 AWS 的一套私有访问机制:服务那边发布一个可连接的端点,消费者在自己的 VPC 里连过去,两边不共享路由、不经过公网。AWS 服务这一侧走的就是这条路,同一篇文档的说法是连过去之后像服务就在你 VPC 里:
you can use AWS PrivateLink to connect your VPC to AWS services as if they were in your VPC, without the use of an internet gateway
第三方 SaaS 走的是同一套机制的另一端,由 provider 发一个 endpoint service,最后一节讲这条路。gateway endpoint 不在 PrivateLink 里,它没有 ENI,靠的是路由表。
价格那一半留给 NAT Gateway 那篇:gateway endpoint 不收钱,interface endpoint 有小时费和每 GB 费,月流量到 600 GB 上下才开始省。这篇整理的是价格之外那几条分界,它们通常在算钱之前就把选择定死了。
gateway endpoint 是路由表里的一条 prefix list 记录#
名字叫 gateway,它不是网关设备:建完以后 VPC 的拓扑没变,多出来的只有路由表里那条记录,既没有新组件,也没有新地址可以连。interface endpoint 那边相反,它会给你一张网卡、一个可以连的私有 IP,后面那些差别都从这一条来。
建 gateway endpoint 的时候要选路由表,AWS 会往每一张选中的表里自动写一条路由,destination 是这个服务的 AWS 托管 prefix list,target 是 endpoint 本身。这条记录在控制台里看得见,改不了也删不掉:解除路由表关联或者删掉 endpoint 时它自己消失。
生效范围是路由表,不是实例。文档里的说法是:
All instances in the subnets associated with a route table associated with a gateway endpoint automatically use the gateway endpoint to access the service. Instances in subnets that aren’t associated with these route tables use the public service endpoint, not the gateway endpoint.
所以漏勾一张表,挂在它下面的子网就照旧走 NAT,而且没有任何报错。同一张路由表里,同一个服务只能有一条 endpoint 路由,但同一个服务的 endpoint 路由可以出现在多张表里。
这条路由不改包的目的地址:发出去时目的地仍然是 S3 或 DynamoDB 的公网 IP,gateway endpoint 改的只是这个包往哪条路走。安全组因此仍然要放行,出站规则可以直接引用 prefix list 的 id;network ACL 引用不了 prefix list,只能把 prefix list 里的 CIDR 抄进规则。
prefix list 按区划分,跨区的流量因此命不中那条路由:
Traffic that’s destined for the service (Amazon S3 or DynamoDB) in a different Region goes to the internet gateway because prefix lists are specific to a Region
发往东京区 S3 的包命中那条 endpoint 路由,发往首尔区同一个服务的包不命中,落回 0.0.0.0/0,也就是回到 NAT 或者 IGW,每 GB 那笔钱照收。
interface endpoint 是子网里的一张 ENI 加一条私有 DNS 记录#
interface endpoint 里的 interface 是 network interface 的那个 interface。它在 VPC 边界上放出一张真网卡,从子网地址段里分一个私有 IP,请求先打到这张网卡,再由 PrivateLink 的背向连接送到服务那侧。每个 endpoint 在指定的每个子网里建一张这种网卡。这张网卡是 requester-managed 的,账号里看得见但改不了,IP 在 endpoint 的生命周期内不变。一个可用区只能选一个子网。
安全组挂在这张 ENI 上,这是两种 endpoint 在访问控制上最容易看出来的差别。gateway endpoint 那边你能收紧的是实例侧的安全组、network ACL 和 endpoint policy,interface endpoint 这边多一层,可以按来源安全组限制 VPC 里谁能用这个 endpoint。endpoint policy 两种 endpoint 都能挂,不过不是每个服务都支持,不支持的那些 AWS 一律放行。它是挂在 endpoint 上的资源策略,不替代 IAM 身份策略,也不替代桶策略那类资源策略;不挂就用默认那份全开的,上限 20480 字符,改完要过几分钟才生效。
打开 private DNS 之后,AWS 建一个隐藏的托管 private hosted zone,把服务原本的公网区域域名解析成这些 ENI 的私有 IP,应用侧不用动代码。铺了多个 AZ 时,走公网域名的请求会在几张健康 ENI 之间 round robin;想固定打到同 AZ 那张,用 endpoint 的 zonal 域名或者直接用 IP。
方向也是固定的:
AWS services accept connection requests automatically. The service can’t initiate requests to resources through the VPC endpoint.
配额上,interface endpoint 和 Gateway Load Balancer endpoint 合起来每个 VPC 默认 50 个(可调),gateway endpoint 是每区 20 个、每 VPC 最多 255 个。
两套机制各管一层:gateway endpoint 由路由表决定,interface endpoint 在 DNS 解析那一步就分了岔。下面这张图是全文分界的落点,选型那三道判断都从这里派生。
连服务的区域域名"] APP --> DNS["Route 53 Resolver"] DNS -- "只有 gateway endpoint
解析出服务的公网 IP" --> RT{"子网路由表
最长前缀匹配"} DNS -- "有 interface endpoint 且开了 private DNS
解析出 ENI 的私有 IP" --> ENI["endpoint ENI
安全组挂在这一层"] RT -- "命中本区 prefix list" --> GW["gateway endpoint"] RT -- "跨区,或没勾这张路由表
落到 0.0.0.0/0" --> NAT["NAT Gateway 或 IGW"] ENI --> SVC[("AWS 服务")] GW --> SVC NAT --> SVC
服务清单、请求来源、DNS 名字#
选型上有三道判断,每一道都能单独把结果定死。先后顺序是:服务本身有没有得选,请求从哪儿发起,客户端连的名字要不要改。
只有 S3 和 DynamoDB 两种都能建#
AWS 有一份 PrivateLink 集成服务清单,2026-09-14 抓下来数了一遍:
curl -s https://docs.aws.amazon.com/vpc/latest/privatelink/aws-services-privatelink-support.md \
| grep '^- \*\*' | grep -vc 'com\.amazonaws\|aws\.api\.'
235
清单上 235 个服务,Service name 那列给的就是建 interface endpoint 时要填的名字,少数几个由服务自己托管 endpoint。能建 gateway endpoint 的仍然只有 S3 和 DynamoDB 两个。
所以「选哪种」这个问题只在这两个服务上成立。Secrets Manager、SSM、ECR API、Kinesis Data Streams 这些要走私有路径就只有 interface endpoint 一条路,回本点算不过来也只能在「建」和「继续走 NAT」之间选。
请求从 VPC 外面发起时 gateway endpoint 接不住#
S3 和 DynamoDB 的文档里各有一张同构的对比表,措辞几乎一样,最后一行才是价格(Not billed 对 Billed)。前面两行直接给了结论:gateway endpoint 那列写着 Do not allow access from on premises 和 Do not allow access from another AWS Region,interface endpoint 那列两条都是 allow。
机制上两层都走不通:gateway endpoint 是一条路由,只对关联了这张路由表的子网有效,从 Direct Connect 或者 Site-to-Site VPN 进来的包不经过你 VPC 的子网路由表;再加上 prefix list 只含本区,跨区那条同样落空。peering 那边 AWS 把这类限制归在 edge to edge routing 底下,VPC peering 文档的说法是:
If VPC A has a gateway endpoint that provides connectivity to Amazon S3 to private subnets in VPC A, resources in VPC B can’t use the gateway endpoint to access Amazon S3.
interface endpoint 给出的是你 VPC 里的私有 IP,本地机房走 DX 或 VPN、别的区走 peering 或 Transit Gateway,都能连到这个地址。
这一条还有例外:cross-region interface endpoint,创建时勾上 Enable cross Region endpoint 再选服务所在的区。支持它的服务另有一份清单,截至 2026-09-14 上面是 9 个,动手之前去那页确认自己要的服务在不在。
从 gateway 换到 interface,客户端连的名字可能要跟着改#
S3 和 DynamoDB 都支持两种 endpoint,在 DNS 这一处的行为却差得很远。DynamoDB 的 PrivateLink 页把 private DNS 明确列进了不支持的清单,还专门警告不要自己建 private hosted zone 去盖:
Do not create private hosted zones to override DynamoDB endpoint DNS names (such as
dynamodb.region.amazonaws.comor*.region.amazonaws.com) to route traffic to your interface endpoints. DynamoDB DNS configurations might change over time.
DynamoDB 从 gateway endpoint 换到 interface endpoint,客户端就得改成 https://vpce-xxxx.dynamodb.<region>.vpce.amazonaws.com 这种 endpoint 专属 URL,SDK 那层要动配置。
S3 支持 private DNS,但默认值本身带着一个前提。CLI 里那个 PrivateDnsOnlyForInboundResolverEndpoint 参数不给就是 true,而它要求 VPC 里已经有一个 S3 gateway endpoint,没有的话建 endpoint 这一步直接报错:
To set PrivateDnsOnlyForInboundResolverEndpoint to true, the VPC vpce_id must have a gateway endpoint for the service.
这个默认值等于 AWS 自己给的分工建议:VPC 里的 S3 请求继续走免费的 gateway endpoint,本地机房经 inbound Resolver endpoint 进来的请求走 interface endpoint。两种共存不冲突,文档原话是 Interface endpoints are compatible with gateway endpoints。要让所有 S3 请求都走 interface endpoint,把这个参数显式设成 false。
第三方 SaaS 只能给 interface endpoint#
第三方账号里的服务想让你私有访问,它只有一种做法:建一个 endpoint service。AWS 的文档写着这件事的硬性前提。
Endpoint services require either a Network Load Balancer or a Gateway Load Balancer.
然后由你这个消费者在自己 VPC 里建 interface endpoint 连过去,和前面访问 AWS 服务用的是同一个机制,只是这一回提供服务的是第三方账号。gateway endpoint 没有对应的提供方形态,S3 和 DynamoDB 那两条 prefix list 是 AWS 自己维护的,第三方拿不到这条路。方向仍然是单向的,请求只能从你的 VPC 发起。
Confluent Cloud 和 MongoDB Atlas 都是这个模型,两边都限档位。Confluent 的 AWS PrivateLink 文档里写的是 AWS PrivateLink allows for one-way secure connection access from your VPC to Confluent Cloud,适用范围限定在 Dedicated 集群,Enterprise 集群走另一套 serverless 的文档;它给出的步骤里,第三步是在 AWS 里建 endpoint,第四步是在 AWS 里配 DNS 记录,这段 DNS 是消费者侧的活。MongoDB Atlas 的 private endpoint 文档同样限定在 dedicated 集群,Free 和 Flex 明确不支持。
NAT Gateway 那篇里查过的那个账号,SaaS 这条路就还停在公网域名上:peering 建好了,走的只是按私有 IP 直连的那部分调用。
小结#
- 「选哪种」只在 S3 和 DynamoDB 上是真问题。清单上另外 233 个服务底下没有 gateway endpoint 这个选项,讨论到价格之前就定了。
- S3 和 DynamoDB 上先建 gateway endpoint。它不要钱,不占子网 IP,也不吃 interface endpoint 那 50 个的配额,代价是只对勾中的路由表生效、只覆盖本区。
- 需要本地机房或者跨区访问时再叠 interface endpoint,两种可以共存。S3 那个
PrivateDnsOnlyForInboundResolverEndpoint的默认值就是这个分工。 - 换 interface endpoint 之前先确认客户端连的名字。DynamoDB 必须改成 endpoint 专属 URL,S3 可以靠 private DNS 不动应用。
- 第三方 SaaS 那边你能建的只有 interface endpoint,DNS 一般要自己配,能不能用还取决于对方的集群档位。