如何用CDK获取VPC终端节点关联ENI的IP及网络接口ID?
使用AWS CDK获取API Gateway VPCE关联IP的问题
背景与目标
我尝试用CDK创建目标组,包含API Gateway的VPC终端节点(VPCE)关联的IP地址。理想情况是只通过VPCE属于API Gateway服务的条件,或者直接用VPCE ID来查询关联的IP。
尝试的方法
- 用CDK的
InterfaceVpcEndpoint静态方法fromInterfaceVpcEndpointAttributes按服务过滤,返回了需要的VPCE,但返回的IInterfaceVpcEndpoint类型没有InterfaceVpcEndpoint构造的vpceNetworkInterfaceIds属性。 - 参考示例代码,用
AwsCustomResource查询指定VPCE网络接口ID对应的IP:
const vpceNetworkInterfaceIds = ['eniId1', 'eniId2']; const getEniIps = new AwsCustomResource(scope, `GetEndpointIps`, { onUpdate: { service: "EC2", action: "describeNetworkInterfaces", parameters: { NetworkInterfaceIds: vpceNetworkInterfaceIds }, physicalResourceId: PhysicalResourceId.of(Date.now().toString()) }, policy: AwsCustomResourcePolicy.fromSdkCalls({ resources: AwsCustomResourcePolicy.ANY_RESOURCE }), }); const privateIpAddresses: string[] = []; for(let i = 0; i< vpceNetworkInterfaceIds.length; i++){ const privateIpAddress: string = getNetworkInterfaceIpAddresses.getResponseField(`NetworkInterfaces.${i}.PrivateIpAddress`).toString(); privateIpAddresses.push(privateIpAddress); } return privateIpAddresses;
- 尝试用
describeVpcEndpointsSDK调用获取NetworkInterfaceIds数组,但遇到问题:
const getNetworkInterfaceIpAddresses = new AwsCustomResource(scope, `GetVpceNetworkInterfaceIds`, { onUpdate: { service: "EC2", action: "describeVpcEndpoints", parameters: { Filters: [ { Name: "service-name", Values: ["com.amazonaws.us-east-1.execute-api"] } ] }, physicalResourceId: PhysicalResourceId.of(Date.now().toString()) }, policy: AwsCustomResourcePolicy.fromSdkCalls({ resources: AwsCustomResourcePolicy.ANY_RESOURCE }), }); return getNetworkInterfaceIpAddresses.getResponseFieldReference(`VpcEndpoints.0.NetworkInterfaceIds`).toJSON();
试过Reference的toJson、toString等多种变体,还是无法从自定义资源中获取数组值。
问题
- 如何从AWS自定义资源的SDK调用中获取数组?
- 是否有更直接的方法获取指定VPCE的
vpceNetworkInterfaceIds? - 是否有更直接的方法获取指定VPCE的IP地址?
解决方案
1. 从AWS自定义资源中获取数组
CDK的AwsCustomResource返回的是CloudFormation动态引用,无法直接在代码中作为数组遍历,可通过以下方式处理:
- 用CloudFormation内置函数遍历:利用
Fn.select和Fn.length逐个提取数组元素,再单独查询每个ENI的IP:
const eniIdsRef = getNetworkInterfaceIpAddresses.getResponseFieldReference(`VpcEndpoints.0.NetworkInterfaceIds`); const eniCount = Fn.length(eniIdsRef); const privateIps = []; for (let i = 0; i < Fn.parseInt(eniCount.toString(), 10); i++) { const eniId = Fn.select(i, eniIdsRef); const getEniIp = new AwsCustomResource(scope, `GetEniIp-${i}`, { onUpdate: { service: "EC2", action: "describeNetworkInterfaces", parameters: { NetworkInterfaceIds: [eniId] }, physicalResourceId: PhysicalResourceId.of(Date.now().toString()) }, policy: AwsCustomResourcePolicy.fromSdkCalls({ resources: AwsCustomResourcePolicy.ANY_RESOURCE }) }); privateIps.push(getEniIp.getResponseField(`NetworkInterfaces.0.PrivateIpAddress`)); }
- 自定义Lambda函数处理:如果数组长度不固定,写一个Lambda函数一次性返回所有IP,再用
CustomResource调用该Lambda,直接获取数组结果。
2. 直接获取指定VPCE的vpceNetworkInterfaceIds
- 若VPCE是在当前CDK栈中创建的,直接使用
InterfaceVpcEndpoint实例的vpceNetworkInterfaceIds属性即可。 - 若引用现有VPCE:可在调用
fromInterfaceVpcEndpointAttributes时手动传入已知的vpceNetworkInterfaceIds;或用自定义Lambda调用describeVpcEndpoints提取ID数组,比纯CloudFormation函数更可靠。
3. 直接获取指定VPCE的IP地址
最直接的方式是用自定义Lambda完成"查询VPCE ENI ID→批量查询ENI IP"的全流程:
// 自定义Lambda函数示例 export async function handler(event: any) { const ec2 = new AWS.EC2(); const vpceId = event.vpceId; const vpceResp = await ec2.describeVpcEndpoints({ Filters: [{ Name: "vpc-endpoint-id", Values: [vpceId] }] }).promise(); const eniIds = vpceResp.VpcEndpoints[0].NetworkInterfaceIds; const eniResp = await ec2.describeNetworkInterfaces({ NetworkInterfaceIds: eniIds }).promise(); return eniResp.NetworkInterfaces.map(eni => eni.PrivateIpAddress); }
然后在CDK中调用这个Lambda:
const getVpceIps = new CustomResource(scope, 'GetVpceIps', { serviceToken: LambdaFunction.fromFunctionName(scope, 'GetVpceIpsLambda', 'your-lambda-name').functionArn, properties: { vpceId: 'your-vpce-id' } }); // 获取IP数组 const privateIps = getVpceIps.getAtt('Result');
内容的提问来源于stack exchange,提问作者Sarah Ganci
相关产品推荐
相关产品推荐

