使用 AWS CDK,如何将 AWS 负载均衡器和 AWS 接口 VPC 端点连接在一起

Using AWS CDK, How to connect an AWS Load balancer and an AWS Interface VPC Endpoint together

背景: 我们正在使用 AWS 云开发工具包 (CDK) 2.5.0。

手动使用 AWS 控制台和硬编码 IP 地址,路由 53 到 ALB(应用程序负载均衡器)到私有接口 VPC 端点到私有 REST API-网关(等等...... ) 有效。见下图。

代码: 我们正在尝试通过 CDK 编写此手动解决方案的代码,但仍停留在如何获取和使用 IP 地址或以某种方式将负载均衡器连接到接口 VPC 端点上。 (终结点有 3 个 IP 地址,该区域中每个可用区一个。)

ALB 需要一个以接口 VPC 端点的 IP 地址为目标的目标组。 (使用“实例”方法而不是 IP 地址,我们尝试将 InstanceIdTarget 与端点的 vpcEndpointId 一起使用,但失败了。我们收到错误 Instance ID 'vpce-WITHWHATEVERWASHERE' is not valid

使用 CDK,我们使用 aws_elasticloadbalancingv2 模块创建了以下内容(除其他外):

我们希望 aws_elasticloadbalancingv2_targetsaws_route53_targets 相似,但没有运气。我们知道 ApplicationTargetGrouptargets 属性 接受一个 IApplicationLoadBalancerTarget 对象的数组,但仅此而已。

  :
import { aws_ec2 as ec2 } from 'aws-cdk-lib';
  :
import { aws_elasticloadbalancingv2 as loadbalancing } from 'aws-cdk-lib';

// endpointSG, loadBalancerSG, vpc, ... are defined up higher
        const endpoint = new ec2.InterfaceVpcEndpoint(this, `ABCEndpoint`, {
            service: {
                name: `com.amazonaws.us-east-1.execute-api`,
                port: 443
            },
            vpc,
            securityGroups: [endpointSG],
            privateDnsEnabled: false,
            subnets: { subnetGroupName: "Private" }
        });


        const loadBalancer = new loadbalancing.ApplicationLoadBalancer(this, 'abc-${config.LEVEL}-load-balancer', {
            vpc: vpc,
            vpcSubnets: { subnetGroupName: "Private" },
            internetFacing: false,
            securityGroup: loadBalancerSG
        });

        const listenerCertificate = loadbalancing.ListenerCertificate.fromArn(config.ARNS.CERTIFICATE)
        const listener = loadBalancer.addListener('listener', {
            port: 443,
            certificates: [ listenerCertificate ]
        });

        let applicationTargetGroup = new loadbalancing.ApplicationTargetGroup(this, 'abc-${config.LEVEL}-target-group', {
            port: 443,
            vpc: vpc,
            // targets: [ HELP ], - how to get the IApplicationLoadBalancerTarget objects?  
        })
        listener.addTargetGroups( 'abc-listener-forward-to-target-groups', { 
            targetGroups: [applicationTargetGroup]
        } );

正如您在上面看到的,我们向 ALB 添加了一个侦听器。我们将目标组添加到侦听器。

我们使用的一些资源:

如果通过图像可视化设置有帮助,这里是我们想要的近似值。

任何帮助使用 IApplicationLoadBalancerTarget 对象填充 ApplicationTargetGrouptargets 属性 的帮助都将受到赞赏。谢谢!

https://aws.amazon.com/blogs/networking-and-content-delivery/accessing-an-aws-api-gateway-via-static-ip-addresses-provided-by-aws-global-accelerator/

此博客展示了如何使用 AWS 控制台配置问题中给出的架构(只需禁用全局加速器选项)。关键要点是应用程序负载均衡器使用目标类型 IP 并在步骤 2 中手动解析 VPC 端点域名。其他两个选项实例(目标是 EC2 实例)和 lambda(目标是 AWS Lambda 函数)不能用过。

ec2.InterfaceVpcEndpoint 构造没有直接给出 IP 地址的输出。底层 CloudFormation 资源也不支持它。相反,您将不得不使用 ec2.InterfaceVpcEndpointvpcEndpointDnsEntries 属性 并将域名解析为代码中的 IP 地址(控制台配置也需要相同的域名解析)。您可以使用 IpTarget object in your ApplicationTargetGroup.

此时,您将 运行 由于 CDK 在幕后的工作方式而遇到最后一个障碍。 如果您在一个 CDK 应用程序中定义了所有资源,则每个参数的值(或使用底层 CloudFormation 函数(如 Ref、GetAtt 等)对值的引用)需要在综合步骤之前可用,因为那是所有生成模板。 AWS CDK 为此目的使用 tokens,它在综合过程中解析为 {'Fn::GetAtt': ['EndpointResourceLogicalName', 'DnsEntries'] 等值。但是,由于我们需要 DNS 条目的实际值才能解析它,因此令牌值将无用。

解决此问题的一种方法是让两个完全独立的 CDK 应用程序以这种方式构建:

  • 具有 VPC 和接口端点的应用程序 A。使用 CfnOutput.
  • vpcEndpointDnsEntries 和 VPC-ID 定义为输出
  • 具有其余资源的应用程序 B。您将必须编写代码来读取应用程序 A 创建的 CloudFormation 堆栈的输出。您可以将 Fn.importValue 用于 VPC ID,但不能将其用于 DnsEntries 输出,因为它会再次解析为 Fn::ImportValue 基于令牌。您需要使用 AWS 开发工具包或其他一些选项来读取堆栈输出的实际值。一旦你有了域名,你就可以在你的 typescript 代码中解析它(我对 typescript 不是很熟悉,这可能需要第三方库)。

图片来源: