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

126
我对是否将.tfstate文件提交到Git上有些困惑。根据Terraform文档,它指出:

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

然而,在使用Terraform的最佳实践的接受和投票答案中指出:

Terraform配置可以用于在不同基础架构上提供许多盒子,其中每个盒子都可能具有不同的状态。由于它也可以由多个人运行,因此应该将此状态放在集中位置(如S3)中,但不要放在Git上。

(原作者强调,而非我)

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

4个回答

103

有几个原因不要将你的.tfstate文件存储在Git中:

  1. 运行terraform apply后,你很可能忘记提交和推送更改,这样你的队友将会拥有过期的.tfstate文件。此外,这些状态文件没有任何锁定机制,如果两个团队成员同时在同一个.tfstate文件上运行Terraform,你们可能会覆盖彼此的更改。你可以通过两种方法解决这些问题:a)使用远程状态的Terraform.tfstate文件存储在S3存储桶中,每次运行terraform apply都会自动推送/拉取.tfstate文件;b)使用像terragrunt这样的工具为你的.tfstate文件提供锁定。
  2. .tfstate文件可能包含秘密信息。例如,如果你使用aws_db_instance资源,则必须指定数据库密码,而Terraform将以明文形式存储在.tfstate文件中。这本来就是Terraform的一个不好的实践,将未加密的秘密信息存储在版本控制中只会使情况更糟。至少,如果你在S3中存储.tfstate文件,则可以启用静态加密(SSL提供运动时的加密)并配置IAM策略来限制谁可以访问。这远非理想,我们必须看看关于此问题的开放性问题是否会得到解决。

更多信息请查看 如何管理 Terraform 状态Terraform 实战,这两本书都是我写的。


11
另一个看待这件事的原因/方式是:考虑将TF+Git作为使用版本控制进行软件开发。 在这种情况下,您不会将构建产物(即状态文件)存储在您的VC仓库中,而是存储在一个中央产物库中(例如S3存储桶)。 - KJH
5
现在不再需要使用Terragrunt来提供锁定功能了。Terraform已经内置了该功能:https://www.terraform.io/docs/state/locking.html - Evan Kroske
我认为可以公正地说,Terraform的.tfstate需要悲观锁定,而Git提供乐观锁定。 - giorgiosironi

73

简而言之:

重要提示! 存储在源代码控制中可能会暴露潜在敏感数据,并冒着使用旧状态运行Terraform的风险。不要这样做。

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

与本地和存储在源代码控制中相比,远程状态提供了显着的优势。下面详细介绍了这些优势。


Yevgeniy的回答很好。该问题现在有点不太具有争议性,因为Terraform已更新其文档以说明:默认情况下,Terraform还将一些状态放入terraform.tfstate文件中。此状态文件非常重要。它将各种资源元数据映射到实际资源ID,以便Terraform知道它正在管理什么。必须保存并分发此文件给任何可能运行Terraform的人。通常建议在使用Terraform时设置远程状态。这将意味着状态文件中存储的任何潜在机密信息都不会被检入版本控制。因此,已经不存在既定最佳实践与官方建议之间的分歧。

更新 2019-05-17

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

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

我不认为建议会再次恢复到源代码控制是首选的状态存储方法。

尽管上述文档引用了远程状态对于单独开发人员仍然有益

远程状态允许单独开发人员:


1
我最终使用了S3后端来在不同的开发人员之间共享和存储状态,而不是将其提交到git仓库中。感谢这个答案! - SaundersB

12

这可能取决于个人喜好,但我认为git(或任何其他源代码控制工具)不是存储状态文件的特别好的选择,因为状态文件是您编写的代码的输出,就像编译的二进制文件或甚至是压缩的JS或LESS编译成CSS一样。

此外,由于状态文件作为运行结果而不是实际更改的部分内容可能会很快发生变化,这使得整个过程相当尴尬。

然而,您确实需要一种与任何远程团队成员或其他设备共享这些状态文件的方式,即使您在不同的笔记本电脑/机器上进行开发。您还需要一种存储和备份这些文件的方法,因为如果丢失状态文件,则会遇到一些真正的痛苦,因为Terraform使用状态文件来确定其管理的内容,以免干扰其他工具。

我认为S3现在可能是您可以放置它们的最佳位置。它几乎是免费的,耐久性和可用性都非常好,在Terraform中有很好的原生支持,使用远程状态资源。也可能是最重要的是,您只需要创建一个S3存储桶即可开始。如果您打算使用这些产品之一,而不是使用Terraform的话,必须首先构建Consuletcd集群(否则您会遇到一个“先有鸡还是先有蛋”的问题,即您在哪里存储用于创建它们的状态文件?)即使您打算使用其中任何一个产品,这也可能是有点麻烦的。

显然,如果您正在使用OpenStack,则Swift应该是一个很好的替代方案(尽管我没有使用过)。我也没有使用过Hashicorp的Atlas,但如果您愿意为该服务支付费用,它可能同样有用。


5
我认为通过其他方式共享terraform.tfstate比Git更有优势。例如:S3,Dropbox等(打开版本控制)。这样就可以回滚到以前的基础架构状态。例如,将存储库从提交B回滚到提交A。如果terraform.tfstate未更改,则terraform将考虑如何回滚您在提交B期间添加的所有内容。回滚将很容易。如果terraform.tfstate也回滚到提交A,则terraform将认为terraform.tfstate与所需配置同步,并且不会将回滚应用于您的基础架构。

这个评论被低估了。如果有一个很好的理由不提交terraform.tfstate,那就是基于技术上的推理,而不是团队认为“这样更好”的政策决定。感谢您的回答。 - cluxter
这个评论被低估了。如果有一个很好的理由不提交terraform.tfstate,那就是基于技术上的原因,而不是团队认为“这样更好”的政策决定。感谢您的回答。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接