Terraform
初始化 Terraform 配置
编写 Terraform 配置后,核心 Terraform 工作流程包含三个主要步骤:
- 初始化(Initialize):准备工作空间,以便 Terraform 可以应用配置。
- 计划(Plan):允许您在应用更改之前预览 Terraform 将要进行的更改。
- 应用(Apply):执行计划中定义的更改,以创建、更新或销毁资源。
当您初始化 Terraform 工作区时,Terraform 会配置后端,安装配置中引用的所有提供程序和模块,并在尚不存在的情况下创建版本锁定文件。此外,您可以使用 terraform init 命令来更改工作区的后端并升级工作区的提供程序和模块。
在本教程中,您将初始化一个使用本地模块和远程模块的 Terraform 工作区,探索 Terraform 用于存储提供程序和模块的 .terraform 目录,并更新您的提供程序和模块版本。在此过程中,您将更多地了解 terraform init 命令在 Terraform 工作流程中的重要作用。
先决条件
您可以使用 Terraform Community Edition 或 HCP Terraform 以相同的流程完成本教程。HCP Terraform 是一个平台,可用于管理和执行您的 Terraform 项目。它包含远程状态和执行、结构化计划输出、工作区资源摘要等功能。
选择 HCP Terraform 标签页以使用 HCP Terraform 完成本教程。
克隆示例仓库
在您的终端中,克隆 learn-terraform-init 仓库。
$ git clone https://github.com/hashicorp-education/learn-terraform-init
导航到克隆的仓库。
$ cd learn-terraform-init
查看配置
此目录包含使用多个提供程序、本地模块和远程模块的 Terraform 配置。您将使用这些资源来查看 Terraform 如何初始化工作目录。
$ tree
.
├── LICENSE
├── main.tf
├── modules
│ └── aws-ec2-instance
│ ├── main.tf
│ └── variables.tf
├── README.md
├── terraform.tf
└── variables.tf
示例仓库包括以下内容
LICENSE包含 HashiCorp 根据 Mozilla Public License 分发示例配置的文本。main.tf包含示例配置使用的资源和数据源。modules/aws-ec2-instance目录包含一个 Terraform 模块,用于在 AWS 上配置 EC2 实例。README.md描述了示例配置。terraform.tf定义了terraform块,该块定义了提供程序、远程后端以及与此配置一起使用的 Terraform 版本。variables.tf定义了此配置中使用的变量。
初始化你的工作区
初始化您的 Terraform 工作区。
接下来,Terraform 下载配置所需的模块。
Terraform 识别到 module "ec2-instance" 块使用本地 modules/aws-ec2-instance 模块。 接下来,Terraform 确定 module "hello" 块引用了一个远程模块,因此它从公共 Terraform Registry 下载它。
Initializing modules...
- ec2-instance in modules/aws-ec2-instance
Downloading registry.terraform.io/joatmon08/hello/random 4.0.0 for hello...
- hello in .terraform/modules/hello
接下来,Terraform 下载配置所需的提供程序。
由于配置尚未具有锁定文件,Terraform 下载了 aws 和 random 在 required_providers 块中指定的提供程序,该块位于 terraform.tf 中。
Initializing provider plugins...
- Finding hashicorp/random versions matching "3.6.0"...
- Finding hashicorp/aws versions matching "6.2.0"...
- Installing hashicorp/random v3.6.0...
- Installed hashicorp/random v3.6.0 (signed by HashiCorp)
- Installing hashicorp/aws v6.2.0...
- Installed hashicorp/aws v6.2.0 (signed by HashiCorp)
当你初始化工作区时,Terraform 将尝试下载工作区锁定文件中指定的提供程序版本。 如果锁定文件不存在,Terraform 将使用 required_providers 块来确定提供程序版本并创建一个新的锁定文件。 如果两者都不存在,Terraform 将搜索匹配的提供程序并下载最新版本。
接下来,Terraform 创建锁定文件(如果它不存在),或者在必要时更新它。
Terraform 的锁定文件 .terraform.lock.hcl 记录了此运行中使用的提供程序的版本和哈希值。 这确保了在不同环境中 Terraform 运行的一致性,因为 Terraform 默认情况下将下载锁定文件中记录的版本以供将来的运行使用。
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
当你在源代码控制存储库中管理 Terraform 配置时,请将 .terraform.lock.hcl 文件与你的配置文件一起提交。
最后,Terraform 打印出一条成功消息,并提醒你如何规划你的配置,以及在更改你的模块或后端配置时重新运行 terraform init。
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.
验证你的配置
现在你已经初始化了你的工作区并下载了所需的模块和提供程序,Terraform 可以验证你的配置语法是否有效且内部一致。 这包括检查你的资源块是否具有无效或缺失的参数。 你必须初始化你的工作区才能验证你的配置。
验证你的配置。
$ terraform validate
Success! The configuration is valid.
查看初始化工件
当你初始化一个新的 Terraform 工作区时,它会创建一个名为 .terraform.lock.hcl 的锁定文件和 .terraform 目录。
探索锁文件
锁文件确保 Terraform 在您的团队内部和远程执行环境中使用的提供程序版本相同。 在初始化期间,Terraform 将下载此文件指定的提供程序版本,而不是最新版本。
打开 .terraform.lock.hcl 以查看其结构和内容。
.terraform.lock.hcl
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/aws" {
version = "6.2.0"
constraints = "6.2.0"
hashes = [
"h1:ziUjk3KGwBa7bAwZaPuQklfcQ3Qlx2d0rlYFvdZn4g8=",
"zh:224b20371f7c7ce14d69a84e16ae94baa0a06c132474d4bc4d192d86936bc750",
"zh:2c079ad275c32b9abae7616d07c24901340207a85995ce0025ac38af16b317b7",
"zh:2d139c99d6e8e48cc5439c2945eee583bb3a2d7faf484639cdfd4590ebc294f2",
"zh:2f2dc72de43d845e5df5a1adeadd4a48f3cacfe413b89b95f50294a386a90124",
"zh:304d4e706ac34aba080a81867209c65cdd28f8e596c02b3565f6530ab697cf94",
"zh:40e69328ae11fe1711b34226d45aa4c685f73e8f958c76c49f4f6a6627a1a54f",
"zh:5c5c9faab6fe242b77f0d0ab6664313dd89409371123e2ec376c72e8f2cd97b3",
"zh:7824709f0226afec5e3ad41392233b4bd7d925bae0d35f4a2ac854b3516e955c",
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
"zh:ab5417435121e8f9a6f539a6972f20c060ebc78624c1ce7c190671f163c423e4",
"zh:d6939385de4931f9fe07c87b744468fbfa96bd4b47861020d68e7ba1efb4185f",
"zh:e51434d1ba106c55d04fdc223aaf403b897ff96cba9bfce4c51854c805c36ed8",
"zh:e6d1012bafe338759ac42a59f566f8c4ad64a67faa3152c7fb758704d890cd75",
"zh:ee24b989ee3b6be79a7f24e97c144535bf7053471ae65343220db3ae78c7632a",
"zh:f61ec9482b9887c4901946407992874531b0c2eadab0c743fdfca4e6cd6dd889",
]
}
provider "registry.terraform.io/hashicorp/random" {
version = "3.6.0"
constraints = "3.6.0"
hashes = [
"h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=",
"zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d",
"zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211",
"zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829",
"zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d",
"zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17",
"zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21",
"zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839",
"zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0",
"zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c",
"zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e",
]
}
如果锁文件中的 provider 块中定义的版本与您的配置的 required_providers 块中定义的版本不匹配,Terraform 将提示您使用 -upgrade 标志重新初始化您的配置。 您将在下一部分中执行此操作。
探索 .terraform 目录
Terraform 使用 .terraform 目录来存储项目的提供程序和模块。 当您运行 validate、plan 和 apply 时,Terraform 将引用这些组件。
查看 .terraform 目录结构。
$ tree .terraform -L 1
.terraform
├── modules
└── providers
请注意,.terraform 目录包含两个子目录:modules 和 providers。 这两个目录包含您的 Terraform 工作区使用的模块和提供程序。
.terraform/modules目录包含一个modules.json文件,以及远程模块“hello”的本地副本。$ tree .terraform/modules ├── hello │ ├── README.md │ └── random.tf └── modules.json打开
modules.json。 此文件显示配置使用了三个模块:根模块(引用工作区根目录中的配置)、本地aws-ec2-instance模块和远程hello模块。modules.json
{ "Modules": [ { "Key": "", "Source": "", "Dir": "." }, { "Key": "ec2-instance", "Source": "./modules/aws-ec2-instance", "Dir": "modules/aws-ec2-instance" }, { "Key": "hello", "Source": "registry.terraform.io/joatmon08/hello/random", "Version": "4.0.0", "Dir": ".terraform/modules/hello" } ] }aws-ec2-instance模块引用一个本地模块,因此 Terraform 直接引用在示例仓库的modules/aws-ec2-instance目录中找到的模块配置。 这意味着如果您对本地模块进行更改,Terraform 会立即识别它们。由于
hello模块是远程模块,因此 Terraform 从其源下载该模块并在您初始化工作区时将其本地副本保存到.terraform/modules/hello目录中。 打开.terraform/modules/hello中的文件以查看模块的配置。 这些文件旨在为只读文件,就像.terraform中的其他内容一样。 不要修改它们。 Terraform 仅在您运行terraform init -upgrade或terraform get时才更新远程模块。.terraform/providers目录存储配置的所有提供程序的缓存版本。查看
.terraform/providers目录。 当您之前运行terraform init时,Terraform 从提供程序的源(由required_providers块定义)下载配置中定义的提供程序,并将其保存到各自的目录中,定义为[hostname]/[namespace]/[name]/[version]/[os_arch]。$ tree .terraform/providers .terraform/providers └── registry.terraform.io └── hashicorp ├── aws │ └── 6.2.0 │ └── darwin_arm64 │ ├── LICENSE.txt │ └── terraform-provider-aws_v6.2.0_x5 └── random └── 3.6.0 └── darwin_arm64 └── terraform-provider-random_v3.6.0_x5
更新提供程序和模块版本
在 terraform.tf 中,将 random 提供程序的版本更新到 3.6.1。
terraform.tf
terraform {
required_providers {
## ..
random = {
source = "hashicorp/random"
version = "3.6.1"
}
}
## ..
required_version = "~> 1.6"
}
在 main.tf 中,将 hello 模块的版本更新到 6.0.0。
main.tf
module "hello" {
source = "joatmon08/hello/random"
version = "6.0.0"
hello = "World"
second_hello = random_pet.instance.id
secret_key = "secret"
}
重新初始化配置
由于您已更新提供程序和模块版本,因此必须重新初始化配置,以便 Terraform 安装更新后的版本。
如果您在执行此操作之前尝试验证、计划或应用您的配置,Terraform 将提示您重新初始化。
$ terraform validate
╷
│ Error: Module version requirements have changed
│
│ on main.tf line 38, in module "hello":
│ 38: source = "joatmon08/hello/random"
│
│ The version requirements have changed since this module was installed and the installed version (4.0.0) is no longer acceptable. Run "terraform init" to
│ install all modules required by this configuration.
╵
重新初始化您的配置,以便 Terraform 将模块升级到与您在上一步中配置的新版本相匹配。但是,Terraform 会报告提供程序错误。
$ terraform init
Initializing the backend...
Initializing modules...
Downloading registry.terraform.io/joatmon08/hello/random 6.0.0 for hello...
- hello in .terraform/modules/hello
Initializing provider plugins...
- Reusing previous version of hashicorp/random from the dependency lock file
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v6.2.0
╷
│ Error: Failed to query available provider packages
│
│ Could not retrieve the list of available versions for provider hashicorp/random: locked
│ provider registry.terraform.io/hashicorp/random 3.6.0 does not match configured version
│ constraint >= 3.0.1, 3.6.1; must use terraform init -upgrade to allow selection of new
│ versions
│
│ To see which modules are currently depending on hashicorp/random and what versions are
│ specified, run the following command:
│ terraform providers
╵
请注意,Terraform 已下载更新的模块版本并将其保存在 .terraform/modules/hello 中。但是,Terraform 无法更新提供程序版本,因为新的提供程序版本与锁定文件中找到的版本冲突。
使用 -upgrade 标志重新初始化您的配置。这告诉 Terraform 将提供程序升级到与该提供程序的 required_version 块中的 version 属性匹配的最新版本。
$ terraform init -upgrade
Initializing the backend...
Upgrading modules...
- ec2-instance in modules/aws-ec2-instance
Downloading registry.terraform.io/joatmon08/hello/random 6.0.0 for hello...
- hello in .terraform/modules/hello
Initializing provider plugins...
- Finding hashicorp/aws versions matching "6.2.0"...
- Finding hashicorp/random versions matching ">= 3.0.1, 3.6.1"...
- Using previously-installed hashicorp/aws v6.2.0
- Installing hashicorp/random v3.6.1...
- Installed hashicorp/random v3.6.1 (signed by HashiCorp)
Terraform has made some changes to the provider dependency selections recorded
in the .terraform.lock.hcl file. Review those changes and commit them to your
version control system if they represent changes you intended to make.
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.
查看 .terraform/providers 目录结构。请注意,Terraform 已安装更新的 random 提供程序版本。
$ tree .terraform/providers -L 4
.terraform/providers
└── registry.terraform.io
└── hashicorp
├── aws
│ └── 6.2.0
└── random
├── 3.6.0
└── 3.6.1
打开锁定文件。请注意,random 提供程序现在使用版本 3.6.1。即使 random 提供程序在 .terraform/providers 中有两个版本,Terraform 始终会使用锁定文件中记录的版本。
.terraform.lock.hcl
## ...
provider "registry.terraform.io/hashicorp/random" {
version = "3.6.1"
constraints = ">= 3.0.1, 3.6.1"
hashes = [
"h1:a+Goawwh6Qtg4/bRWzfDtIdrEFfPlnVy0y4LdUQY3nI=",
## ...
"zh:e4aabf3184bbb556b89e4b195eab1514c86a2914dd01c23ad9813ec17e863a8a",
]
}
更新模块参数
由于您已更新提供程序和模块版本,请检查您的配置是否仍然有效。
$ terraform validate
╷
│ Error: Missing required argument
│
│ on main.tf line 37, in module "hello":
│ 37: module "hello" {
│
│ The argument "some_key" is required, but no definition was found.
╵
╷
│ Error: Missing required argument
│
│ on main.tf line 37, in module "hello":
│ 37: module "hello" {
│
│ The argument "hellos" is required, but no definition was found.
╵
╷
│ Error: Unsupported argument
│
│ on main.tf line 41, in module "hello":
│ 41: hello = "World"
│
│ An argument named "hello" is not expected here. Did you mean "hellos"?
╵
╷
│ Error: Unsupported argument
│
│ on main.tf line 42, in module "hello":
│ 42: second_hello = random_pet.instance.id
│
│ An argument named "second_hello" is not expected here.
╵
╷
│ Error: Unsupported argument
│
│ on main.tf line 44, in module "hello":
│ 44: secret_key = "secret"
│
│ An argument named "secret_key" is not expected here.
╵
新版本的 hello 模块需要与旧版本不同的参数。将整个 module "hello" 块替换为以下内容
main.tf
module "hello" {
source = "joatmon08/hello/random"
version = "6.0.0"
hellos = {
hello = random_pet.instance.id
second_hello = "World"
}
some_key = "secret"
}
重新验证您的配置。
$ terraform validate
Success! The configuration is valid.
现在您的 Terraform 工作区已初始化并准备好应用。
在以下情况下,使用 terraform init 初始化您的 Terraform 工作区
您创建新的 Terraform 配置并准备好使用它来创建工作区和配置基础设施。
您克隆包含 Terraform 配置的版本控制存储库,并准备好使用它来创建工作区和配置基础设施。
您添加、删除或更改现有工作区中模块或提供程序的版本。
您添加、删除或更改现有工作区中
backend或cloud块内的terraform块。
下一步
在本教程中,您使用本地和远程模块初始化了 Terraform 配置,探索了 .terraform 目录,并更新了您的提供程序和模块版本。这些步骤对于理解 terraform init 背后的机制至关重要。
有关本教程涵盖的主题的更多信息,请查看以下资源。
- 完成 锁定和升级提供程序版本 教程。
- 完成 将状态迁移到 HCP Terraform 教程。
- 了解更多关于
init的信息,请参阅 文档。