使用IBM Cloud构建的Terraform后端配置,其中包含HTTP类型
近期有一篇博客文章介绍了将IBM Cloud作为Terraform的后端使用的文档。
将 Terraform 状态存储在云对象存储中。
https://www.ibm.com/cloud/blog/store-terraform-states-cloud-object-storage
(谷歌翻译的链接)https://www-ibm-com.translate.goog/cloud/blog/store-terraform-states-cloud-object-storage?_x_tr_sl=en&_x_tr_tl=ja&_x_tr_hl=ja&_x_tr_pto=wapp的内容可以被简要地概括为:使用云对象存储存储Terraform状态。
我在下面提到了一种方法。
-
- AWS S3 backendの仕組みを流用して、Terraformの状態をIBMCloudObjectStorageに保管する
- httpバックエンドを利用して、サーバーレスTerraformバックエンドでロックとバージョン管理を追加する
在这里,关于后一种方法的步骤已经在 GitHub 上公开,所以我尝试使用了它,看看是什么样子的。
此外,尽管在本次情况下我们没有使用 local_file 资源,但是在 IBM Cloud 上还提供了一个名为 Schematics 的 Terraform 服务。在使用该服务时,后端会被自动管理。
给出一个选择只需要数一个前提
-
- IBM Cloudアカウント・タイプ
-
- 少なくともリソース・グループを作成したりする為、アカウント・タイプは「従量課金」である必要がありました。
- アカウント・タイプ「ライト (無料)」ではリソース・グループが1つのみの為、リソース・グループ追加のあたりで失敗しています。
追加说明:
您可以通过在010-prepare-backend/terraform.tfvars文件中添加以下内容,为轻量级计划的默认资源组(Default)创建后端(该功能尚未在轻量级计划中进行验证)。
resource_group="Default"
验证环境
使用本地的Terraform。
-
- Fedora Linux 35 (Workstation Edition)
- Terraform v1.1.9
步骤
请按照 README.md 的说明进行操作。
克隆用于验证的代码并编辑IBM Cloud定义信息。
$ git clone git@github.com:l2fprod/serverless-terraform-backend.git
...
$ cd serverless-terraform-backend
$ tree .
.
├── 010-prepare-backend # <= httpバックエンド構成用tf
│ ├── backend.js
│ ├── main.tf
│ └── terraform.tfvars.template
├── 020-use-backend. # <= httpバックエンドを利用するtf
│ ├── backend.tf
│ └── main.tf
├── LICENSE
├── README.md
├── terraform
│ ├── backend.tf
│ └── main.tf
└── xdocs
├── architecture.drawio
└── step-010.png
4 directories, 11 files
$ cd 010-prepare-backend
$ cp terraform.tfvars.template terraform.tfvars
$ vi terraform.tfvars
...
# IBM Cloud API key
ibmcloud_api_key="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# Prefix for the resources to be created
basename="terraform-backend"
# Region where to create resources
region="us-south"
-
- ibmcloud_api_key
-
- ユーザーやサービスID(「機能 ID」または「アプリケーション ID」のようなもの。ユーザーを表すためではなく、サービスの認証のために使用される。)に対応する、その権限での処理を行うためのkeyです。
- IBM Cloudのログイン後のページにおける上部の「管理」を選択するとプルダウンしてくるサブメニューから「アクセス(IAM)」を選択後、左のサブメニューの「APIキー」を選択し、青い「IBM Cloud APIキーの作成」ボタンを押して作成可能です。
-
- basename
-
- このソリューションで作成される資源などの名前の接頭語となります。
- 検証環境固有の問題の可能性もありますが、元のserverless-terraform-backendではterraform apply時に以下のエラーとなった為、ここではterraform-backendとしています。
│ Error: BucketAlreadyExists: The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again.
-
- region
- 特に編集していません。us-southはダラスとなります。
通过terraform apply创建一个用于定义后端服务和配置在使用后端时所需的环境变量的文件。
$ terraform init
...
$ terraform apply --auto-approve
...
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
$ ls
backend.js main.tf terraform.tfstate terraform.tfvars terraform.tfvars.template
$ awk '$1 == "resource"' main.tf | cat -n
1 resource "ibm_resource_group" "group" {
2 resource "ibm_resource_instance" "cos" {
3 resource "ibm_resource_key" "cos_key" {
4 resource "ibm_cos_bucket" "bucket" {
5 resource "ibm_function_namespace" "namespace" {
6 resource "ibm_function_package" "package" {
7 resource "ibm_function_action" "backend" {
8 resource "local_file" "backend-config" {
在IBM Cloud上,创建了一个存储tfstate文件的存储桶(terraform-backend-bucket),一个用于保存tfstate文件的Web动作(terraform-backend-package/backend),以及其他7个资源和一个本地文件。这个apply只是为了准备http后端,并且此时的terraform.tfstate文件被放置在本地。
使用 Terraform apply 进行测试,使用了由 HTTP 后端构成的。
$ cd ../020-use-backend/
$ ls
backend.env backend.tf main.tf
backend.env是一个用于设置http后端所需环境变量的脚本文件,该文件通过先前的terraform apply命令创建。
# TF_HTTP_ADDRESS points to the Cloud Functions action implementing the backend.
# It is reused for locking implementation too.
#
# env: name for the terraform state, e.g mystate, us/south/staging (.tfstate will be added automatically)
# versioning: set to true to keep multiple copies of the states in the storage
export TF_HTTP_ADDRESS="https://us-south.functions.cloud.ibm.com/api/v1/web/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/terraform-backend-package/backend?env=dev&versioning=true"
export TF_HTTP_PASSWORD="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# comment the following variables to disable locking
export TF_HTTP_LOCK_ADDRESS=$TF_HTTP_ADDRESS
export TF_HTTP_UNLOCK_ADDRESS=$TF_HTTP_ADDRESS
后端是通过以下的 tf 文件定义的。
基本上这里不需要更改。
terraform {
backend "http" {
# See backend.env for configuration of the following fields:
# address
# lock_address
# unlock_address
# password
# Do not change the following
username = "cos"
update_method = "POST"
lock_method = "PUT"
unlock_method = "DELETE"
skip_cert_verification = "false"
}
}
主要的tf文件
resource "local_file" "file" {
content = "hello"
filename = "hello.txt"
}
在设置环境变量之后,对使用云存储的后端应用程序进行测试。
$ source backend.env
如果是bash环境,也可以使用backend.env。
$ terraform init
Initializing the backend...
Successfully configured the backend "http"! Terraform will automatically
use this backend unless the backend configuration changes.
Initializing provider plugins...
- Finding latest version of hashicorp/local...
- Installing hashicorp/local v2.2.2...
- Installed hashicorp/local v2.2.2 (signed by HashiCorp)
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.
正在初始化后端…
成功配置后端”http”!Terraform 将自动使用这个后端,除非后端配置发生更改。
$ terraform apply --auto-approve
Acquiring state lock. This may take a few moments...
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:
# local_file.file will be created
+ resource "local_file" "file" {
+ content = "hello"
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "hello.txt"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
local_file.file: Creating...
local_file.file: Creation complete after 0s [id=aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d]
Releasing state lock. This may take a few moments...
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
$ ls
backend.env backend.tf hello.txt main.tf
按照预期,在本地没有创建terraform.tfstate文件。
$ cat hello.txt; echo
hello
从IBM Cloud的控制台中选择资源列表,以确认IBM Cloud上的对象存储。
从资源列表中选择创建的对象存储。
在桶中创建了tfstate文件。
目前有效的 tfstate 文件是 states/named/dev.tfstate。这里的dev是在backend.env中通过 export TF_HTTP_ADDRESS= 设置为 env=dev。
再次申请并检查对象存储。
$ terraform apply --auto-approve
Acquiring state lock. This may take a few moments...
local_file.file: Refreshing state... [id=aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d]
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
Releasing state lock. This may take a few moments...
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
以下是备份的版本/named/dev-2.tfstate和/named/dev-3.tfstate。
请查看010-prepare-backend/backend.js文件来了解逻辑。
如果不使用环境变量
可以直接在tf文件中编写。
是否可以写入密码等是令人犹豫的。
terraform {
backend "http" {
address = "https://us-south.functions.cloud.ibm.com/api/v1/web/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/terraform-backend-package/backend?env=dev&versioning=true"
lock_address = "https://us-south.functions.cloud.ibm.com/api/v1/web/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/terraform-backend-package/backend?env=dev&versioning=true"
unlock_address = "https://us-south.functions.cloud.ibm.com/api/v1/web/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/terraform-backend-package/backend?env=dev&versioning=true"
password = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
username = "cos"
update_method = "POST"
lock_method = "PUT"
unlock_method = "DELETE"
skip_cert_verification = "false"
}
}
是否可以反过来尝试将它逃逸到环境变量中尽可能多?
更加,额外添加
export TF_HTTP_USERNAME="cos"
export TF_HTTP_LOCK_METHOD="PUT"
export TF_HTTP_UNLOCK_METHOD="DELETE"
如果设定为
terraform {
backend "http" {
}
}
看起来不错。
印象
只要简单地运行一下就好了,之后就可以轻松了,但要写比想象中更长的逻辑才能实现,这真是令人烦恼。
Node.js 的版本
在`010-prepare-backend/main.tf`文件的第118行中设置了Node.js的版本。然而,目前不推荐使用Node.js 10,根据该文档(2022/05)的说明,推荐使用Node.js 16。
113 # the backend implementation
114 resource "ibm_function_action" "backend" {
115 name = "${ibm_function_package.package.name}/backend"
116 namespace = ibm_function_namespace.namespace.name
117 exec {
118 kind = "nodejs:16" # <= nodejs:10(非推奨)から書き換え
119 code = file("backend.js")
120 }
121 publish = true