Terraform 0.14 GA!したので新機能幾つか試してみた

2020.12.07

どうも、コンサルティング部の後藤です。

Terraform 0.14がGAしました!0.13リリースから割とあっと言う間だった気がします。
Announcing HashiCorp Terraform 0.14 General Availability

今回はそんな0.14の新機能を幾つか試してみました。

Terraformバージョン

Terraformダウンロードページから最新バージョン 0.14 が取得出来ました。
Download Terraform

$ terraform --version
Terraform v0.14.0

差分出力の簡潔化

嬉しい機能ですね!

以前までは、リソースの一部を変更してPlan等を行うと、変更するしないを問わず、全ての値が出力されており、結局どの部分が変更になるのか目を凝らして見ていました。

例として、既に作成済みのSubnetのCIDRを変更した際の出力を試してみました。

Terraform 0.13の頃

Terraform will perform the following actions:

  # aws_subnet.private_a must be replaced
-/+ resource "aws_subnet" "private_a" {
      ~ arn                             = "arn:aws:ec2:ap-northeast-1:074547258653:subnet/subnet-029f01bd2fd4893ac" -> (known after apply)
        assign_ipv6_address_on_creation = false
        availability_zone               = "ap-northeast-1a"
      ~ availability_zone_id            = "apne1-az4" -> (known after apply)
      ~ cidr_block                      = "10.1.1.0/24" -> "10.1.3.0/24" # forces replacement
      ~ id                              = "subnet-029f01bd2fd4893ac" -> (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
        map_public_ip_on_launch         = false
      ~ owner_id                        = "074547258653" -> (known after apply)
        tags                            = {
            "Name" = "tf13-test-subnet-a"
        }
        vpc_id                          = "vpc-08724f69c04ede339"
    }

変更されないavailability_zoneやvpc_id等が出力されていましたが、

Terraform will perform the following actions:

  # aws_subnet.private_a must be replaced
-/+ resource "aws_subnet" "private_a" {
      ~ arn                             = "arn:aws:ec2:ap-northeast-1:074547258653:subnet/subnet-00b24e463e8367bc7" -> (known after apply)
      ~ availability_zone_id            = "apne1-az4" -> (known after apply)
      ~ cidr_block                      = "10.1.1.0/24" -> "10.1.3.0/24" # forces replacement
      ~ id                              = "subnet-00b24e463e8367bc7" -> (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      ~ owner_id                        = "074547258653" -> (known after apply)
        tags                            = {
            "Name" = "tf14-test-subnet-a"
        }
        # (4 unchanged attributes hidden)
    }

スッキリしてますね!変更しない部分が4つあり、隠されていることも一目で分かりますね。

変数にsensitive属性の追加

以前まではOutputの属性として使用出来ていたSensitive属性ですが、0.14からは変数に対しても使用出来るようになりました。

Sensitive属性は機密性の高い値をTerraform CLIやTerraform Cloudの出力結果から隠してくれる機能になります。

試しにVPC CIDRの値を変数に起こし、sensitive属性を付与してみました。

variable "vpc_cidr" {
        type = string
        default = "10.1.0.0/16"
        sensitive = true
}

resource "aws_vpc" "vpc" {
        cidr_block = var.vpc_cidr

planで確認してみると、cidr_block部分がsensitiveと隠されている事が確認出来ました。

  # aws_vpc.vpc will be created
  + resource "aws_vpc" "vpc" {
      + arn                              = (known after apply)
      + assign_generated_ipv6_cidr_block = false
      + cidr_block                       = (sensitive)

outputと違い、変数自体を隠しているためかterraform showコマンドでもsensitiveで出力されていました。

$ terraform show
# aws_vpc.vpc:
resource "aws_vpc" "vpc" {

    ~~~
    cidr_block                       = (sensitive)
    ~~~

しかし、stateにはそのままの値が保存されていたため、stateの中身を見れてしまうユーザには機密性は担保出来ないようです。

プロバイダー依存関係のロックファイル追加

Terraformで使用するプロバイダー情報を記述したロックファイル.terraform.lock.hcl

が新たに追加されました。

このロックファイルはTerraform initを実行すると作成されるようです。

ロックファイルの中身は以下のようになっていました。

# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.

provider "registry.terraform.io/hashicorp/aws" {
  version = "3.20.0"
  hashes = [
    "h1:3M0q/GqB24RM5E1wIu23bEbChJ2RDVaM5lTLENB92Cc=",
    "zh:1b53d410c21332750be561092d412d83014fa0656e00f940944d2e7b07b1b9ec",
    "zh:307bf780790462fe547fe23f8e38a4c178437f3a9dd725f9aa63c6d8c6cbf25d",
    "zh:5818a978b9766b23a190716b85aad3a4731d33ddb8a81080cf3ef6e4bd68a003",
    "zh:5f68eb4779208e21d9657b9ff492aa5f6496efea7994bdec1d302f88b0b65f34",
    "zh:6028208a7b3738801cd9f3376efa40a1e55f4bb8184584f7387b08c054e43c4c",
    "zh:8130269e2d8c80ea9136dcd26cfeb4e1fac83bda4aab0db70f36651a7b22365d",
    "zh:9dd4a07beb89606e051b64ab05d75e1c1616389871a55065676b370aebaed8e5",
    "zh:b7194500db431ba862ea8008db56a5decececda1f904ed8842d2b0f1a04eea9d",
    "zh:ec214b7341137e6dd47754b843ed16fe3e1d32832537042ee81a64a3ccdbb4bd",
    "zh:ec2973e04f3cb853895e51f6ec56660574610b860ee3de669ccbb1f04d1089c9",
  ]
}

ロックファイルに3.20.0のバージョンが記載されている状態で、required_providersで異なるバージョンを指定してみました。

        required_providers {
                aws = "3.10.0"
        }

そして、再度terraform initを実行すると

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file

Error: Failed to query available provider packages

Could not retrieve the list of available versions for provider hashicorp/aws:
locked provider registry.terraform.io/hashicorp/aws 3.20.0 does not match
configured version constraint 3.10.0; must use terraform init -upgrade to
allow selection of new versions

エラーとして出力されました。

ロックファイルに記載されているバージョンと一致しておらず、プロバイダーのバージョンを変更するにはterraform init --upgradeを実行する必要があるそうです。

terraform init --upgradeを実行したところ、required_providersで指定したバージョンを取得し、ロックファイルが新しく設定されていました。

provider "registry.terraform.io/hashicorp/aws" {
  version     = "3.10.0"
  constraints = "3.10.0"

ロックファイル .terraform.lock.hcl を削除したところ、planを実行することが出来ずinitを要求されたため、Terraformを実行するには必須なファイルとなっているのでしょうか。

その他

その他にも幾つかアップデートがありました。
・Terraform 0.14 では、Linux ARM64 ビルドを公式にサポートしています。

・変数検証を使用しているユーザーのために、anyとallの2つの検証条件を追加しています。

・Terraformは、将来のバージョンのTerraformでも、互換性のあるステートファイルの読み書きをサポートするようになりました。これにより、Terraform 0.14.0のユーザーは、新しいステート・ファイル・フォーマットのバージョンが必要になるまで、将来のTerraformバージョンでステート・ファイルを共有することができるようになりました。

まとめ

Terraform0.14がGAされたので、幾つかの機能を試してみました。個人的には差分出力の簡易化が非常に嬉しいアップデートと思いました。それにしても0.14のリリース早かったですね。0.13すらあまり触る時間が無かったのは私だけでしょうか。。