AWS Lambda无法连接Amazon EFS?求Pulumi配置下的解决方案
问题描述
我尝试通过Access Point和挂载目标将Amazon EFS文件系统连接到AWS Lambda函数,对应的Pulumi代码如下:
export const lamdaExecutionRole = new aws.iam.Role("lamda-execution-role", {assumeRolePolicy: `{ "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Principal": { "Service": "lambda.amazonaws.com" }, "Effect": "Allow" } ] }`, name:'lamda-execution-role', managedPolicyArns: [ lamdaPolicy.arn, fileSystemPolicy.arn, vpcPolicy.arn, ] } ); export const lambdaFileSystem = new aws.efs.FileSystem("lamda-file-sysytem", {tags: { Name: "efs_for_lambda", }}) const vpc = new awsx.ec2.Vpc("vpc"); const subnetIds = vpc.publicSubnetIds; const lamdaSecurityGroup = new aws.ec2.SecurityGroup("lamda-security-group", { vpcId: vpc.vpcId, }) export const montTarget = new aws.efs.MountTarget("mount-target", { fileSystemId: lambdaFileSystem.id, subnetId: subnetIds[0], }) export const lamdaAccessPoint = new aws.efs.AccessPoint("lamda-access-point-scor", { fileSystemId: lambdaFileSystem.id, rootDirectory: { path: "/", creationInfo: { ownerGid: 1000, ownerUid: 1000, permissions: "777", }, }, posixUser: { gid: 1000, uid: 1000, }, }) export const lamda = new aws.lambda.Function("aws-lamda-function", { code: new pulumi.asset.FileArchive("../app/build/libs/HelloWorldServerless-all.jar"), runtime: aws.lambda.Runtime.Java11, handler: "HelloWorldServerless.HelloWorld::handler", role: lamdaExecutionRole.arn, name: "hello-world", memorySize: 300, timeout: 100, fileSystemConfig: {arn: lamdaAccessPoint.arn, localMountPath :"/mnt/efs"}, vpcConfig: { subnetIds: [subnetIds[0]], securityGroupIds: [lamdaSecurityGroup.id], }, layers: [ 'arn:aws:lambda:eu-north-1:464622532012:layer:dd-trace-java:8', "arn:aws:lambda:eu-north-1:464622532012:layer:Datadog-Extension:38"], environment: { variables: { DD_API_KEY:"*******", DD_CAPTURE_LAMBDA_PAYLOAD: "false", DD_LAMBDA_HANDLER: "HelloWorldServerless.HelloWorld::handler", DD_LOG_LEVEL: "info", FUNCTION_NAME: "hello-world", DD_SERVICE: 'hello-world', DD_SITE: "datadoghq.eu", DD_VERSION: "0.1", DD_LOGS_INJECTION: 'true', DD_JMXFETCH_ENABLED: 'false', DD_TRACE_ENABLED: 'true', DD_ENV: 'dev', DD_MERGE_XRAY_TRACES: "false", DD_FLUSH_TO_LOG: "true" }, }, }, { dependsOn:montTarget} )
运行以下测试代码时:
import { LambdaClient, InvokeCommand } from "@aws-sdk/client-lambda"; // ES Modules import it("should be Hello World ", async () => { const client = new LambdaClient({region:"eu-north-1"}); const inputPayload = {"body": "{ \"message\": \"Hello from Lambda!\" }"} const command = new InvokeCommand({FunctionName:"hello-world" ,Payload:JSON.stringify(inputPayload)}); const response = await client.send(command); expect(response.StatusCode).toBe(200) const payLoad = String.fromCharCode.apply(null, response.Payload) expect(payLoad).toBe("{\"isBase64Encoded\":false,\"statusCode\":200,\"body\":\"{\\\"message\\\":\\\"HELLO FROM LAMBDA!\\\"}\"}") })
出现错误:EFSMountConnectivityException:函数无法连接ARN为arn:aws:elasticfilesystem:eu-north-1:888219289265:access-point/fsap-05aead28f4e33f496的Amazon EFS文件系统。请检查网络配置并重试。
修复方案
以下是需要调整的几个关键配置点:
1. 配置安全组入站规则,允许Lambda访问EFS
当前Lambda安全组没有任何入站/出站规则,EFS挂载目标也缺少允许NFS流量的安全组配置,这是连接失败的核心原因。
修改代码:
// Lambda安全组:添加出站规则允许NFS流量(端口2049) const lamdaSecurityGroup = new aws.ec2.SecurityGroup("lamda-security-group", { vpcId: vpc.vpcId, egress: [ { fromPort: 2049, toPort: 2049, protocol: "tcp", cidrBlocks: [vpc.vpcCidrBlock], // 限制到VPC内部,更安全 }, // 保留Lambda访问外部服务的出站规则(比如Datadog) { fromPort: 0, toPort: 0, protocol: "-1", cidrBlocks: ["0.0.0.0/0"], } ], }); // EFS挂载目标专用安全组:允许来自Lambda安全组的NFS流量 const efsMountTargetSg = new aws.ec2.SecurityGroup("efs-mount-target-sg", { vpcId: vpc.vpcId, ingress: [ { fromPort: 2049, toPort: 2049, protocol: "tcp", securityGroups: [lamdaSecurityGroup.id], }, ], egress: [ { fromPort: 0, toPort: 0, protocol: "-1", cidrBlocks: ["0.0.0.0/0"], }, ], }); // 更新挂载目标,关联EFS专用安全组 export const montTarget = new aws.efs.MountTarget("mount-target", { fileSystemId: lambdaFileSystem.id, subnetId: subnetIds[0], securityGroups: [efsMountTargetSg.id], });
2. 使用私有子网而非公有子网
Lambda连接EFS时,推荐使用私有子网(公有子网依赖互联网网关,不符合EFS的安全访问最佳实践),修改子网获取逻辑:
// 替换publicSubnetIds为privateSubnetIds const subnetIds = vpc.privateSubnetIds;
awsx创建的VPC默认会为私有子网配置NAT网关,不影响Lambda访问外部服务。
3. 验证EFS文件系统权限
确保fileSystemPolicy包含允许Lambda角色访问EFS的权限,示例策略如下:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "${lamdaExecutionRole.arn}" }, "Action": [ "elasticfilesystem:ClientMount", "elasticfilesystem:ClientWrite" ], "Resource": "${lambdaFileSystem.arn}/*" } ] }
4. 完善资源依赖顺序
当前Lambda仅依赖挂载目标,建议同时依赖Access Point,确保所有EFS相关资源就绪后再创建Lambda:
export const lamda = new aws.lambda.Function("aws-lamda-function", { // ... 原有配置 }, { dependsOn: [montTarget, lamdaAccessPoint] });
5. 确认VPC DNS配置
检查VPC是否启用了DNS支持(awsx创建的VPC默认启用),否则Lambda无法解析EFS挂载目标的DNS名称。
内容的提问来源于stack exchange,提问作者stein korsveien
相关产品推荐
相关产品推荐

