跨区域S3访问未使用VPC接口端点的解决方法咨询
我在us-east-2区域的私有子网中部署了Lambda函数,需要从us-east-1区域的S3存储桶拉取数据。为避免NAT网关成本,我配置了VPC Interface端点,但流量仍通过NAT路由。我原本以为启用private_dns_enabled后,跨区域S3请求会自动解析到该端点而非走NAT。
以下是创建VPC端点的Terraform代码:
resource "aws_vpc_endpoint" "s3_global" { vpc_id = aws_vpc.main.id vpc_endpoint_type = "Interface" service_name = "com.amazonaws.s3-global.accesspoint" subnet_ids = aws_subnet.private.*.id private_dns_enabled = true }
S3客户端配置(Python):
client_config = botocore.config.Config( max_pool_connections=settings.threads, connect_timeout=5, read_timeout=10, s3={"us_east_1_regional_endpoint": "regional"}, ) s3_client = boto3.client( "s3", aws_access_key_id=settings.aws_access_key_id, aws_secret_access_key=settings.aws_secret_access_key region_name="us-east-1", config=client_config, )
1. 修正VPC端点的服务名称
你当前使用的s3-global.accesspoint端点仅适用于**S3访问点(Access Points)**的跨区域访问,无法直接用于访问普通S3桶。若要直接跨区域访问us-east-1的S3桶,需创建目标区域的S3 Interface端点:
resource "aws_vpc_endpoint" "s3_us_east_1" { vpc_id = aws_vpc.main.id vpc_endpoint_type = "Interface" # 替换为us-east-1区域的S3 Interface端点服务名 service_name = "com.amazonaws.us-east-1.s3" subnet_ids = aws_subnet.private.*.id private_dns_enabled = true # 绑定允许Lambda访问443端口的安全组 security_group_ids = [aws_security_group.lambda_s3_endpoint.id] }
注意:S3 Interface端点仅支持HTTPS访问,需确保Lambda的安全组允许出站到端点安全组的443端口,同时端点安全组允许来自Lambda安全组的443端口入站请求。
2. 调整客户端配置以匹配端点DNS规则
你的客户端配置中设置了us_east_1_regional_endpoint": "regional",这会让boto3使用区域端点域名s3.us-east-1.amazonaws.com,但s3-global.accesspoint端点的私有DNS仅对*.s3-global.amazonaws.com类域名生效,因此请求无法被解析到VPC端点。
若采用第一步的修改(使用us-east-1区域的S3 Interface端点),无需修改客户端的区域端点配置,但需修复原代码的语法错误:
client_config = botocore.config.Config( max_pool_connections=settings.threads, connect_timeout=5, read_timeout=10, s3={"us_east_1_regional_endpoint": "regional"}, ) s3_client = boto3.client( "s3", aws_access_key_id=settings.aws_access_key_id, aws_secret_access_key=settings.aws_secret_access_key, # 补充缺失的逗号 region_name="us-east-1", config=client_config, )
此时s3.us-east-1.amazonaws.com会被VPC端点的私有DNS解析为内网IP,流量直接走VPC内网。
3. 验证私有DNS生效状态
登录Lambda所在VPC的EC2实例(或通过Lambda网络日志)执行DNS解析测试:
nslookup s3.us-east-1.amazonaws.com
若返回结果是VPC内网IP(属于你的VPC CIDR范围),说明私有DNS配置生效;若返回公网IP,检查以下配置:
- VPC的
enableDnsSupport和enableDnsHostnames是否设为true - VPC端点的
private_dns_enabled是否为true - 是否存在Route 53私有域等规则覆盖了S3域名的解析
4. 确认路由表配置
私有子网的路由表无需额外添加指向VPC端点的路由,因为Interface端点的IP属于VPC内网地址,默认会在VPC内部转发流量。只需确保安全组规则正确即可。
内容的提问来源于stack exchange,提问作者James Stonehill

