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

Posted

技术标签:

【中文标题】使用 Terraform 模块创建资源,其中一些资源由模块共享【英文标题】:Create resources using Terraform Module with some resources shared by the modules 【发布时间】:2019-08-26 06:49:54 【问题描述】:

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

模块调用的通用基础设施是: 根\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的模块如下: 根\app1\main.tf:

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

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

当我如下创建另一个 app2 时, 根\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"

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

【问题讨论】:

您是在问如何组织代码以使 lambda 资源仅在多个模块中声明一次,或者为什么一个模块可以声明而另一个模块不能声明,或者如何组织代码等lambda 设置独立于应用程序特定的资源,还是完全独立于其他东西?您很好地描述了当前状态,但不清楚您在问什么,因为不清楚您在这里想要什么路径,因为您真正提出的问题非常广泛。 @MattSchuchard:谢谢我更新了我的帖子。我的意思是我的代码的正确布局/结构是什么。 【参考方案1】:

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

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

因此,您可以将 Lambda 资源从这些文件中取出,并将其放入单独的文件夹中。然后,您只需在依赖它们的资源('app1'、'app2')之前先运行 Terraform 应用这些共享资源('app' lambda)。

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

【讨论】:

谢谢哈米。这可能是唯一的解决方案。 我确信有一些方法可以通过在 Terraform 中使用条件等来实现它,但我想说保持文件的可读性更重要:)

以上是关于使用 Terraform 模块创建资源,其中一些资源由模块共享的主要内容,如果未能解决你的问题,请参考以下文章

Terraform : for_each 一个一个

Terraform 模块作为“自定义函数”

Terraform 模块输出用作其他模块中的输入,特别是 for_each

Terraform For_Each:如何引用创建的资源 ID

Terraform适用于现有的ARM资源。需要国家吗?

是否可以重载 terraform 模块?