LoginSignup
1
2

More than 3 years have passed since last update.

Terraform v0.9からv0.13まで駆け足でバージョンアップした話

Last updated at Posted at 2020-10-05

はじめに

久々に触ったTerraformを v0.9から v0.13 まで駆け足でバージョンアップしたので、どの辺にハマりどころがあったかメモとして残しておこうと思います。

実行環境について

  • tfenvを使って .terraform-version の書き換えによりバージョンアップする
  • tflintを使って記法をチェックする
  • tfファイル内のbackend設定は以下とし、 terraform init 時の引数でbackendの バケット名キー名リージョン名 を渡す
terraform {
  backend "s3" {
    dynamodb_table = "terraform-state-lock"
  }
}

Terraformのバージョンアップに関するまとめ

Terraformのバージョンアップについて、こちらで簡単にまとめます。
v0.11系までの段階的なバージョンアップについては過去に実績があったので、以下の通り段階的にバージョンアップを行ないました。

  • v0.9.8v0.9.11
    • まず同バージョンの最新に上げる
    • サクッと上げられる
  • v0.9.11v0.10.8
    • apply 方式に一部変更あり
    • サクッと上げられる
  • v0.10.8v0.11.14
    • apply 時、適用するか確認のメッセージが出力される様になる
    • サクッと上げられる
  • v0.11.14v0.12.28
    • HCL(HashiCorp Configuration Language) の大幅な変更があるため、公式ドキュメントのUpgrading to Terraform v0.12に従いアップグレードを行う必要がある
    • 手動で直さないといけない部分もあるので、結構大変
  • v0.12.28v0.13.2
    • サクッと上げられる

Terraformのバージョンアップについて

Terraform v0.9.8 から v0.9.11 へのバージョンアップ

v0.9.8から v0.9.11 はすんなり上がりました。

$ cat .terraform-version
0.9.11

$ terraform init \
    -backend-config=bucket=terraform.backend \
    -backend-config=key=terraform.tfstate \
    -backend-config=region=us-west-2 \
    /home/username/my-terraform/tf

$ terraform plan \
    -var-file=/home/username/my-terraform/conf/vars.tfvars \
    -refresh=true

$ terraform apply \
    -var-file=/home/username/my-terraform/conf/vars.tfvars \
    -refresh=true

Terraform v0.9.11 から v0.10.8 へのバージョンアップ

v0.9.11から v0.10.8 は一部 plan apply のやり方を変える必要がありました。

$ cat .terraform-version
0.10.8

$ terraform init \
    -backend-config=bucket=terraform.backend \
    -backend-config=key=terraform.tfstate \
    -backend-config=region=us-west-2 \
    /home/username/my-terraform/tf

$ terraform plan \
    -var-file=/home/username/my-terraform/conf/vars.tfvars \
    -refresh=true

ここまで実行したところ、以下のエラーとなりました。

Failed to load backend: Initialization required. Please see the error message above.

どうやら v0.9 系までは plan apply 時に tf ファイルのディレクトリを指定しなくとも動きましたが、 v0.10 系からは明示的に指定が必要になった様です。
以下の通り、引数で tf ファイルのディレクトリを指定してやることで上手く動きました。

$ terraform plan \
    -var-file=/home/username/my-terraform/conf/vars.tfvars \
    -refresh=true \
    /home/username/my-terraform/tf

$ terraform apply \
    -var-file=/home/username/my-terraform/conf/vars.tfvars \
    -refresh=true \
    /home/username/my-terraform/tf

また、一部の iam_policy では、明示的に false 設定を入れていなかったリソースに対して false 設定を入れる差分が出力されました。
false のままで問題なかったためそのまま適用しました。

 ~ aws_iam_role.test_role
      force_detach_policies: "" => "false"

Terraform v0.10.8 から v0.11.14 へのバージョンアップ

v0.10.8から v0.11.14 はすんなり上がりました。

$ cat .terraform-version
0.11.14

$ terraform init \
    -backend-config=bucket=terraform.backend \
    -backend-config=key=terraform.tfstate \
    -backend-config=region=us-west-2 \
    /home/username/my-terraform/tf

$ terraform plan \
    -var-file=/home/username/my-terraform/conf/vars.tfvars \
    -refresh=true \
    /home/username/my-terraform/tf

$ terraform apply \
    -var-file=/home/username/my-terraform/conf/vars.tfvars \
    -refresh=true \
    /home/username/my-terraform/tf

v0.11 系から、リソースに変更がある場合は apply 実行時に差分が出力されたあと、以下のメッセージが出力されるようになります。
差分を確認して問題がなければ yes を入力して apply を確定します。

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

Terraform v0.11.14 から v0.12.28 へのバージョンアップ

v0.12 系から HCL の大幅な変更があり、何もせずにそのままバージョンだけ上げるのは難しいようです。
公式ドキュメントのUpgrading to Terraform v0.12に従いアップグレードしていきます。

v0.12 系へのバージョンアップの流れ

  1. Terrafrom v0.11.14 までバージョンを上げる
  2. アップグレード前のチェックリスト対応をする
    1. Terraform v0.11.14 では terraform 0.12checklist というヘルパーコマンドが追加されており、アップグレード前に対応すべき項目を知ることができる
    2. チェックリストに従い、 tf ファイルの修正を行う
  3. Terraform v0.12 へアップグレードする
  4. terraform 0.12upgrade でモジュールのアップグレードを行う
    1. Terraform v0.12 では terraform 0.12upgrade というヘルパーコマンドが追加されており、Terraform v0.11 用に書かれたモジュールを v0.12 用に更新することができ

terraform 0.12checklist に関する注意事項

数字で始まる名前のモジュール名についてはチェックリストツールで自動検出できない様です。
Addendum: Invalid module namesに記載の通り、Terraform v0.11.14 リリース時点でTerraformチームが認識していなかった事象とのことです。

実際にバージョンアップした時の様子

1. Terrafrom v0.11.14 までバージョンを上げる

これは前段のバージョンアップで実施済みです。

$ cat .terrafrom-version
0.11.14

2. アップグレード前のチェックリスト対応をする

怖いぐらいすんなり通りました・・・。

$ terraform 0.12checklist /home/username/my-terraform/tf
Looks good! We did not detect any problems that ought to be
addressed before upgrading to Terraform v0.12.

This tool is not perfect though, so please check the v0.12 upgrade
guide for additional guidance, and for next steps:
    https://www.terraform.io/upgrade-guides/0-12.html

3. Terraform v0.12 へアップグレードする

Terraform v0.12 へアップグレードするため、.terraform-version を書き換えて terraform init していきます。

$ vi .terraform-version
$ cat .terrafrom-version
0.12.28

$ terraform init \
    -backend-config=bucket=terraform.backend \
    -backend-config=key=terraform.tfstate \
    -backend-config=region=us-west-2 \
    /home/username/my-terraform/tf

terraform init 時に以下のエラーが出力されました。

Error: Unexpected comma after argument
Error: Unexpected comma after argument

  on ../../home/username/my-terraform/tf/iam_policy.tf line 4, in data "aws_iam_policy_document" "sample":
   4:         effect = "Deny",

Argument definitions must be separated by newlines, not commas. An argument
definition must end with a newline.

ポリシードキュメントの effect 定義の終端に ,(カンマ) が入っているのが駄目になった様です。
終端の ,(カンマ) を削除して terraform init したところ無事通りました。

4. terraform 0.12upgrade でモジュールのアップグレードを行う

terraform 0.12upgradetf ファイルをTerraform v0.12 向けにアップグレードします。

$ terraform 0.12upgrade /home/username/my-terraform/tf

<snip>

This command will rewrite the configuration files in the given directory so
that they use the new syntax features from Terraform v0.12, and will identify
any constructs that may need to be adjusted for correct operation with
Terraform v0.12.

We recommend using this command in a clean version control work tree, so that
you can easily see the proposed changes as a diff against the latest commit.
If you have uncommited changes already present, we recommend aborting this
command and dealing with them before running this command again.

Would you like to upgrade the module in ../../home/livesen/mb-terraform-jsen/accounts/tf?
  Only 'yes' will be accepted to confirm.

  Enter a value: yes

-----------------------------------------------------------------------------

Upgrade complete!

The configuration files were upgraded successfully. Use your version control
system to review the proposed changes, make any necessary adjustments, and
then commit.

無事アップグレードできたので、試しに plan してみます。

$ terraform plan \
    -var-file=/home/username/my-terraform/conf/vars.tfvars \
    -refresh=true \
    /home/username/my-terraform/tf

-var-filetfvars ファイルから変数を読み込んでいるので、以下の通り一部の初期化していない変数で Warning が出力されるようです。
こちらについては variables.tf ファイルなどで変数を定義しておきます。

Warning: Value for undeclared variable

The root module does not declare a variable named "env_name" but a value was
found in file "/home/livesen/mb-terraform-jsen/config/playground/env.tfvars".
To use this value, add a "variable" block to the configuration.

Using a variables file to set an undeclared variable is deprecated and will
become an error in a future release. If you wish to provide certain "global"
settings to all configurations in your organization, use TF_VAR_...
environment variables to set these instead.

Warning: Value for undeclared variable

The root module does not declare a variable named "az2" but a value was found
in file "/home/livesen/mb-terraform-jsen/config/playground/env.tfvars". To use
this value, add a "variable" block to the configuration.

Using a variables file to set an undeclared variable is deprecated and will
become an error in a future release. If you wish to provide certain "global"
settings to all configurations in your organization, use TF_VAR_...
environment variables to set these instead.

Warning: Value for undeclared variable

The root module does not declare a variable named "vpc_cidr_16" but a value
was found in file
"/home/livesen/mb-terraform-jsen/config/playground/env.tfvars". To use this
value, add a "variable" block to the configuration.

Using a variables file to set an undeclared variable is deprecated and will
become an error in a future release. If you wish to provide certain "global"
settings to all configurations in your organization, use TF_VAR_...
environment variables to set these instead.

Warning: Values for undeclared variables

In addition to the other similar warnings shown, 3 other variable(s) defined
without being declared.

Releasing state lock. This may take a few moments...

最後に、試しに apply してみましたが問題なく通りました。

$ terraform apply \
    -var-file=/home/username/my-terraform/conf/vars.tfvars \
    -refresh=true \
    /home/username/my-terraform/tf

5. おまけ その1: 一部でterraform 0.12upgrade が上手くいかずに手動で書き換えた設定とエラーメッセージ

実は一部のコードについては terraform 0.12upgrade でアップグレードできなかったため手動で書き換えた箇所がありました。
その際に出力されたエラーメッセージについてまとめます。
エラーについては、 plan 時と tflint で出力されたものに関してまとめています。

Error: Unsupported block type
Error: Unsupported block type

  on ../../home/username/my-terraform/tf/dmz_network.tf line 6, in resource "aws_vpc" "dmz":
   6:     tags {

Blocks of type "tags" are not expected here. Did you mean to define argument
"tags"? If so, use the equals sign to assign it a value.

tagsの記法が以下の記法でないと駄目になった様です。

tags = {
   "Name" = "Sample"
}
Incorrect attribute value type
Error: Incorrect attribute value type

  on ../../home/username/my-terraform/tf/dmz_network.tf line 84, in resource "aws_security_group" "dmz":
  84:     cidr_blocks = ["${var.vpc_network_address}", "${var.own_ips}"]

Inappropriate value for attribute "cidr_blocks": element 1: string required.

以前 cidr_blocks に設定する値は stringlist 形式が混在していても問題なかったのですが、 string 型の list として list(string) を指定するようになったようです。

string 型を維持する場合は以下の様に concatを使って listの結合を行います。

cidr_blocks = concat(var.own_ips, [var.vpc_network_address])

今回は var.vpc_network_address の参照箇所がここだけだったので型を string 型から list 型に変更して以下の記載としました。

cidr_blocks = concat(var.own_ips, var.vpc_network_address)
Warning: Quoted type constraints are deprecated

変数を宣言する際、 type の指定は "(ダブルクォート)" が不要になった様です。

Warning: Quoted type constraints are deprecated

  on ../../home/username/my-terraform/tf/variables.tf line 2, in variable "env_site_url":
   2:   type    = "map"

Terraform 0.11 and earlier required type constraints to be given in quotes,
but that form is now deprecated and will be removed in a future version of
Terraform. To silence this warning, remove the quotes around "map" and write
map(string) instead to explicitly indicate that the map elements are strings.

以下の様に修正しました。

    type    = map
Warning: Interpolation-only expressions are deprecated

他のリソース情報を参照する際は "${}" で括らない記法になった様です。

Warning: Interpolation-only expressions are deprecated

  on ../../home/username/my-terraform/tf/iam.tf line 41, in resource "aws_iam_policy_attachment" "sample_policy_attach":
  41:   policy_arn = "${aws_iam_policy.sample.arn}"

Terraform 0.11 and earlier required all non-constant expressions to be
provided via interpolation syntax, but this pattern is now deprecated. To
silence this warning, remove the "${ sequence from the start and the }"
sequence from the end of this expression, leaving just the inner expression.

Template interpolation syntax is still used to construct strings from
expressions when the template includes multiple interpolation sequences or a
mixture of literal strings and interpolations. This deprecation applies only
to templates that consist entirely of a single interpolation sequence.

6.おまけ その2: 新記法でなくとも tflintterraform init, terraform plan 時に特に何もエラーが出ない記法

tagsで変数を使っている箇所

変数の参照で、以下の記法でも特に問題ないようです。

tags = {
    "Name"       = "AnyBatch"
    "Role"       = "Batch"
    "Env"        = "${var.env_label}"
}

他と記法を合わせる意味で、今回は以下の通り記載しました。
※ただし、VSCodeのシンタックスハイライトが効かなくなるので好みによりそうです

tags = {
    "Name"       = "AnyBatch"
    "Role"       = "Batch"
    "Env"        = var.env_label
}
listで変数を使っている箇所

listで記載するものについて、AWSリソースによっては特に何も指摘されないものがありました。

resource "aws_cloudfront_distribution" "promotion" {
<snip>
  aliases = ["${var.promotion_url[var.env_name]}"]
<snip>

こちらも他と記法を合わせる意味で、今回は以下の通り記載しました。

resource "aws_cloudfront_distribution" "promotion" {
<snip>
  aliases = [var.promotion_url[var.env_name]]
<snip>

その他、以下の項目でも、リスト内の変数参照に "${}" が付いていても特に何も指摘されませんでした。

  • aws_network_interface
    • vpc_security_group_ids
  • aws_instance
    • vpc_security_group_ids

v0.12.28→v0.13.2

v0.12.28から v0.13.2 へ上げる際、一部で以下の差分が出ました。

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
 <= read (data resources)

Terraform will perform the following actions:

  # data.aws_acm_certificate.promotion will be read during apply
  # (config refers to values not yet known)
 <= data "aws_acm_certificate" "promotion"  {
        arn         = "arn:aws:acm:us-east-1:************:certificate/********-****-****-****-************"
        domain      = "*.stg.sample.domain"
      ~ id          = "2020-09-17 06:55:01.618103996 +0000 UTC" -> "2020-09-17 06:57:05.718177187 +0000 UTC"
        most_recent = false
        tags        = {}
    }

Plan: 0 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

手動で作成した ACMdata sourceとして読み込んでいる場合、 idの部分が適用時のものに更新される様です。
add でも change でもない差分らしく、plan結果のカウントは全て 0 になります。
そして、一度 apply しても plan する度に差分として出力されます。
terraform-provider-awsのコードを読んでみると

d.SetId(time.Now().UTC().String())

と書いてありますね・・・。
data source を読み込む度に、読み込んだ日時に更新する実装になっている様です。
取り急ぎ、今回のバージョンアップに直接影響しないので別途対応としました。
※2020/10/14現在、こちらのコミットにより修正されています
https://github.com/terraform-providers/terraform-provider-aws/commit/9d9bcbd8931b628b8213541dfc61809623a911ed#diff-a71cf6c5f1fdbb1915e591e3ca8872ac05e1b7a650a61034b55b40f8da061bc3

$ cat .terraform-version
0.13.2

$ terraform init \
    -backend-config=bucket=terraform.backend \
    -backend-config=key=terraform.tfstate \
    -backend-config=region=us-west-2 \
    /home/username/my-terraform/tf

$ terraform plan \
    -var-file=/home/username/my-terraform/conf/vars.tfvars \
    -refresh=true \
    /home/username/my-terraform/tf

$ terraform apply \
    -var-file=/home/username/my-terraform/conf/vars.tfvars \
    -refresh=true \
    /home/username/my-terraform/tf

おわりに

以上で 2020/10/02 時点の最新バージョン v0.13.2 まで上げ終わりました。
実行する環境によってハマりどころが変わるとは思いますが、バージョンアップされる方の助けになればと思います。

参考リンク

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2