我应该将.tfstate文件提交到Git吗?


76

我对是否将.tfstate文件提交到Git感到困惑。该Terraform文档状态:

Terraformterraform.tfstate默认还会在文件中添加一些状态。这个状态文件非常重要。它将各种资源元数据映射到实际资源ID,以便Terraform知道它正在管理什么。该文件必须保存并分发给可能运行Terraform的任何人。我们建议您简单地将其放入版本控制中,因为它通常不会太大。

现在,另一方面,在使用Terraform状态时,关于最佳实践的答案已被接受并被认可:

Terraform配置可用于在不同基础架构上置备许多盒子,每个盒子可能具有不同的状态。由于它也可以由多个人运行,因此该状态应位于集中位置(如S3),而不是git。

(由原作者强调,而不由我强调)

谁是正确的,如果是,为什么?

Answers:


47

TL; DR:

重要!存储在源代码管理中可能会暴露潜在的敏感数据,并存在针对旧版本状态运行Terraform的风险。不要这样

Terraform不再建议将状态存储在源代码管理中。您的“好”选项是远程的或本地的。

相对于本地控制和存储在源代码管理中,远程状态具有明显的优势。这些的详细信息如下。


原始答案:

叶夫根尼的答案是一个很好的答案。由于Terraform已更新其文档以表明:

Terraform默认还会将某些状态放入terraform.tfstate文件。这个状态文件非常重要。它将各种资源元数据映射到实际资源ID,以便Terraform知道它正在管理什么。该文件必须保存并分发给可能运行Terraform的任何人。通常建议在使用Terraform时设置远程状态。这意味着存储在状态文件中的任何潜在机密都不会被检入版本控制中

因此,既定的最佳做法和官方建议之间不再存在分歧。


更新2019-05-17

最新版本的文档中,此内容已更改为:

...默认情况下,此状态存储在名为“ terraform.tfstate”的本地文件中,但也可以远程存储,在团队环境中效果更好。...

我不希望该建议会恢复为源代码管理作为存储状态的首选方法。

尽管上面引用了文档,但作为独立开发人员远程状态仍然有益

远程状态允许单独开发人员执行以下操作:

  • 在多个设备上处理/运行其Terraform代码
  • 根据所选的后端,轻松备份并防止丢失状态文件
  • 通过输出隔离其架构的各个部分
  • 根据所选的后端自动加密静止状态文件

1
我最终利用S3后端在不同开发人员之间共享和存储状态,而不是将其提交到git repo。感谢您的回答!
SaundersB

56

有一些原因不将.tfstate文件存储在Git中:

  1. 运行后terraform apply,您可能会忘记提交和推送更改,因此您的队友将拥有过期的.tfstate文件。同样,如果没有两个状态文件的任何锁定,则如果两个团队成员同时在同一.tfstate文件上运行Terraform,则您可能会覆盖彼此的更改。您可以通过以下两种方法来解决这两个问题:a).tfstate使用Terraform远程状态将文件存储在S3存储桶中,这将在.tfstate每次运行时自动推送/拉动文件terraform apply; b)使用terragrunt之类的工具来为.tfstate文件提供锁定。
  2. 这些.tfstate文件可能包含机密。例如,如果使用aws_db_instance资源,则必须指定数据库密码,然后Terraform会将其以明文形式存储在.tfstate文件中。首先,这代表Terraform的一种不好的做法,并且在版本控制中存储未加密的机密只会使情况变得更糟。至少如果您将.tfstate文件存储在S3中,则可以启用静态加密(SSL在移动时提供加密)并配置IAM策略以限制谁可以访问。这离理想还很遥远,我们必须看看讨论此问题的公开讨论问题是否已经解决。

有关更多信息,请查看如何管理Terraform状态Terraform:启动和运行


7
这是查看此问题的另一个原因/方式:将TF + Git视为使用版本控制的软件开发。在那种情况下,您不会将构建工件(即状态文件)存储在VC存储库中,而是存储在中央工件存储库(例如S3存储桶)中。
KJH '16

3
您不再需要Terragrunt提供锁定。现在它已内置在Terraform中:terraform.io/docs/state/locking.html
Evan Kroske

我认为可以公平地说Terraform.tfstate需要悲观锁定,而Git提供了乐观锁定。
giorgiosironi

8

这可能会归结为偏好,但我想说git(或任何其他源代码控制)不是存储状态文件的特别好选择,因为状态文件是您正在编写的代码的输出,就像编写的二进制文件甚至是最小化JS或LESS编译为CSS。

最重要的是,状态文件作为正在运行的事物的输出可能会在状态文件中快速变化,而不是在代码中实际更改事物,这会使整个事情变得很尴尬。

但是,如果您在不同的笔记本电脑/机器上进行开发,则确实需要某种方式与任何远程团队成员甚至其他设备共享这些状态文件。您还将需要某种方式来存储和备份这些内容,因为如果丢失状态文件,您将遭受一些真正的痛苦,因为Terraform使用状态文件来确定其要管理的内容,以免踩到脚尖其他工具。

我想说S3可能是您现在可以放置它们的最佳位置。它几乎免费,耐用性和可用性都很出色,使用远程状态资源在Terraform中对其提供了很好的本机支持。也许最重要的是,您只需要创建一个S3存储桶即可上手。即使您打算使用其中任何一种产品,也必须首先在没有Terraform的情况下构建Consuletcd集群(否则您会遇到鸡和蛋的问题,即在哪里存储创建这些对象的状态?)。

显然,如果您使用的是OpenStack,那么Swift应该是一个不错的选择(尽管我没有使用过)。我也没有使用过Hashicorp的Atlas,但是如果您愿意为此服务付费,它可能同样有用。


0

我看到通过其他方式(而不是Git)共享terraform.tfstate的优势。

例如:S3,Dropbox等。(启用版本控制)

然后,可以回滚到以前的基础结构状态。

例如,您将数据库从提交B回滚到提交A。如果terraform.tfstate不变-terraform将考虑如何回滚在提交B期间添加的所有内容。回滚将很容易。

如果terraform.tfstate也已回滚以提交A-则terraform将认为terraform.tfstate与所需的配置同步,并且不会将回滚应用于您的基础结构。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.