AWS VPC Endpoint连接私有API Gateway超时问题求助
问题描述
采用「VPC Endpoint -> 私有API Gateway -> AWS Lambda」架构,向VPC Endpoint发起的GET请求https://{{api-gateway-id}}-{{vpc-endpoint-id}}.execute-api.us-east-1.amazonaws.com/prod/login始终超时,且私有API Gateway未接收到请求。
核心问题与修复方案
1. 子网CIDR冲突问题
当前VPC和子网使用相同的CIDR(10.0.0.0/16),会导致子网无法正常分配IP,接口型VPC端点也无法正确部署。需拆分VPC的CIDR为多个子网,且接口型端点推荐部署在多可用区以提升可用性:
# 替换原有VPCSubnet资源 VPCSubnet1: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.1.0/24 AvailabilityZone: !Select [0, !GetAZs ''] VPCSubnet2: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.2.0/24 AvailabilityZone: !Select [1, !GetAZs '']
同时更新VPC端点的子网配置:
APIGatewayVPCEndpoint: Type: AWS::EC2::VPCEndpoint Properties: # 保留其他属性 SubnetIds: - !Ref VPCSubnet1 - !Ref VPCSubnet2
2. API Gateway资源策略格式错误
资源策略中Resource字段格式不符合AWS规范,私有API Gateway的资源路径需使用execute-api:/*/*/*格式,同时优化策略逻辑(先拒绝非指定VPCE的请求,再允许合法请求):
APIGateway: Type: AWS::Serverless::Api Properties: # 保留其他属性 Auth: ResourcePolicy: CustomStatements: - Effect: Deny Principal: "*" Action: execute-api:Invoke Resource: - "execute-api:/*/*/*" Condition: StringNotEquals: aws:SourceVpce: !Ref APIGatewayVPCEndpoint - Effect: Allow Principal: "*" Action: execute-api:Invoke Resource: - "execute-api:/*/*/*"
3. 安全组入站规则优化
当前安全组允许任意IP的443端口访问,建议限制为VPC内部CIDR,避免不必要的外部访问:
APIGatewaySecurityGroup: Type: AWS::EC2::SecurityGroup Properties: VpcId: !Ref VPC GroupDescription: Allow HTTPS access from within the VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: 10.0.0.0/16
4. 验证DNS解析
由于开启了PrivateDnsEnabled: true,VPC内部实例应能通过私有域名解析到VPC端点。在VPC内的EC2实例上执行以下命令验证:
nslookup {{api-gateway-id}}-{{vpc-endpoint-id}}.execute-api.us-east-1.amazonaws.com
若解析结果为VPC内私有IP,则DNS配置正常;否则检查VPC的EnableDnsSupport和EnableDnsHostnames是否为true。
5. 确认API Gateway部署状态
确保API Gateway已部署到prod阶段,可通过SAM CLI重新部署验证:
sam deploy --guided
部署完成后,检查API Gateway阶段配置,确认关联的Lambda函数正确。
修复后的完整SAM模板示例
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > my-sam-template Resources: # API Gateway APIGateway: Type: AWS::Serverless::Api Properties: StageName: prod EndpointConfiguration: Type: PRIVATE VPCEndpointIds: - !Ref APIGatewayVPCEndpoint Auth: ResourcePolicy: CustomStatements: - Effect: Deny Principal: "*" Action: execute-api:Invoke Resource: - "execute-api:/*/*/*" Condition: StringNotEquals: aws:SourceVpce: !Ref APIGatewayVPCEndpoint - Effect: Allow Principal: "*" Action: execute-api:Invoke Resource: - "execute-api:/*/*/*" # VPC VPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: true EnableDnsHostnames: true VPCSubnet1: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.1.0/24 AvailabilityZone: !Select [0, !GetAZs ''] VPCSubnet2: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.2.0/24 AvailabilityZone: !Select [1, !GetAZs ''] APIGatewaySecurityGroup: Type: AWS::EC2::SecurityGroup Properties: VpcId: !Ref VPC GroupDescription: Allow HTTPS access from within the VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: 10.0.0.0/16 APIGatewayVPCEndpoint: Type: AWS::EC2::VPCEndpoint Properties: PrivateDnsEnabled: true SubnetIds: - !Ref VPCSubnet1 - !Ref VPCSubnet2 SecurityGroupIds: - !Ref APIGatewaySecurityGroup ServiceName: com.amazonaws.us-east-1.execute-api VpcId: !Ref VPC VpcEndpointType: Interface # Lambdas GetUsersLambda: Type: AWS::Serverless::Function Properties: CodeUri: lambdas/users_lambda Handler: main.lambda_handler Runtime: python3.9 Events: Login: Type: Api Properties: Path: /login Method: get RestApiId: !Ref APIGateway
验证步骤
- 重新部署SAM模板
- 在VPC内的EC2实例上发起请求:
curl https://{{api-gateway-id}}-{{vpc-endpoint-id}}.execute-api.us-east-1.amazonaws.com/prod/login
- 检查CloudWatch日志,确认Lambda函数是否收到请求并打印日志
内容的提问来源于stack exchange,提问作者oisin097

