【问题标题】:Set Terraform variable only on initial creation仅在初始创建时设置 Terraform 变量
【发布时间】:2021-06-26 08:21:05
【问题描述】:

我想知道如果给定的资源是否已经创建,是否可以设置 Terraform 变量的值。

我的 Terraform 项目管理许多无状态资源,但也管理一种有状态资源:数据库。基础设施第一次到位时,我们想要初始化(导入)数据库,但不是下一次(当根据 Terraform 声明升级无状态资产时)。此导入由 EC2 实例的 User Data 脚本完成(编辑:EC2 实例是无状态的,为了方便我们将 DB 导入命令放在其 user_data 中并限制从 EC2 实例对 RDS DB 的访问)。

我们在用户数据脚本中检测是否是第一次并不明显(这需要开发)。所以现在我可以看到两个选项:

  • 在调用 terraform apply 的脚本中,我可以查询 Terraform 状态 (terraform state list) 以确定 DB 是否已经存在,并将其作为变量传递给 terraform apply
  • 但如果可以直接在 Terraform 声明中确定 DB 资源的当前状态(它是否存在)会更简单,所以我可以将它传递给我的用户数据脚本(因此它会初始化 DB或不)。我没有看到如何做到这一点。我看不到任何函数,看起来当我引用资源的属性(例如:RDS DB 的 ID)时,它将在创建资源后计算。

你知道我的第二点是否可行吗?

【问题讨论】:

  • 没有。 tf 中没有确定某物是否存在的功能,除非您为此实施了一些自定义解决方案。
  • 这个问题有点过于抽象,缺乏其他相关信息。如果您唯一的托管有状态资源是 RDS,那么为什么会有 user_data?这意味着一个实例也被管理,这是有状态的。此外,大概可以由提供者或在 Terraform 配置中为无状态资源赋予状态以确保它们的幂等性,然后您将有更多可用选项。
  • EC2 实例本身是无状态的(我们的服务器应用程序正在其上运行,它不会在其磁盘上存储任何数据并且可以销毁/重新创建)。我们目前使用它的user_data 来运行初始导入(以及其他初始化,例如为实例本身定制配置文件)。

标签: terraform


【解决方案1】:

一般来说,从 Terraform 自己的角度来看,如果这样的事情对特定对象。

例如,从 Terraform 的角度来看,user_data 只是要传递给 AWS 提供商的任意字符串,而 AWS 提供商又将其视为要传递给 AWS API 和 AWS API 的任意字符串反过来将其视为 EC2 实例中的软件可以检索的任意字符串。但是由于在您的 EC2 实例中运行的软件 可以保留状态(在磁盘上),该软件 可以潜在地跟踪“首次启动”与“后续启动”的概念",并据此采取不同的行动。许多 AMI 包括 CloudInit 作为解释 user_data 的软件,并且确实该软件确实跟踪首次启动和后续启动,因此它的某些模块可以在这两种情况下表现不同。

这种模型是否可以应用于其他资源类型将取决于相应的远程对象具有哪些功能,或者该系统的 Terraform 提供者在远程系统功能之上分层了哪些附加功能。例如,原则上,数据库实例的资源类型实现可能包含一些仅在初始创建期间才考虑的参数,尽管我不知道您使用的特定资源类型是否具有这种能力.

话虽如此,数据库自然是一个有状态的对象,因此可以直接检查它以确定它是否已被填充,而无需 Terraform 的帮助。我认为对您的潜在问题最可靠的答案是负责填充数据库的系统首先连接到数据库并查看它是否已被填充,如果是,则不执行任何操作。这样,数据库状态的真实来源就是数据库本身,您无需处理该信息的代理(例如 Terraform 状态)可能与现实不同步的尴尬情况。

【讨论】:

  • 我同意负责数据库的组件(在我的例子中是服务器应用程序及其位于用户数据中的初始化脚本)应该负责管理数据库的状态,所以会有成为真理的来源之一。由于服务器应用程序的复杂性,我没有这样做。我想我会使用战术解决方案(terraform state),直到我们对 DBimport 实施另一项计划改进。
猜你喜欢
  • 2020-05-01
  • 2018-06-03
  • 1970-01-01
  • 1970-01-01
  • 2016-04-29
  • 1970-01-01
  • 2010-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多