Terraform 0.12がリリースされたのでアップグレードしてみた
こんにちは佐伯です。本日待望のTerraform 0.12がリリースされました!
ということで、アップグレードガイドに沿ってTerraform 0.11からアップグレードしてみました。
アップグレードガイド
はじめに、アップグレードガイドは以下リンクです。アップグレードする前に読みましょう。
アップグレードプロセス
アップグレードの流れとしては以下の通りです。
- Terraform 0.11.14へアップグレード
- アップグレード前チェックリストの実行
- Terraform 0.12へのアップグレード
- Terraformコードの修正
- モジュールのアップグレード
事前準備
Terraform stateファイルのバックアップ
Terraform stateファイルをRemote Backendで管理しており、Remote Bacckend側の機能(S3のバージョニング機能など)でバックアップできている場合は特にバックアップを取得する必要はありませんが、もしローカルで管理しているのであればバックアップを取得しましょう。
TerraformコードのGit管理
Terraform 0.12ではHCL(HashiCorp Configuration Language)の構文自体が変わっており、Terraform 0.11との完全な互換性はありません。アップグレードするにあたって色々変更が必要になります。もしかするとTerraform 0.11に戻したくなることもあるかもしれません。もしGitで管理していない場合は、その時のためにコードはGitで管理しておきましょう。
tfenvのインストール
必須ではないですがアップグレード作業中にTerraformバージョンを何度か切り替える必要があるので、tfenvをインストールしておくとバージョン切替が楽にできて便利です。
やってみた
Terraform 0.11.14へアップグレード
これまでTerraform 0.11を使用しているのであればそのままバージョンアップすることができると思います。それ以前のバージョンを利用している場合はバージョンに応じてアップグレードガイドを確認しながらTerraform 0.11までバージョンアップします。
Terraform 0.9→0.11まで変更点については以下エントリにもまとめています。
tfenvでは以下のコマンドを実行してTerraform 0.11.14に変更します。
$ tfenv install 0.11.14 # Terraform 0.11.14のダウンロード $ tfenv use 0.11.14 # Terraform 0.11.14へスイッチ $ terraform -v Terraform v0.11.14
アップグレード前チェックリストの実行
Terraform 0.11.14では0.12checklist
サブコマンドが追加されており、このコマンドを実行してTerraform 0.12にアップグレードする前に事前にチェックを行います。
terraform 0.12checklist
コマンドを実行する前にterraform init
で必要なプロバイダープラグインをインストール、terraform apply
でTerraform stateファイルとコードに差異が無いかを確認します。
その後、terraform 0.12checklist
コマンドでチェックを実施します。このコマンドを実行することで以下の項目がチェックされます。
- Terraform 0.12と互換性のないプロバイダーバージョンを使用していないかチェック
- Terraform 0.12では使用できなくなった数字で始まるリソース名やプロバイダエイリアス名がないかチェック
- 外部モジュールが上記の項目に該当しないかチェック
特に問題なければ以下のメッセージが出力されます。
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
Terraform 0.12へのアップグレード
Terraform 0.12へアップグレードします。こちらも初回にterraform init
を実行します。Terraform 0.12と互換性のないコードが存在している場合は、以下のメッセージが出力されるのでコードの変更が必要となります。
Terraform has initialized, but configuration upgrades may be needed. Terraform found syntax errors in the configuration that prevented full initialization. If you've recently upgraded to Terraform v0.12, this may be because your configuration uses syntax constructs that are no longer valid, and so must be updated before full initialization is possible. Terraform has installed the required providers to support the configuration upgrade process. To begin upgrading your configuration, run the following: terraform 0.12upgrade To see the full set of errors that led to this message, run: terraform validate
Terraformコードの修正
Terraform 0.12には0.12upgrade
サブコマンドが追加されており、このコマンドを実行することでTerraform 0.12の構文で置換が行われます。メッセージにもあるように作業中のワーキングツリーなどではなく、別途ブランチを作成するなどしましょう。
$ terraform 0.12upgrade 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 the current directory? Only 'yes' will be accepted to confirm. Enter a value: yes
terraform 0.12upgrade
コマンド実行後、以下メッセージ出力であれば置換が成功しています。
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.
WARNINGメッセージが出力された場合は手動で修正する必要があります。terraform 0.12upgrade
実行後のメッセージにも出力されますが、コード自体にTF-UPGRADE-TODO:
といったコメント行が追記されます。git grep TF-UPGRADE-TODO
コマンド等で該当箇所を検索し、メッセージを読んで修正します。
私が遭遇したパターンでは、アップグレードガイドにも記載のある変数の型制約で手動変更が必要でした。aws_waf_ipsetのip_set_descriptorsの値をlist of mapの形で変数に入れて設定していました。
variable "ipset" { type = "list" default = [ { value = "1.1.1.1/32", type="IPV4" }, { value = "2.2.2.2/32", type="IPV4" }, ] } resource "aws_waf_ipset" "whitelist_ipset" { name = "WhitelistIpset" ip_set_descriptors = "${var.ipset}" }
terraform 0.12upgrade
実行後はfor_each
でループする形に自動的に変更されてました。しかし、コメントが追記されており変数の型がlistのため、キーを指定出来ていないようでした。
variable "ipset" { type = list(string) default = [ { value = "1.1.1.1/32", type="IPV4" }, { value = "2.2.2.2/32", type="IPV4" }, ] } resource "aws_waf_ipset" "whitelist_ipset" { name = "WhitelistIpset" dynamic "ip_set_descriptors" { for_each = var.ipset content { # TF-UPGRADE-TODO: The automatic upgrade tool can't predict # which keys might be set in maps assigned here, so it has # produced a comprehensive set here. Consider simplifying # this after confirming which keys can be set in practice. type = ip_set_descriptors.value.type value = ip_set_descriptors.value.value } } }
変数のタイプをlist(object)に変更することでterraform plan
でエラーが発生しなくなりました。
variable "ipset" { type = list(object({ value = string type = string })) default = [ { value = "1.1.1.1/32", type="IPV4" }, { value = "2.2.2.2/32", type="IPV4" }, ] } resource "aws_waf_ipset" "whitelist_ipset" { name = "WhitelistIpset" dynamic "ip_set_descriptors" { for_each = var.ipset content { type = ip_set_descriptors.value.type value = ip_set_descriptors.value.value } } }
と、このように手動で修正な箇所はコードによって様々な理由があります。それらについてもアップグレードガイドに記載がありますので確認ください。
モジュールのアップグレード
モジュールがTerraform 0.12に対応していない場合、モジュールの更新も必要です。Terraform Module RegistryやGitHubからダウンロードしている場合、PRを送るかTerraform 0.12への対応を待つしかないと思いますが、モジュールを自作している場合は同様にterraform 0.12upgrade
の実行、terraform validate
を行い正常に動作するか確認する必要があります。
最後に
今回はTerraform 0.12でどういった変更があったには触れていませんが、破壊的な変更はあるものの個人的には新しい構文はかなりスッキリ書けるようになった印象があります。リリースされたばかりなので細かな修正が発生する可能性はありますが、アップグレードを検討してみてはいかがでしょうか。