使用 Terraform 从 VPC 中的 Lambda 访问 S3

Access S3 from Lambda within VPC using Terraform

我有一个 Lambda

resource "aws_lambda_function" "api" {
  function_name = "ApiController"

  timeout = 10

  s3_bucket = "mn-lambda"
  s3_key = "mn/v1.0.0/sketch-avatar-api-1.0.0-all.jar"

  handler = "io.micronaut.function.aws.proxy.MicronautLambdaHandler"
  runtime = "java11"

  memory_size = 1024

  role = aws_iam_role.api_lambda.arn

  vpc_config {
    security_group_ids = [aws_security_group.lambda.id]
    subnet_ids = [for subnet in aws_subnet.private: subnet.id]
  }
}

在 VPC 内

resource "aws_vpc" "vpc" {
  cidr_block = var.vpc_cidr_block
  enable_dns_support = true
  enable_dns_hostnames = true
}

我创建了一个 aws_vpc_endpoint 因为我读到这是我的 VPC 访问 S3 所需要的

resource "aws_vpc_endpoint" "s3" {
  vpc_id = aws_vpc.vpc.id
  service_name = "com.amazonaws.${var.region}.s3"
}

我创建并附加了允许访问 S3 的策略

resource "aws_iam_role_policy_attachment" "s3" {
  role = aws_iam_role.api_lambda.name
  policy_arn = aws_iam_policy.s3.arn
}

resource "aws_iam_policy" "s3" {
  policy = data.aws_iam_policy_document.s3.json
}

data "aws_iam_policy_document" "s3" {
  statement {
    effect = "Allow"
    resources = ["*"]

    actions = [
      "s3:*",
    ]
  }
}

可能值得注意的是,我尝试访问的存储桶是使用 aws cli 创建的,但位于同一区域。所以不使用 terraform。

问题是当我尝试从 S3 读取文件时我的 Lambda 超时。

可以找到完整的项目 here 如果有人想看一看。

您正在创建 com.amazonaws.${var.region}.s3,即 gateway VPC endpoint , which shouldn't be confused with interface VPC endpoints

两者的主要区别之一是网关类型需要与路由tables关联。因此,您应该使用 route_table_ids 将您的 S3 网关与子网的路由 table 相关联。

例如,使用默认主 VPC 路由 table:

resource "aws_vpc_endpoint" "s3" {
  vpc_id = aws_vpc.vpc.id
  service_name = "com.amazonaws.${var.region}.s3"

  route_table_ids = [aws_vpc.vpc.main_route_table_id]
}

或者,您也可以使用 aws_vpc_endpoint_route_table_association 来完成。