这是一个高级指南!在开始使用Terraform时,建议从命令行本地使用它。一旦 Terraform 在生产中定期使用,或者由更大的团队使用,自动化就会变得有价值,但本指南假定您熟悉正常的本地 CLI 工作流。
对于使用 Terraform 作为更改管理和部署管道的关键部分的团队,可能需要在某种自动化中编排 Terraform 运行,以确保运行之间的一致性,并提供其他有趣的功能,例如与版本控制挂钩的集成。
Terraform的自动化可以以各种形式出现,并且程度不同。一些团队继续在本地运行Terraform,但使用包装脚本为Terraform准备一致的工作目录,而其他团队则完全在Jenkins等编排工具中运行Terraform。
本教程介绍了在实现此类自动化时应考虑的一些事项,以确保Terraform的安全操作,并适应Terraform工作流程中需要特别注意的一些当前限制。它假设Terraform将在非交互式环境中运行,无法在终端上提示输入。对于包装器脚本,这不一定是正确的,但在业务流程工具中运行时通常是正确的。
本教程的目标是概述在自动化标准 Terraform 工作流时要考虑的事项。本集合中的其他教程将指导您实现本教程中讨论的概念。
-
这使用 CircleCI 部署 Terraform 基础架构教程将指导您使用 AWS S3 作为后端自动执行标准 Terraform 工作流。此方法使用 Docker 映像在每个 CircleCI 作业中本地运行 Terraform。
hashicorp/terraform:light
-
这使用 GitHub 操作自动执行地球化教程指导您完成标准自动化地球化云工作流.此方法利用 Terraform Cloud 进行远程运行和状态管理。虽然Terraform Cloud提供版本控制系统集成,包括GitHub,但这种方法使您能够在触发Terraform Cloud远程运行之前或之后添加状态检查,从而更好地使Terraform Cloud适应您的用例。
»自动化地球化 CLI 工作流程
在自动化中运行Terraform时,重点通常放在核心计划/应用周期上。因此,主路径与 CLI 用法大致相同:
- 初始化 Terraform 工作目录。
- 制定更改资源以匹配当前配置的计划。
- 让人工操作员审查该计划,以确保其可接受。
- 应用计划描述的更改。
可以使用熟悉的 Terraform CLI 命令执行步骤 1、2 和 4,并带有一些附加选项:
- terraform init -input=false 以初始化工作目录。
- terraform plan -out=tfplan -input=false 以创建一个计划并将其保存到本地文件。
tfplan
- terraform apply -input=false tfplan 以应用存储在文件中的计划。
tfplan
该选项指示 Terraform 不应尝试提示输入,而是期望所有必要的值由配置文件或命令行提供。因此,可能需要使用 and 上的选项来指定传统上在交互式使用下手动输入的任何变量值。-input=false
-var
-var-file
terraform plan
强烈建议使用支持远程状态,因为这允许 Terraform 自动将状态保存在一个持久位置,以便后续运行可以找到并更新该状态。选择支持状态锁定此外,还将针对可能由并发 Terraform 运行引起的争用条件提供安全性。
»控制自动化中的地球输出
默认情况下,某些 Terraform 命令的结尾是向用户提供可能的下一步的描述,通常包括要运行下一步的特定命令。
自动化工具通常会抽象出正在运行哪些命令的详细信息,从而导致这些消息令人困惑且不可操作,并且如果无意中鼓励用户完全绕过自动化工具,则可能是有害的。
当环境变量设置为任何非空值时,Terraform 会对其输出进行一些细微的调整,以不再强调要运行的特定命令。所做的具体更改会随着时间的推移而有所不同,但一般来说,Terraform会考虑此变量,以表明有一些包装应用程序可以帮助用户进行下一步。TF_IN_AUTOMATION
为了降低复杂性,此功能主要针对上述主工作流命令实现。无论此设置如何,其他辅助命令仍可能生成命令行建议。
»在不同的机器上计划和应用
在业务流程工具中运行时,可能很难或不可能确保 和 子命令在同一台计算机上、同一目录中运行,并且存在所有相同的文件。plan
apply
在不同的计算机上运行和运行需要一些额外的步骤来确保正确的行为。稳健的策略如下:plan
apply
- 完成后,存档整个工作目录,包括在 期间创建的子目录,并将其保存到可用于应用步骤的位置。一个常见的选择是作为所选业务流程工具中的“生成工件”。
plan
.terraform
init
- 在运行之前,获取在上一步中创建的归档文件,并将其解压缩到相同的绝对路径。这将重新创建计划后存在的所有内容,从而避免了在计划步骤中创建本地文件的奇怪问题。
apply
Terraform目前做出了一些假设,这些假设必须通过这样的自动化设置来适应:
- 保存的计划文件可以包含子模块和配置引用的其他数据文件的绝对路径。因此,有必要确保在相同的绝对路径下提取存档的配置。这通常是通过在某种隔离状态下运行Terraform来实现的,例如Docker容器,其中可以控制文件系统布局。
- Terraform 假设该计划将应用于与其创建位置相同的操作系统和 CPU 体系结构。例如,这意味着无法在 Windows 计算机上创建计划,然后在 Linux 服务器上应用它。
- Terraform 希望用于生成计划的提供程序插件在应用计划时可用且相同,以确保正确解释计划。如果在创建和应用计划之间升级Terraform或任何插件,则会产生错误。
- Terraform 无法自动检测用于创建计划的凭据是否授予对用于应用该计划的相同资源的访问权限。如果对每个凭据使用不同的凭据(例如,使用只读凭据生成计划),请务必确保两者在它们所属的相应服务上的哪个帐户中保持一致。
计划文件包含配置的完整副本、计划应用到的状态以及传递给 的任何变量。如果其中任何一个包含敏感数据,则应相应地保护包含计划文件的存档工作目录。对于提供程序身份验证凭据,建议尽可能改用环境变量,因为这些变量不包含在计划中,也不会由 Terraform 以任何其他方式保存到磁盘。terraform plan
»交互式批准计划
自动化Terraform工作流程的另一个挑战是希望在计划和应用之间执行交互式审批步骤。为了可靠地实现这一点,重要的是要确保一次只能有一个计划是未完成的,或者这两个步骤是相互关联的,以便批准计划时将足够的信息传递给应用步骤,以确保应用正确的计划,而不是一些也存在的后续计划。
不同的业务流程工具以不同的方式解决此问题,但通常通过构建管道功能实现,其中可以按顺序应用不同的步骤,后续步骤可以访问早期步骤生成的数据。
建议的方法是一次只允许一个计划未完成。应用计划时,针对同一状态生成的任何其他现有计划都将失效,因为现在必须相对于新状态重新计算这些计划。通过按顺序强制批准(或驳回)计划,可以避免这种情况。
»自动批准计划
虽然强烈建议对生产用例进行手动审查计划,但在预生产或开发环境中进行部署时,有时需要采用更自动的方法。
在不需要手动批准的情况下,可以使用更简单的命令序列:
该命令的此变体隐式创建一个新计划,然后立即应用它。该选项告诉Terraform在应用计划之前不需要对计划进行交互式批准。apply
-auto-approve
当 Terraform 有权对基础架构进行破坏性更改时,始终建议手动查看计划,除非在发生意外更改时允许停机。仅对非关键基础结构使用自动审批。
»使用地球化计划测试拉取请求
terraform plan
可以用作对Terraform配置的有效性执行某些有限验证的方法,而不会影响实际的基础设施。尽管计划步骤会更新状态以匹配实际资源,从而确保计划准确,但不会保留更新的状态,因此可以安全地使用此命令生成仅为帮助代码审查而创建的“一次性”计划。
在实现这样的工作流时,可以在相关代码审查工具(例如,Github Pull Requests)中使用钩子来为正在审查的每个新提交触发编排工具。在这种情况下,可以按如下方式运行 Terraform:
与在“主要”工作流程中一样,可能需要提供或酌情提供。在此方案中不使用该选项,因为永远不会应用为代码审查目的生成的计划。相反,一旦合并了更改,就可以从主版本控制分支创建和应用新计划。-var
-var-file
-out
请注意,通过变量或环境变量将敏感/秘密数据传递给Terraform将使任何可以提交PR的人都有可能发现这些值,因此必须在开源项目或任何私人项目中谨慎使用此流,其中部分或所有贡献者不应直接访问凭据, 等。
»多环境部署
Terraform的自动化通常与多次创建相同的配置齐头并进,以便为预发布测试或多租户基础架构等用例生成并行环境。在这种情况下,自动化有助于确保为每个环境使用正确的设置,并在每次操作之前正确配置工作目录。
用于多环境编排的两个最有趣的命令是 和 。前者可以与其他选项一起使用,以针对环境之间的任何差异定制后端配置,而后者可用于在单个后端中存储的相同配置的多个状态之间安全地切换。terraform init
terraform workspace
在可能的情况下,建议对所有环境使用单个后端配置,并使用以下命令在工作区之间切换:terraform workspace
在此使用模型中,后端存储中使用固定命名方案,以允许存在多个状态,而无需任何进一步的配置。
或者,自动化工具可以将环境变量设置为现有工作区名称,这将覆盖使用该命令所做的任何选择。建议仅将此环境变量用于非交互式用法,因为在本地 shell 环境中,很容易忘记设置了变量并将更改应用于错误的状态。TF_WORKSPACE
terraform workspace select
在一些更复杂的情况下,不可能共享相同的后端配置跨环境。例如,环境可能存在于目标服务中完全独立的账户中,因此需要为后端本身使用不同的凭据或终端节点。在这种情况下,可以通过以下方式覆盖后端配置设置选项-backend-configterraform init.
»预安装插件
在默认用法中,terraform init自动下载并安装配置中使用的任何提供程序的插件,并将它们放在目录的子目录中。这为简单的情况提供了更简单的工作流程,并允许每个配置可能使用不同版本的插件。.terraform
在自动化环境中,最好禁用此行为,而是提供一组已安装在运行 Terraform 的系统上的固定插件。这样可以避免在每次执行时重新下载插件的开销,并允许系统管理员控制哪些插件可用。
要使用此机制,请在系统上运行Terraform的某个位置创建一个目录,并将插件可执行文件放入其中。插件版本存档可在releases.hashicorp.com.请务必下载目标操作系统和体系结构的相应存档。
提取必要的插件后,新插件目录的内容将如下所示:
<span style="color:var(--text-color-base)"><span style="color:var(--code-light)"><code class="language-shell-session"><span style="color:var(--text-color-base)"><span style="color:#ef3b7d">$</span> ls -lah /usr/lib/custom-terraform-plugins
</span><span style="color:var(--text-color-base)">-rwxrwxr-x 1 user user 84M Jun 13 15:13 terraform-provider-aws-v1.0.0-x3
</span><span style="color:var(--text-color-base)">-rwxrwxr-x 1 user user 84M Jun 13 15:15 terraform-provider-rundeck-v2.3.0-x3
</span><span style="color:var(--text-color-base)">-rwxrwxr-x 1 user user 84M Jun 13 15:15 terraform-provider-mysql-v1.2.0-x3
</span></code></span></span>
文件名末尾的版本信息很重要,以便Terraform可以推断出每个插件的版本号。可以安装同一提供程序插件的多个版本,Terraform 将使用与提供程序版本约束在“地球形式”配置中。
填充此目录后,通常的自动下载和插件发现可以使用以下选项绕过行为:-plugin-dir
terraform init
使用此选项时,只有给定目录中的插件可供使用。这使系统管理员能够对执行环境进行高度控制,但另一方面,它可以防止使用尚未安装到本地插件目录中的较新的插件版本。哪种方法更合适将取决于每个组织内部的独特限制。
还可以通过创建一个目录来提供插件以及配置,该目录将在自动下载其他插件之前进行搜索。该标志可用于防止Terraform自动下载其他插件。terraform.d/plugins/OS_ARCH
-get-plugins=false
»地球云
作为本土自动化解决方案的替代方案,Hashicorp提供地球云.
在内部,Terraform Cloud 运行上述相同的 Terraform CLI 命令,使用在此站点上提供的相同版本二进制文件。
Terraform Cloud 以核心 Terraform CLI 功能为基础,可添加其他功能,例如基于角色的访问控制、计划和应用生命周期的编排、用于审查和批准计划的用户界面等等。
始终可以通过内部自动化运行Terraform,以便在Terraform Cloud不合适的情况下使用。建议将Terraform Cloud视为内部解决方案的替代方案,因为它提供了一个开箱即用的解决方案,该解决方案已经包含本指南中描述的最佳实践,因此可以减少开发和维护内部替代方案所花费的时间。