我怎样才能创建资源分为具有Terraform不同的模块?

时间:2019-02-01 09:18:06

标签: terraform terraform-provider-azure

我想使用不同的模块拆分资源创建,但是我一直无法弄清楚如何做。

对于此示例,我想创建一个Web应用程序(我正在使用azurerm提供程序)。为此,我将以下内容添加到了模块中:

resource "azurerm_app_service" "test" {
  name                = "${var.app_service_name}"
  location            = "${var.location}"
  resource_group_name = "${var.resource_group_name}"
  app_service_plan_id = "${var.app_service_plan_id}"

  app_settings {
    SOME_SETTING = "${var.app_setting}"
  }
}

它的工作原理,但我想有一个单独的模块,用于将所述应用程序的设置,因此:

  • 模块1创建网络应用
  • 第2单元应用应用设置
  • 潜在模块3将其他内容应用到网络应用

这可能吗?我尝试将其拆分(有两个模块定义了Web应用程序,但其中只有一个包含应用程序设置),但是我收到一条错误消息,指出该Web应用程序已经存在,因此似乎无法理解我试图操纵相同的资源。

详细信息上它是如何将要使用: 我将为最终用户提供一个UI,他/她可以在该UI上选择所需的资源堆栈,并为该人的项目打勾所需的一系列选项,以及填写基础结构所需的参数。

完成并提交参数后,会将其应用于Terraform模板。这是不可行的具有用于选项每个排列的模板,所以它必须包括根据所选择的选项的不同模块。

例如:如果用户勾选了Web应用程序,Cosmos DB和应用程序见解,则Terraform模板将包括这些模块(使用计数技巧来创建条件)。在这个例子中,我需要通过从应用程序的见解,Web应用程序的应用程序设置的仪表键,这是我的问题。

如果用户没有选择应用程序见解,那么我不需要设置Web应用程序,这就是为什么我需要逐步构建Terraform资源的原因。另外,根据用户选择的数据库类型,会将不同的设置添加到Web应用程序的设置中。

所以我的想法是创建一个模块以应用某些应用程序设置。我不知道这是否可能(或存在更好的方法),因此是我的问题。

2 个答案:

答案 0 :(得分:0)

执行此操作的最佳方法是使用bash脚本或所需的任何脚本语言(python)包装terraform。然后使用bash或python(jinja2)创建一个模板,以使用客户为设置选择的任何选项生成资源,运行该模板以生成terraform代码,然后应用它。

我已经用S3存储桶做了很多。在terraform 0.12中,您可以在terraform中生成模板。

答案 1 :(得分:0)

我知道这已经5个月了,但是我认为这里的部分情况是您描述的拆分方式与模块的使用方式并不完全匹配。一方面,您不能动态地“构建资源”,因为Terraform是设计声明性的。您只能定义资源,然后动态提供它的预定义输入(包括激活/停用的计数)。其次,模块不需要通过配置打开和关闭堆栈的某些部分。模块只是将资源集分组在一起以进行遏制和重用的一种方式。包含复杂模块层次结构的堆栈可为您提供的任何动力都可以在一个巨大的整体Blob中使用基本相同的代码来获得。整体将是一团糟,这是问题所在,您将无法将其用于其他用途。最后,使用模块来提供设置并不是真正的目的。是的,从理论上讲,您可以使用“ null_data_source”创建一个模块,然后将其纯粹用作某种填充程序以提供设置,但是,通过简单地以您提供的方式提供变量,这可能是不必要的复杂方法已经显示。

您可能像其他答案中提到的那样,需要将其包装在顶级的bash(etc)脚本中,这不是 对Terraform的限制。例如,一旦有了模块,就希望将所有当前应用的堆栈(针对每个客户或其他客户)保留在某种组合存储库中。在这些客户填写设置表格后,您将如何为其创建构图堆栈?您将不得不使用某些不是Terraform的文件创建自动化来做到这一点。 Terraform在那里执行存在的堆栈。首先,不必使用外部文本编辑器来创建.tf文件,这不是Terraform的限制;在这种情况下,您可以使用一些外部脚本为客户动态创建合成堆栈,这并不是一种限制。 ,这只是您使用自动化为Terraform做好准备以完成应用堆栈的工作的一部分方式。

因此,您无法避免使用此外部脚本工具,您可能会用它来为客户特定的合成堆栈(指的是您的模块)创建文件夹,用默认文件填充文件夹,并创建一个.tfvars根据客户从表单中输入的文件。然后,您可以通过多种方式进行操作:

  1. 您拥有.tfvars文件是客户构成堆栈之间的唯一区别。给定.tfvars中的变量,无论您使用或不想使用什么模块,都可以通过您提到的“计数技巧”来激活/停用。这种方式的优点是易于推理,因为所有客户构成堆栈都是同一件事,只是配置不同。

  2. 您可以让该工具将所需的模块定义实际插入到组成堆栈的文件中。这将创建更简洁的合成堆栈,并减少较少的“计数技巧”,但每个客户的堆栈都是它自己的怪异雪花。

就拆分模块而言,请注意,这涉及整个艺术/科学/哲学。我指的是this resource on IAC design patternsthis talk on the subject(相关位从19:15开始)。这些是该主题的一般背景。

对于您的特定情况,您基本上希望将所有最小的可分割功能块(可以打开/关闭)放入它们自己的模块中,每个模块都由更高级别的使用模块来引用。您提到了为每个置换都拥有一个模块是不可行的,再次考虑到它是错误的。您的目标是要成为模块和组合的“ 树”。在顶层,您将具有(重击等)工具,该工具创建新客户组合文件夹,其.tfvars文件,并放入将成为“模块树”顶部的相同组合堆栈。代表客户堆栈中可选部分的每个模块都将计数。这些模块将在内部具有功能性资源,或者将是中间模块,它们自身将实例化一组包含资源的可配置子模块。

但是,您需要坐下来思考一下“决策树”的设计,该决策树以模块的层次结构实现,涵盖了所有无法创建单独的单片堆栈的排列。

>

TFv12动态嵌套块将特别在具有或不具有声明的块(如app_settings)的一方面方面为您提供帮助。由于您不能动态地“构建资源”,因此,在这种情况下,唯一的选择就是拥有一个中间模块,该模块以多种方式声明资源(带有和不带有app_settings块),并且将通过“ count”选择一个技巧”或其他输入配置。既然动态块已经存在,这种事情就没有必要了。