无需Lambda提取CloudFormation中VPC端点IP的方案咨询
CloudFormation中提取VPC端点IP:无需Lambda或创建后自动删除Lambda的方案
问题背景
我在编写AWS CloudFormation模板搭建S3静态网站基础设施,需要创建Interface类型VPC端点和负载均衡器。配置目标组时,必须把VPC端点在对应子网的IP填入Targets属性,但VPC端点创建后只能获取到NetworkInterfaceIds属性,无法直接拿到IP。不想只为提取IP单独创建Lambda,想搞清楚两个问题:
- 有没有不用Lambda就能提取VPC端点IP的方法?
- 如果必须用Lambda,能不能在基础设施搭建完成后自动删除它?
一、无需Lambda提取IP的方案
可以通过CloudFormation的资源引用直接获取VPC端点对应网络接口的IP,不需要额外Lambda。
Interface类型的VPC端点会在你指定的每个子网中自动创建一个网络接口,NetworkInterfaceIds列表的顺序和SubnetIds中填写的子网顺序完全一致。我们可以通过引用这些自动生成的网络接口资源,直接获取对应的私网IP:
具体实现步骤
- 为每个子网对应的网络接口创建
AWS::EC2::NetworkInterface类型资源,引用VPC端点返回的NetworkInterfaceIds中的对应ID; - 在目标组的
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:嵌套栈+自定义资源清理
- 将Lambda函数和用于提取IP的自定义资源放在一个嵌套栈中;
- 主栈引用嵌套栈输出的IP地址来配置目标组;
- 主栈创建完成后,手动或通过一个轻量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
相关产品推荐
相关产品推荐

