如何使用CDK连接负载均衡器和接口VPC端点?

0

【以下的问题经过翻译处理】 缩写解释:

  • ALB - 应用程序负载均衡器(Application Load Balancer)
  • ATG - 应用程序目标组,也称目标组(Application Target Group)
  • VPC - 虚拟私有云(Virtual Private Cloud)

我们的情况: 手动使用 AWS 控制台显示,使用 Route 53 到 ALB(应用程序负载均衡器)到私有接口 VPC 终端点到私有 REST API-Gateway 到私有 Lambda 可以很好地运行。(由于 HTTPS 和所需的证书,存在 ALB 和网关自定义域名)

ALB 需要一个目标组,该目标组针对接口 VPC 终端点的 IP 地址。(我们尝试使用 InstanceIdTarget 和终端点的 vpcEndpointId,但是出现错误“实例 ID 'vpce-WITHWHATEVERHERE' 无效”)

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

  • 应用程序负载均衡器(ALB)
  • 应用程序目标组(ATG)也称目标组

我们向 ALB 添加了侦听器。我们将目标组添加到了侦听器中。 不清楚如何从 VPC 终端点获取 IP 地址。我们希望使用目标属性将 IP 地址添加到 ATG aka 目标组中。

如何通过 CDK获取接口 VPC 终端点的 IP 地址?

我们使用过的一些资源示例:

https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_elasticloadbalancingv2-readme.html https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationLoadBalancer.html https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationTargetGroup.html https://stackoverflow.com/questions/57267594/how-to-get-privateipaddress-of-vpc-endpoint-in-cdk https://medium.com/codex/aws-private-api-gateway-with-custom-domain-names-350fee48b406 - The approach we want in general.

我们正在使用截至撰写本文时可用的最新版本(AWS CDK 2.5.0)

1 回答
0

【以下的回答经过翻译处理】 您需要使用自定义资源来调用API以获取端点网络接口的IP地址,因为CloudFormation不会将其公开作为返回值,这意味着CDK无法将其作为属性提供。

(请注意:此代码最初是为CDK ~1.40编写的,但仍应该能够工作或轻松更新。)

假设您像这样创建VPC端点:

    // 注意:创建两个端点,因为此VPC有两个私有子网
    const VPCEndpoints = new ec2.InterfaceVpcEndpoint(this, "APIEndpoint", {
      vpc: my_vpc,
      service: ec2.InterfaceVpcEndpointAwsService.APIGATEWAY,
      subnets: { subnetType: ec2.SubnetType.PRIVATE },
    });

然后,您可以创建一个自定义资源来调用其上的DescribeNetworkEndpoints API。这将是一个Lambda函数,CloudFormation将部署并调用它,函数的返回值将包含API响应。

CDK有一个辅助程序,可以轻松部署一个自定义资源,只需调用AWS API即可,因此我们可以使用它。 (CDK为我们编写一个小的nodeJS函数来执行此操作,这就是我在上面链接到JS SDK的原因。)

const eni = new custom_resources.AwsCustomResource(
      this,
      "DescribeNetworkInterfaces",
      {
        onCreate: {
          service: "EC2",
          action: "describeNetworkInterfaces",
          parameters: {
            NetworkInterfaceIds: VPCEndpoints.vpcEndpointNetworkInterfaceIds,
          },
          physicalResourceId: PhysicalResourceId.of(Date.now().toString()),
        },
        onUpdate: {
          service: "EC2",
          action: "describeNetworkInterfaces",
          parameters: {
            NetworkInterfaceIds: VPCEndpoints.vpcEndpointNetworkInterfaceIds,
          },
          physicalResourceId: PhysicalResourceId.of(Date.now().toString()),
        },
        policy: {
          statements: [
            new iam.PolicyStatement({
              actions: ["ec2:DescribeNetworkInterfaces"],
              resources: ["*"],
            }),
          ],
        },
      }
    );

我们现在可以在 eni 对象上使用 getResponseField () 方法从 API 调用中读取响应值,然后使用它们来创建 ALB 目标组。

 // note: two ENIs in our endpoint as above, so we can get two IPs out of the response
    const ip1 = eni.getResponseField("NetworkInterfaces.0.PrivateIpAddress");
    const ip2 = eni.getResponseField("NetworkInterfaces.1.PrivateIpAddress");

    const ALBTargetGroup = new elbv2.ApplicationTargetGroup(this, "ALBTG", {
      port: 443,
      targetType: elbv2.TargetType.IP,
      vpc: my_vpc,
    });

    ALBTargetGroup.addTarget(new elbv2_targets.IpTarget(ip1));
    ALBTargetGroup.addTarget(new elbv2_targets.IpTarget(ip2));

然后,目标组可以像往常一样在 ALB 监听器中使用。

profile picture
专家
已回答 2 年前

您未登录。 登录 发布回答。

一个好的回答可以清楚地解答问题和提供建设性反馈,并能促进提问者的职业发展。

回答问题的准则