一、Treeaform-state的作用
Terraform-state是指Terroform的状态,是terraform不可缺少的生命周期元素。本质上来讲,terraform状态是你的基础设施配置的元数据存储库,terraform会把它管理的资源状态保存在一个状态文件里。
默认情况下,状态保存在一个
名为terraform.tfstate的文件中,但也可以远程存储,在团队协作管理的基础设施场景下,推荐采用远程存储。
terraform 使用状态来创建执行计划并更改基础设施,在任何操作之前,terraform会执行刷新操作以用基础设施的实际状态来更新状态。terraform的状态的主要目的是存储在远端系统上(主要存储在对象存储中)和配置文件中声明的资源实例之间的绑定关系。当terraform通过配置文件创建或更改了远端对象时,它会将该远端对象存储的表示记录与之对应的资源实例中,并保存在状态文件中,之后,terraform会根据实际情况来更新或者删除资源。
每个资源块中常见的基础设施资源都是通过其resource_name在terraform状态中标识的,其对资源的管理流程大致如下;
- 当第一次通过terraform apply应用terraform配置时,会创建基础设施资源,同时自动生成一个状态文件,该文件引用资源块中声明的名称。
- 如果一个资源已经在terraform状态文件中有标识,那么terraform会将配置文件与状态文件和当前资源远端的实际状态进行比较,并根据比较结果,会生成一个执行计划。
- 当执行计划时,他会更新资源的状态以匹配配置文件中的定义,如果远端api限制无法实现就地更新参数,那么执行该计划会将先销毁资源,然后再重新创建资源,如果是一个销毁资源的计划,将发起资源的销毁操作
- 计划执行成功后,terraform状态文件会更新以反映当前的基础设施状态
- 如果某资源已从当前terraform配置中移除但是状态文件中仍然存在,terraform则会比较配置文件并销毁不存在的资源
二、存储terraform state
terraform 默认将本地状态文件保存在当前工作目录中,扩展名为.tfstate,因此他们不需要额外的维护。本地状态文件适用于只有一个开发人员的项目,当多个开发人员同时运行terraform并且每台机器都有对当前基础设施的理解和配置时,默认的本地配置文件就不适合了。
在团队协作开发场景中使用本地状态时主要存在以下几个问题:
- 本地状态没有共享访问权限
当使用 Terraform 更新你的基础设施,团队中的每个成员都需要访问相同的状态文件,这意味着这些文件必须存储在一个共享的位置,比如 ECS 实例特定的位置,而这无形中增加了管理成本。 - 不能锁定本地状态文件
如果两个团队成员同时运行 Terraform,他们可能会遇到竞争条件,因为多个 Terraform 进程可能同时在更新状态文件。在这种情况下,可能带来导致冲突、数据丢失和状态文件损坏等风险。 - 本地状态文件不保密
当信息以明文形式存储在状态文件中时,敏感数据将存在被暴露的风险,例如数据库凭证,SSH 登录密码等。
因此,当一个团队中有多个开发人员通过编写代码来管理基础设施时,我们推荐你应该将状态文件存储在一个远端的中心位置。这样,当基础设施发生变化时,Terraform 状态文件会更新并同步,团队中的所有人员将始终使用最新的基础设施状态。
面对本地状态存在的问题,当使用远端状态存储时,这些问题将会得到解决:
- 远端状态文件会自动更新
当远程存储时,状态文件会自动更新,即一旦配置了远程后端,每次运行 plan 或 apply 命令时,Terraform 将自动从远端加载状态文件。除此之外,它还会在每次 apply 后自动将状态文件同步存储在远端中,因此不存在手动错误的情况。 - 远端状态文件支持状态锁定
当执行 Terraform 命令时,可以对远端状态文件进行加锁,这样如果多个开发人员同时运行 terraform apply,它不会因同时更新而损坏。 - 远端状态文件存储比本地存储更安全
OSS Bucket 支持本地传输加密和远端加密功能。此外,OSS Bucket 包括多种配置访问权限的方法,因此你可以以精细化的方式控制状态文件的访问权限。
三、配置远端状态存储
- 创建远端状态所依赖的资源
首先,将 alicloud_oss_bucket,alicloud_ots_instance,alicloud_ots_table 资源添加到 Terraform 配置文件中,例如 main.tf,并按照自身的需求对资源进行配置,如设置 Bucket 名称,OTS 实例名称,实例规格,表格名称等。完成配置后,运行 terraform apply 来创建 Bucket 以及其他资源。 - 配置远端状态
接下来,将代码配置添加到一个名为 backend.tf 的新 Terraform 配置文件中,接着运行 terraform init 来配置你的 Terraform 远端状态。此时,Terraform 检测到本地已经有一个状态文件,并提示你将其复制到新的 OSS Bucket 中。输入 yes,terraform init 运行成功后,你的 Terraform 状态将存储在 OSS Bucket 中。
四、Terraform State 的最佳实践
针对 Terraform 状态文件,我们从状态优化和安全性方面给出如下建议:
- 团队协作场景使用远端状态
首先,在团队协作场景中应使用远程状态,以便锁定和版本控制状态文件。阿里云的客户应使用 OSS 作为远端状态存储后端,并使用 OTS 来锁定状态文件。将敏感信息与 Terraform 配置文件的版本控制分开,并确保只有构建系统和高权限管理员可以访问远程状态存储 Bucket。为了防止意外地将开发环境的状态文件提交到源代码版本控制系统中(如Github,Gitlab等),请为 Terraform 状态文件配置 gitignore。 - 不要在状态中存储敏感数据
许多资源和数据提供者会将敏感数据以明文形式存储在状态文件中,这是存在安全隐患的。如果可能,尽量避免在状态文件中存储敏感信息。 - 对状态进行加密
增加一层防御,始终对远端状态文件进行加密。阿里云 OSS 存储支持 KMS、AES256、SM4 三种加密方式的,客户可以通过自定义的 KMS 密钥对状态文件提供额外一层保护。 - 不要手动修改 Terraform 状态
状态文件是维护 Terraform 配置和阿里云基础设施资源之间的映射关系的关键,状态文件的损坏可能导致重大的基础设施问题。因此不要尝试手动修改 Terraform 状态文件内容。