Terraform
使用仅刷新模式同步 Terraform 状态
Terraform 依赖于工作区状态文件的内容来生成执行计划,以对您的资源进行更改。为了确保提议的更改的准确性,您的状态文件必须是最新的。
在 Terraform 中,刷新你的状态文件会更新 Terraform 对你的基础设施的了解,正如你的状态文件中所表示的那样,使其与你的基础设施的实际状态同步。Terraform plan 和 apply 操作会在其功能中运行隐式的内存刷新,从而在建议基础设施更改之前协调状态文件中的任何偏差。你还可以使用 -refresh-only 标志,为 plan 和 apply 操作更新你的状态文件,而无需对你的基础设施进行修改。
在本教程中,您将使用 -refresh-only 标志安全地刷新您的 Terraform 状态文件。您还将回顾 Terraform 的隐式刷新行为以及 -refresh-only 标志相对于已弃用的 terraform refresh 子命令的优势。
先决条件
您可以使用 Terraform Community Edition 或 HCP Terraform 以相同的流程完成本教程。HCP Terraform 是一个平台,可用于管理和执行您的 Terraform 项目。它包含远程状态和执行、结构化计划输出、工作区资源摘要等功能。
选择 HCP Terraform 标签页以使用 HCP Terraform 完成本教程。
本教程假定您熟悉 Terraform 工作流。如果您不熟悉 Terraform,请先完成 入门教程。
为了完成本教程,您需要以下条件
- Terraform v1.1+ 本地安装。
- 一个配置了本地凭证的AWS 账户,这些凭证已配置为与 Terraform 一起使用。
克隆示例仓库
克隆本教程的 示例仓库。
$ git clone https://github.com/hashicorp-education/learn-terraform-refresh
进入仓库目录。
$ cd learn-terraform-refresh
查看配置
打开 main.tf 以检查示例配置。它定义了一个 EC2 实例和一个数据源来识别最新的 Amazon Linux AMI。提供程序块引用了 region 输入变量,该变量默认为 us-east-2。
main.tf
provider "aws" {
region = var.region
default_tags {
tags = {
hashicorp-learn = "refresh"
}
}
}
创建基础设施
初始化此配置。
$ terraform init
Initializing the backend...
##...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
应用您的配置。对提示输入 yes 以确认操作。
$ terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_instance.server will be created
+ resource "aws_instance" "server" {
## ...
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_instance.server: Creating...
aws_instance.server: Still creating... [10s elapsed]
aws_instance.server: Still creating... [20s elapsed]
aws_instance.server: Creation complete after 22s [id=i-072ef122350d5a3e5]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
仅运行刷新计划
一个常见的错误场景,可能导致 Terraform 刷新状态文件的内容,是错误地修改了您的凭证或提供程序配置。通过更新您的 AWS 提供程序的区域来模拟这种情况。然后,您将查看 Terraform 刷新后的状态文件提议的更改。
在您的 learn-terraform-refresh 目录中创建一个 terraform.tfvars 文件。打开该文件,并粘贴以下配置以覆盖默认区域变量。
terraform.tfvars
region = "us-west-2"
由于您在 main.tf 中将 region 变量传递给您的 AWS 提供程序配置,因此这将重新配置您的提供程序为 us-west-2 区域。您之前创建的资源仍然在 us-east-2 中。
运行 terraform plan -refresh-only 以查看 Terraform 将如何更新您的状态文件。
$ terraform plan -refresh-only
aws_instance.server: Refreshing state... [id=i-072ef122350d5a3e5]
Note: Objects have changed outside of Terraform
Terraform detected the following changes made outside of Terraform since the last "terraform apply":
# aws_instance.server has been deleted
- resource "aws_instance" "server" {
## ...
}
This is a refresh-only plan, so Terraform will not take any actions to undo these. If you were expecting these changes then you can apply this plan to
record the updated values in the Terraform state without changing any remote objects.
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
由于您已将提供程序更新为 us-west-2 区域,Terraform 尝试定位状态文件中跟踪的 EC2 实例的实例 ID,但由于它位于不同的区域而失败。Terraform 假定您已销毁该实例,并希望将其从您的状态文件中删除。
如果通过 -refresh-only 计划对状态文件进行的修改是可以接受的,您可以运行 terraform apply -refresh-only 并批准该操作以覆盖您的状态文件,而无需修改您的基础设施。但是,在本教程中,刷新状态文件会删除您的资源,因此不要运行 apply 操作。
查看 Terraform 的刷新功能
在 Terraform 的早期版本中,刷新状态文件的唯一方法是使用 terraform refresh 子命令。但是,这不如 -refresh-only 计划和应用模式安全,因为它会自动覆盖您的状态文件,而不会让您有机会先查看修改。在这种情况下,这意味着自动从您的状态文件中删除所有资源。
terraform plan 和 terraform apply 操作的 -refresh-only 模式通过让您查看对状态文件的提议更改,使检查 Terraform 状态与实际基础设施更加安全。它让您可以避免错误地从状态中删除现有资源,并有机会更正您的配置。
仅刷新的 apply 操作还会更新输出(如果需要)。如果您有任何其他工作区使用 terraform_remote_state 数据源来访问当前工作区的输出,-refresh-only 模式允许您预测下游影响。
为了对您的基础设施提出准确的更改,Terraform 首先尝试调和状态文件中跟踪的资源与您的实际基础设施。 Terraform plan 和 apply 操作首先运行内存刷新以确定要对您的基础设施提出哪些更改。在确认 terraform apply 后,Terraform 将更新您的基础设施和状态文件。
尽管 Terraform 将在未来的版本中继续支持 refresh 子命令,但它已被弃用,我们鼓励您改用 -refresh-only 标志。这使您可以查看状态文件中的任何更新。与 refresh 子命令不同,-refresh-only 模式在使用了 HCP Terraform 作为远程后端的 workspace 中受支持,允许您的团队协作审查任何修改。
清理资源
现在,您已经查看了 -refresh-only 标志的行为,您将销毁您配置的 EC2 实例。
首先,删除您的 terraform.tfvars 文件,以使用 region 变量的默认值。
$ rm terraform.tfvars
现在运行 terraform destroy 以销毁您的基础设施。回复 yes 以确认操作。
$ terraform destroy
aws_instance.server: Refreshing state... [id=i-072ef122350d5a3e5]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# aws_instance.server will be destroyed
- resource "aws_instance" "server" {
## ...
}
Plan: 0 to add, 0 to change, 1 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
aws_instance.server: Destroying... [id=i-072ef122350d5a3e5]
aws_instance.server: Still destroying... [id=i-072ef122350d5a3e5, 10s elapsed]
aws_instance.server: Still destroying... [id=i-072ef122350d5a3e5, 20s elapsed]
aws_instance.server: Still destroying... [id=i-072ef122350d5a3e5, 30s elapsed]
aws_instance.server: Destruction complete after 31s
Destroy complete! Resources: 1 destroyed.
如果您在此教程中使用了 HCP Terraform,则在销毁资源后,请从您的 HCP Terraform 组织中删除 learn-terraform-refresh workspace。
下一步
您使用了 Terraform 的 -refresh-only 模式来安全地比较您的基础设施和状态文件。您还查看了 Terraform 标准操作中的隐式刷新行为。
要了解更多关于管理状态和漂移的信息,请完成以下教程
- 了解 HCP Terraform 的 漂移检测 功能如何帮助您确保您的实际资源与跟踪它们的 Terraform 状态相匹配。
- 管理资源漂移
- 管理状态中的资源
- 排查 Terraform 的常见问题