You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Terraform的for_each动态创建Lambda函数及Docker容器?

问题解决:Terraform动态创建Lambda函数报错处理

问题原因

  1. 多余的空Lambda模块:你在main.tf里声明了一个完全未配置参数的module "lambda",这个模块会默认生成IAM角色和策略,但因为没指定合理的命名参数,导致名称不符合AWS IAM的命名规则(仅允许[\w+=,.@-]这类字符),直接触发报错。
  2. 无效打包流程触发:这个空模块还会默认执行代码打包逻辑,但根本没设置source_path,所以出现Could not locate source_path "null"的错误。
  3. 硬编码AWS账号ID和区域的做法不够灵活,容易因环境变化出错。

修复步骤

1. 删除多余的空Lambda模块

打开main.tf,删掉这段无意义的代码:

module "lambda" {
  source  = "terraform-aws-modules/lambda/aws"
  version = "6.0.0"
}

这是触发大部分报错的核心原因。

2. 用数据源替换硬编码的AWS账号和区域

在main.tf里添加两个数据源,自动获取当前账号ID和区域:

data "aws_caller_identity" "current" {}
data "aws_region" "current" {}

然后更新docker provider的地址:

provider "docker" {
  registry_auth {
    address  = "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com"
    username = data.aws_ecr_authorization_token.token.user_name
    password = data.aws_ecr_authorization_token.token.password
  }
}

同时修改lambda_build.tf里的image_uri:

image_uri = "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/${each.value}:${var.commit_sha}"

这样就不用手动维护账号ID和区域了。

3. 确保函数名符合IAM命名规则

如果你的函数名(比如function1这类)本身包含特殊字符,需要先过滤处理,在lambda_function模块里修改角色和策略名称:

role_name = "${regexreplace(each.value, "[^\\w+=,.@-]", "")}_role"
policy_name = "${regexreplace(each.value, "[^\\w+=,.@-]", "")}_policy"

如果函数名本身都是合法字符,这一步可以跳过。

4. 验证输入变量的有效性

确保GitHub Actions传递的directories变量格式正确(比如function1,function2,function3),且没有空值。local.lambda_dirs的过滤逻辑已经处理了空项,这部分没问题。

修改后的完整代码

main.tf

terraform {
  required_version = ">= 0.15"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 4.63"
    }
    docker = {
      source  = "kreuzwerker/docker"
      version = ">= 3.0"
    }
  }
  backend "s3" {
    encrypt        = true
    bucket         = "my-bucket-for-tfstate"
    key            = "terraform.tfstate"
    region         = "REGION"
  }
}

provider "aws" {
  region = "us-east-1"
}

data "aws_ecr_authorization_token" "token" {}
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}

provider "docker" {
  registry_auth {
    address  = "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com"
    username = data.aws_ecr_authorization_token.token.user_name
    password = data.aws_ecr_authorization_token.token.password
  }
}

locals {
  lambda_dirs = [for item in split(",", var.directories) : item if length(item) > 0]
}

lambda_build.tf

module "docker_build" {
  source = "terraform-aws-modules/lambda/aws//modules/docker-build"

  for_each         = toset(local.lambda_dirs)
  create_ecr_repo  = true
  ecr_repo         = each.value
  image_tag        = var.commit_sha
  source_path      = "${path.module}/../functions/${each.value}/"
  docker_file_path = "${path.module}/../functions/${each.value}/Dockerfile"
}

module "lambda_function" {
  source        = "terraform-aws-modules/lambda/aws"
  for_each      = toset(local.lambda_dirs)

  function_name = each.value
  description   = "Lambda function for ${each.value}"
  image_uri     = "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/${each.value}:${var.commit_sha}"
  package_type  = "Image"
  memory_size   = 10000
  timeout       = 900
  role_name     = "${each.value}_role"
  policy_name   = "${each.value}_policy"
  depends_on    = [module.docker_build]
}

内容的提问来源于stack exchange,提问作者Steven Burgess

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 08:37:49