使用 terraform-bundle 将执行 Terraform 所需的文件打包
2021年7月15日:补充
Terraform v1.0.0 版本结束了对 terraform-bundle 的开发。请参考下面的文章,了解替代方案。
Terraform打包工具是什么?
Terraform-bundle 是一个由 Terraform 社区维护的官方工具,用于创建包含特定版本的 Terraform 二进制文件和 Provider 二进制文件的 ZIP 文件捆绑包的命令行界面(CLI)。
一般而言,Terraform 在初始化过程中会从 HashiCorp 提供的 Terraform Registry 或其他外部注册表中安装 Provider 二进制文件。然而,在执行 Terraform 的主机受到组织或地区防火墙的限制时,可能无法访问外部注册表。
通过提前安装 Provider 二进制文件或使用可以从执行主机网络访问的私有注册表来解决上述问题。但只需执行 terraform-bundle,就可以打包并准备好 Terraform 执行所需的文件,这是使用 terraform-bundle 的好处之一。
通过提前在 Provider 计算机上安装二进制文件或使用可以从执行主机网络访问的私有注册表,解决上述问题是可能的。但是,借助 terraform-bundle,您只需运行它,就能将 Terraform 执行所需的文件打包成一个整体,这是使用 terraform-bundle 的优点。
如果你对Provider的安装规范感兴趣,可以参考《理解Terraform中的Provider安装过程(2021年2月版)》一文中的总结。
安裝方法
以下是安装最新版本 v0.14.7 的示例,截至2021年2月24日为止。
git clone --depth 1 -b v0.14.7 https://github.com/hashicorp/terraform.git
cd terraform
go install ./tools/terraform-bundle
建议将 terraform-bundle 的版本设置为与打包存档中的 Terraform 兼容的版本。例如,如果计划使用 Terrarom v0.14.x,则最好也使用 terraform-bundle v0.14.x。
设定文件
terraform-bundle 会根据包含 Terraform 二进制文件和供应商二进制文件的 HCL 格式的配置文件来创建捆绑包归档文件。以下是配置文件的示例。
terraform {
# Version of Terraform to include in the bundle. An exact version number
# is required.
version = "0.10.0"
}
# Define which provider plugins are to be included
providers {
# Include the newest "aws" provider version in the 1.0 series.
aws = {
versions = ["~> 1.0"]
}
# Include both the newest 1.0 and 2.0 versions of the "google" provider.
# Each item in these lists allows a distinct version to be added. If the
# two expressions match different versions then _both_ are included in
# the bundle archive.
google = {
versions = ["~> 1.0", "~> 2.0"]
}
# Include a custom plugin to the bundle. Will search for the plugin in the
# plugins directory and package it with the bundle archive. Plugin must have
# a name of the form: terraform-provider-*, and must be built with the operating
# system and architecture that terraform enterprise is running, e.g. linux and amd64.
customplugin = {
versions = ["0.1"]
source = "myorg/customplugin"
}
}
设置文件由terraform块和providers块组成。在terraform块中定义Terraform二进制版本,在providers块中以提供者名称为键定义版本和源2。版本定义遵循版本约束。
在bundle archive中,可以包含多个特定的Provider二进制文件的不同版本。在这种情况下,需要为Provider的版本定义多个值。通过包含多个版本,可以在每个.tf文件中使用不同版本的Provider。
创建打包存档的示例
在这个例子中,将使用以下的配置文件。
# Terraform バイナリは v0.14.7 とする
terraform {
version = "0.14.7"
}
providers {
# registry.terraform.io/hashicorp/aws の v3.29.1 をインストールする
# https://github.com/hashicorp/terraform-provider-aws
aws = {
versions = ["= 3.29.1"]
}
# registry.terraform.io/hashicorp/google の任意の3バージョンをインストールする
# https://github.com/hashicorp/terraform-provider-google
google = {
versions = ["= 3.56.0", "= 3.57.0", "= 3.58.0"]
}
}
指定一个配置文件,执行 terraform-bundle。
$ terraform-bundle --version
0.14.7
$ terraform-bundle package terraform-bundle.hcl
Fetching Terraform 0.14.7 core package...
Local plugin directory ".plugins" found; scanning for provider binaries.
No ".plugins" directory found, skipping local provider discovery.
- Finding hashicorp/aws versions matching "3.29.1"...
- Installing hashicorp/aws v3.29.1...
- Finding hashicorp/google versions matching "3.56.0"...
- Installing hashicorp/google v3.56.0...
- Finding hashicorp/google versions matching "3.57.0"...
- Installing hashicorp/google v3.57.0...
- Finding hashicorp/google versions matching "3.58.0"...
- Installing hashicorp/google v3.58.0...
Creating terraform_0.14.7-bundle2021022502_darwin_amd64.zip ...
All done!
一个名为 terraform_-bundle__ 的文件被创建,可以从文件名中获取 Terraform 版本、创建时间和所使用的主机的信息。
$ ls -l terraform_0.14.7-bundle2021022502_darwin_amd64.zip
-rwxr-xr-x 1 ryumyosh staff 128M Feb 25 11:46 terraform_0.14.7-bundle2021022502_darwin_amd64.zip
默认情况下,bundle archive 将包含在执行 terraform-bundle 命令的主机上操作系统和 CPU 架构兼容的 Terraform 二进制文件和 Provider 二进制文件。因此,请根据使用 bundle archive 的环境,在命令中加上 -os 和 -arch 选项,如下所示。
$ terraform-bundle package -os=linux -arch=amd64 terraform-bundle.hcl
那么,我们将解压缩已创建的捆绑存档并进行内容确认。
$ unzip terraform_0.14.7-bundle2021022502_darwin_amd64.zip
Archive: terraform_0.14.7-bundle2021022502_darwin_amd64.zip
inflating: plugins/registry.terraform.io/hashicorp/aws/3.29.1/darwin_amd64/terraform-provider-aws_v3.29.1_x5
inflating: plugins/registry.terraform.io/hashicorp/google/3.56.0/darwin_amd64/terraform-provider-google_v3.56.0_x5
inflating: plugins/registry.terraform.io/hashicorp/google/3.57.0/darwin_amd64/terraform-provider-google_v3.57.0_x5
inflating: plugins/registry.terraform.io/hashicorp/google/3.58.0/darwin_amd64/terraform-provider-google_v3.58.0_x5
inflating: terraform
确认发现bundle存档按照设置文件中的定义包含以下内容。
-
- Terraform: v0.14.7
-
- registry.terraform.io/hashicorp/aws: v3.29.1
- registry.terraform.io/hashicorp/google: v3.56.0、v3.57.0、v3.58.0
$ ls -l
total 424512
drwxr-xr-x 3 ryumyosh staff 96B Feb 25 11:47 plugins
-rwxr-xr-x 1 ryumyosh staff 79M Feb 25 11:46 terraform
-rw-r--r-- 1 ryumyosh staff 502B Feb 25 11:47 terraform-bundle.hcl
-rwxr-xr-x 1 ryumyosh staff 128M Feb 25 11:47 terraform_0.14.7-bundle2021022502_darwin_amd64.zip
$ ./terraform --version
Terraform v0.14.7
$ tree plugins
plugins
└── registry.terraform.io
└── hashicorp
├── aws
│ └── 3.29.1
│ └── darwin_amd64
│ └── terraform-provider-aws_v3.29.1_x5
└── google
├── 3.56.0
│ └── darwin_amd64
│ └── terraform-provider-google_v3.56.0_x5
├── 3.57.0
│ └── darwin_amd64
│ └── terraform-provider-google_v3.57.0_x5
└── 3.58.0
└── darwin_amd64
└── terraform-provider-google_v3.58.0_x5
由于插件目录的结构为<主机名>/<命名空间>/<类型>/<版本>/<目标>,所以无需额外操作,可以直接使用filesystem_mirror方式从存档档案中安装提供程序的文件。
# 適当な .tf ファイルを用意する
$ cat main.tf
terraform {
required_version = "= 0.14.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = "= 3.29.1"
}
google = {
source = "hashicorp/google"
version = "= 3.58.0"
}
}
}
# .terraformrc を用意せず -plugin-dir オプションを利用して
# filesystem_mirror 方式で Provider をインストールする
# Terraform バイナリは bundle archve に含まれているものを利用する
$ ./terraform init -plugin-dir plugins
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "3.29.1"...
- Finding hashicorp/google versions matching "3.58.0"...
- Installing hashicorp/aws v3.29.1...
- Installed hashicorp/aws v3.29.1 (unauthenticated)
- Installing hashicorp/google v3.58.0...
- Installed hashicorp/google v3.58.0 (unauthenticated)
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 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.
# bundle archive に含まれるファイルから Provider をインストールできた
$ tree -a .
.
├── .terraform
│ ├── plugin_path
│ └── providers
│ └── registry.terraform.io
│ └── hashicorp
│ ├── aws
│ │ └── 3.29.1
│ │ └── darwin_amd64 -> /Users/ryumyosh/Desktop/terraform/plugins/registry.terraform.io/hashicorp/aws/3.29.1/darwin_amd64
│ └── google
│ └── 3.58.0
│ └── darwin_amd64 -> /Users/ryumyosh/Desktop/terraform/plugins/registry.terraform.io/hashicorp/google/3.58.0/darwin_amd64
├── .terraform.lock.hcl
├── main.tf
├── plugins
│ └── registry.terraform.io
│ └── hashicorp
│ ├── aws
│ │ └── 3.29.1
│ │ └── darwin_amd64
│ │ └── terraform-provider-aws_v3.29.1_x5
│ └── google
│ ├── 3.56.0
│ │ └── darwin_amd64
│ │ └── terraform-provider-google_v3.56.0_x5
│ ├── 3.57.0
│ │ └── darwin_amd64
│ │ └── terraform-provider-google_v3.57.0_x5
│ └── 3.58.0
│ └── darwin_amd64
│ └── terraform-provider-google_v3.58.0_x5
├── terraform
├── terraform-bundle.hcl
└── terraform_0.14.7-bundle2021022502_darwin_amd64.zip
关于自定义提供商的支持
在 terraform-bundle 中,除了提供官方注册表上的 Provider,还可以将自定义 Provider 包含在 bundle 存档中。如果要包含自定义 Provider,则需要事先将名为 ////_ 的目录下的 terraform-provider- 的二进制文件放置在其中,并在执行 terraform-bundle 时指定该目录。
以下是创建一个包含自定义提供商 example.com / dev / myprovider 的 bundle 存档的示例。
# OS と ARCH は MacOS での実行を想定したものにしています
$ mkdir -p custom-plugins/example.com/dev/myprovider/0.1.0/darwin_amd64
# 今回は例なので Custom Provider といて空ファイルを配置しています
$ touch custom-plugins/example.com/dev/myprovider/0.1.0/darwin_amd64/terraform-provider-myprovider
# Custom Provider を含める場合にソースを
# <HOSTNAME>/<NAMESPACE>/<TYPE> 形式で定義する必要があります
$ cat terraform-bundle.hcl
terraform {
version = "0.14.7"
}
providers {
myprovider = {
versions = ["= 0.1.0"]
source = "example.com/dev/myprovider"
}
}
# 実行時に Custom Provider を配置したディレクトリを指定する
$ terraform-bundle package -plugin-dir custom-plugins terraform-bundle.hcl
Fetching Terraform 0.14.7 core package...
Local plugin directory "custom-plugins" found; scanning for provider binaries.
Found provider "example.com/dev/myprovider" in "custom-plugins". p
- Finding example.com/dev/myprovider versions matching "0.1.0"...
- Installing example.com/dev/myprovider v0.1.0...
Creating terraform_0.14.7-bundle2021022505_darwin_amd64.zip ...
All done!
# Custom Provider を含む bundle archive が作成できた
$ unzip -Z terraform_0.14.7-bundle2021022505_darwin_amd64.zip
Archive: terraform_0.14.7-bundle2021022505_darwin_amd64.zip
Zip file size: 35045518 bytes, number of entries: 2
-rw-r--r-- 2.0 unx 0 bX defN 21-Feb-25 14:14 plugins/example.com/dev/myprovider/0.1.0/darwin_amd64/terraform-provider-myprovider
-rwxr-xr-x 2.0 unx 83173328 bX defN 21-Feb-25 14:14 terraform
2 files, 83173328 bytes uncompressed, 35045092 bytes compressed: 57.9%
备考
由于v0.14.7中的go.sum存在问题,如果按照步骤执行安装,将会出现以下Go Modules的检查和校验错误。为了避免错误,您需要临时更新go.sum。这仅是为了安装目的的操作验证,因此在生产环境中,请使用已解决此问题的版本。
# そのままだと Go Modules のチェックサムエラーが発生する
$ go install ./tools/terraform-bundle
verifying github.com/hashicorp/go-getter@v1.5.1: checksum mismatch
downloaded: h1:LZ49OxqBBtdKJymlpX7oTyqGBQRg4xxQDyPW4hzoZqM=
go.sum: h1:lM9sM02nvEApQGFgkXxWbhfqtyN+AyhQmi+MaMdBDOI=
SECURITY ERROR
This download does NOT match an earlier download recorded in go.sum.
The bits may have been replaced on the origin server, or an attacker may
have intercepted the download attempt.
For more information, see 'go help module-auth'.
# 一時的に go.sum を更新する
$ sed -i '' -e 's/h1:lM9sM02nvEApQGFgkXxWbhfqtyN+AyhQmi+MaMdBDOI=/h1:LZ49OxqBBtdKJymlpX7oTyqGBQRg4xxQDyPW4hzoZqM=/' go.sum
# インストールする
$ go install ./tools/terraform-bundle
# 期待したバージョンがインストールできたことを確認する
$ terraform-bundle --version
0.14.7
可以通过使用terraform providers mirror命令下载Provider或者从官方网站下载Terraform二进制文件等操作,只需一个terraform-bundle命令即可完成。 ↩
在源代码中,定义的值将根据源地址的/进行设置。 ↩
请参考源代码https://github.com/hashicorp/terraform/blob/v0.14.7/tools/terraform-bundle/package.go#L289-L297。 ↩