You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需Lambda提取CloudFormation中VPC端点IP的方案咨询

CloudFormation中提取VPC端点IP:无需Lambda或创建后自动删除Lambda的方案

问题背景

我在编写AWS CloudFormation模板搭建S3静态网站基础设施,需要创建Interface类型VPC端点和负载均衡器。配置目标组时,必须把VPC端点在对应子网的IP填入Targets属性,但VPC端点创建后只能获取到NetworkInterfaceIds属性,无法直接拿到IP。不想只为提取IP单独创建Lambda,想搞清楚两个问题:

  1. 有没有不用Lambda就能提取VPC端点IP的方法?
  2. 如果必须用Lambda,能不能在基础设施搭建完成后自动删除它?

一、无需Lambda提取IP的方案

可以通过CloudFormation的资源引用直接获取VPC端点对应网络接口的IP,不需要额外Lambda。

Interface类型的VPC端点会在你指定的每个子网中自动创建一个网络接口,NetworkInterfaceIds列表的顺序和SubnetIds中填写的子网顺序完全一致。我们可以通过引用这些自动生成的网络接口资源,直接获取对应的私网IP:

具体实现步骤

  1. 为每个子网对应的网络接口创建AWS::EC2::NetworkInterface类型资源,引用VPC端点返回的NetworkInterfaceIds中的对应ID;
  2. 在目标组的Targets属性中,通过!GetAtt获取这些网络接口的私网IP。

修改后的模板示例

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  StaticWebSitesVpcEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcEndpointType: Interface
      ServiceName: com.amazonaws.eu-central-1.s3
      VpcId: !Ref VPC
      SubnetIds:
        - !Ref Subnet1  # 第一个子网ID
        - !Ref Subnet2  # 第二个子网ID
      SecurityGroupIds:
        - !Ref VpcEndpointSG

  # 引用VPC端点在第一个子网生成的网络接口
  StaticWebSitesVpcEndpointNI1:
    Type: AWS::EC2::NetworkInterface
    Properties:
      NetworkInterfaceId: !Select [0, !GetAtt StaticWebSitesVpcEndpoint.NetworkInterfaceIds]

  # 引用VPC端点在第二个子网生成的网络接口
  StaticWebSitesVpcEndpointNI2:
    Type: AWS::EC2::NetworkInterface
    Properties:
      NetworkInterfaceId: !Select [1, !GetAtt StaticWebSitesVpcEndpoint.NetworkInterfaceIds]

  StaticWebSitesTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      TargetType: ip
      Targets:
        - Id: !GetAtt StaticWebSitesVpcEndpointNI1.PrivateIpAddress  # 第一个子网的VPC端点IP
        - Id: !GetAtt StaticWebSitesVpcEndpointNI2.PrivateIpAddress  # 第二个子网的VPC端点IP
      Protocol: HTTP
      Port: 80
      ProtocolVersion: HTTP1
      Matcher:
        HttpCode: 200,307,405
      VpcId: !Ref VPC

Parameters:
  VPC:
    Type: AWS::EC2::VPC::Id
  Subnet1:
    Type: AWS::EC2::Subnet::Id
  Subnet2:
    Type: AWS::EC2::Subnet::Id
  VpcEndpointSG:
    Type: AWS::EC2::SecurityGroup::Id

注意事项

  • 目前AWS会保证NetworkInterfaceIds的顺序和SubnetIds完全匹配,但需要关注后续是否有行为变更;
  • 该方法适用于子网数量固定的场景,如果子网数量动态变化,还是需要用Lambda遍历处理。

二、使用Lambda后自动删除的方案

如果是子网数量动态变化的场景,必须用Lambda的话,可以通过以下两种方式自动删除Lambda:

方法1:嵌套栈+自定义资源清理

  1. 将Lambda函数和用于提取IP的自定义资源放在一个嵌套栈中;
  2. 主栈引用嵌套栈输出的IP地址来配置目标组;
  3. 主栈创建完成后,手动或通过一个轻量Lambda触发删除嵌套栈,嵌套栈内的Lambda会被一并删除。

方法2:Lambda自删除

在Lambda函数代码中,完成IP提取并返回给CloudFormation后,调用AWS SDK的DeleteFunction API删除自身。需要给Lambda添加lambda:DeleteFunction的IAM权限。

示例Lambda代码片段(Python):

import boto3
import cfnresponse

def lambda_handler(event, context):
    # 提取VPC端点IP的业务逻辑
    ec2 = boto3.client('ec2')
    response = ec2.describe_network_interfaces(
        NetworkInterfaceIds=event['ResourceProperties']['NetworkInterfaceIds']
    )
    ip_addresses = [ni['PrivateIpAddress'] for ni in response['NetworkInterfaces']]
    
    # 返回结果给CloudFormation
    cfnresponse.send(event, context, cfnresponse.SUCCESS, {'IpAddresses': ip_addresses})
    
    # 删除自身函数
    lambda_client = boto3.client('lambda')
    lambda_client.delete_function(FunctionName=context.function_name)

注意事项

  • 自删除的Lambda在栈更新或删除时可能会引发资源依赖问题,建议仅用于一次性创建的场景;
  • 嵌套栈的方式更稳定,适合需要重复部署的模板。

内容的提问来源于stack exchange,提问作者Karel Krýda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 03:55:00