使用 Terraform Module 创建资源,其中一些资源由模块共享

Create resources using Terraform Module with some resources shared by the modules

我有 App1、App2、App3 等。要重用代码,我想使用 Terraform 模块创建它们。

模块调用的公共基础设施是: root\Common_infra\main.tf:

resource "aws_lambda_function" "app" {
     # count = “${var.should_launch}”
     function_name = "app"
     …
}
resource "aws_cloudwatch_event_rule" "app" {
  name                = " ${var.app_name } "
  schedule_expression = "${var.app_schedule}"
}
resource "aws_cloudwatch_event_target" "app_target" {
  rule      = "${aws_cloudwatch_event_rule.app.name}"
  arn       = "${aws_lambda_function.app.arn}"
  input = <<EOF
{
  "app_name": "${var.app_name}"
}
EOF
}
resource "aws_lambda_permission" "allow_cloudwatch_to_call_lambda"   {
  action        = "lambda:InvokeFunction"
  function_name =     "${aws_lambda_function.app.function_name}"
  principal     = "events.amazonaws.com"
  source_arn    = "${aws_cloudwatch_event_rule.app.arn}"
}
# Other resources each app need to create.

app1的模块如下: root\app1\main.tf:

module "app1" {
  # should_launch = 1
  source  = "../common_infra"
  app_name = "app1"
  schedule = "cron(01 01 ? * * *)"
  ……
}

使用该模块,我已经成功启动了一个 cloudwatch 事件,它按计划触发了 lambda,并且我已经成功启动了名为“app”的 lambda。 lambda 获取 app_name = app1 作为输入,然后在 app1 上工作。

当我如下创建另一个app2时, root\app2\main.tf:

module "app2" {
  # should_launch = 0
  source = "../common_infra"
  app_name = "app2"
  schedule = "cron(01 01 ? * * *)"
  ……
}

它尝试创建另一个 lambda 但失败,因为 lambda 已由 app1 模块创建。事实上,我不想创建一个新的 lambda,因为没有必要为 app1、app2…创建多个 lambda。我可以使用 input = app_name 来控制 lambda 应该做什么。

我尝试使用 should_launch(见上面的注释行)仅在创建 app1 时创建 lambda。但它不起作用。部署 app1 时,将创建 lambda。创建app2时。 Terrform 抱怨:

aws_cloudwatch_event_target.app_target 

找不到

arn = "${aws_lambda_function.app.arn}"

我的问题是:如何组织我的代码 layout/structure 以便 lambda 资源只为多个模块声明一次?例如也许我应该创建一个新文件夹 root/resource_called_by_all_module/lambda.tf?然后提前部署这个新文件夹?

是的,正如您所指出的,在当前设置中,您的所有模块都将尝试单独创建该文件中的所有资源。因为您的 lambda 的名称是硬编码的,所以 terraform 会正确地抱怨。

如果您拥有其他事物依赖的资源,您可以重新安排 Terraform 以在单独的 Terraform 应用程序上构建该资源。

所以您可以从这些文件中取出 Lambda 资源,并将其放入单独的文件夹中。然后,您只需 运行 Terraform 先申请这些共享资源 ('app' lambda),然后再申请依赖它们的资源 ('app1','app2')。

创建共享资源后,您可以使用 Terraform 数据源(通常是获取名称或 ARN)从中检索所需的详细信息。