如何将 VPC 和安全组分配给 AWS CDK 中的 Lambda?

Posted

技术标签:

【中文标题】如何将 VPC 和安全组分配给 AWS CDK 中的 Lambda?【英文标题】:How do you assign a VPC and security group to a Lambda in AWS CDK? 【发布时间】:2020-06-28 19:10:40 【问题描述】:

我有一个带有 lambda 函数的 AWS CDK 堆栈,需要插入到 RDS 数据库中。 部署堆栈时,lambda函数无法访问数据库并报错:getaddrinfo ENOTFOUND [RDS endpoint as defined by me]。 手动添加RDS数据库所在的VPC、子网和安全组后,lambda函数正常工作。

您如何在 AWS CDK 中定义 VPC、子网和安全组,最好是在 TypeScript 中? 就文档而言,我尝试过:

const vpc = ec2.Vpc.fromLookup(this, "VPC",  vpcName: "myVPC" );

const securityGroup = ec2.SecurityGroup.fromSecurityGroupId(
  this,
  "SG",
  "sg-XXXXX"
);

const subnet1a = ec2.PrivateSubnet.fromSubnetAttributes(this, "SUBNET1A", 
  subnetId: "eu-central-1a"
);

const myLambda = new lambda.Function(this, "myLambda", 
  runtime: lambda.Runtime.NODEJS_12_X,
  code: lambda.Code.fromAsset("lambda"),
  handler: "myLambda.handler",
  description: "myLambda",
  environment: 
    DB_HOST: "XXXX",
    DB_USER: "XXXX",
    DB_PASSWORD: "XXXX",
    DB_NAME: "XXXX"
  ,
  vpc: vpc,
  vpcSubnets: [subnet1a],
  securityGroups: [securityGroup]
);

运行 cdk deploy 时,会出现 AWS CDK 错误:“无法将 Lambda 函数放置在公共子网中 子进程退出,错误 1"

欢迎任何帮助。

【问题讨论】:

【参考方案1】:

如果您想将 Lambda 函数部署到 VPC,则应将其部署到私有子网(具有 subnetType: SubnetType.PRIVATE 的子网)或隔离子网(具有 subnetType: SubnetType.ISOLATED 的子网)。

您选择哪一种取决于 Lambda 函数是否需要出站互联网访问。如果是,则使用 PRIVATE,否则使用 ISOLATED。

要访问同一 VPC 中的 RDS 实例,应将 Lambda 函数放置在安全组中,该安全组对 RDS 实例的安全组的相关端口号具有入站访问权限。

VPC here 和 Lambda here 的示例。

【讨论】:

跟进这个问题:可以将 lambda 放置在隔离子网中,而将公开此 lambda 的 Rest GatewayApi 放置在 PRIVATE 子网中吗? @Sammy 从 API Gateway 到您的 Lambda 函数的流量不会通过常规 VPC 网络到达您的 Lambda 函数。它由 API Gateway 传送到 Lambda 服务控制平面,然后由 Lambda 服务数据平面呈现给您的 Lambda 函数。 Lambda 函数可以位于任何类型的子网中 - 您所做的选择将影响其出站网络。这就是我对其工作原理的理解。 谢谢@jarmod,确实是的:即使我向我的 vpc 添加了 NAT 实例,我的 lambda 函数也无法访问 Internet(出站)。知道我应该如何为其提供出站互联网访问权限吗? Lambda 函数应位于私有子网中。私有子网的默认路由应该是公有子网(具有 IGW)中的 NAT 或 NAT 网关。 啊,问题可能是我把它放在了一个隔离子网而不是一个私有子网中。我会尝试切换。【参考方案2】:

您使用 vpc 配置 lambda 的代码很好。您的“subnet1a”是一个公共子网,建议不要在公共子网中定义任何后端服务。 AWS documentation for lambda and vpc configuration Another link for reference

为 lambda 选择私有或隔离子网。

【讨论】:

【参考方案3】:

这是一个简单的例子,希望对你有帮助:

//get VPC Info form AWS account, FYI we are not rebuilding we are referencing
const DefaultVpc = Vpc.fromVpcAttributes(this, 'vpcdev', 
    vpcId:'vpc-d0e0000b0',
    availabilityZones: core.Fn.getAzs(),
    privateSubnetIds: 'subnet-00a0de00',
    publicSubnetIds: 'subnet-00a0de00'
);

const YourService = new lambda.Function(this, 'LambdaName', 
    code: lambda.Code.fromAsset("lambda"),
    handler: 'handlers.your_handler',
    role: lambdaExecutionRole,
    securityGroup: lambdaSecurityGroup,
    vpc: DefaultVpc,
    runtime: lambda.Runtime.PYTHON_3_7,
    timeout: Duration.minutes(2),
);

【讨论】:

以上是关于如何将 VPC 和安全组分配给 AWS CDK 中的 Lambda?的主要内容,如果未能解决你的问题,请参考以下文章

AWS CDK 如何覆盖 Auto Scaling 组中的默认启动配置?

将 Lambda 函数分配给 serverless.yml 中的特定 VPC ID

将空元组分配给专用变量时的类型不兼容

是否可以将多个验证组分配给单个验证控件?

如何在 AWS CDK 中指定源安全组 ID?

AWS CloudFormation VPC CIDR 分配给安全组