[レポート]Announcing Terraform 0.14

2021.01.18

Terraform 0.14に関してのWebinarを聴講したのでレポートします。(一ヶ月以上前のwebinarですが…)

Webinar 概要

Terraform 0.14 is all about perfecting workflow. Our latest version enables practitioners to leverage more predictability and reliability in infrastructure automation. In meeting this goal, we’ve also added some key features to help organizations heavily invested in Terraform, continue to mature. Additionally, updates included in this release will be equally valuable to practitioners and teams just starting their journey with infrastructure as code. In this webinar, Terraform OSS Product Manager Petros Kolyvas and Technical Product Marketing Manager Kyle Ruddy will walk you through new Terraform features such as concise diff, sensitive variables, and the provider dependency lock file.

(筆者訳) Terraform 0.14 はワークフローを完璧にするためのツールです。最新バージョンでは、インフラストラクチャの自動化において、より予測可能性と信頼性を高めることができます。この目標達成のため、Terraformに多大な投資をしている組織が成熟を続けることを支援する、いくつかの重要な機能を追加しました。加えて、このリリースに含まれるアップデートは、infrastructure as codeの旅を始めたばかりの人やチームにも同等に価値あるものとなるでしょう。このwebinerではTerraform OSS プロダクトマネージャーであるPetros KolyvasとテクニカルプロダクトマーケティングマネージャーKyle RuddyがTerrafromの新機能である簡潔なdiff、sensitive variables、provider dependency ロックファイルについて説明します。

スピーカー

  • Kyle Ruddy - Product Marketing at HashiCorp
  • Petros Kolyvas - Product Manager at HashiCorp

Webinar 内容

最初に喋るKyle Ruddyさんが新機能の概要説明、次のPetros Kolyvasさんがデモ実演、その後QAという流れでした。本レポートでは構成を変更し、機能毎に説明とデモをまとめてレポートします。Webinarで触れられていない点を私が追記した内容も含まれています。QAはすみません、私の英語力不足で理解が及ぼなかったので割愛させていただきます。

Concise Diff(簡潔な差分)

Terraformがリソースの何を変更するのか、より簡潔にわかるようになりました。

デモ

Azure Providerを使ったデモをします。

azurerm_linux_virtual_machineのNICを追加する変更をやってみて、version 0.13と0.14でdiffの出方がどう変わるか実演します。

コードの変更点 before

nic-before

after

nic-after

version 0.13

まずはversionの確認です。 013-version terraform planしてみます。 013-diff network_interface_idsattributeのlistに一要素追加されていることがわかります。が、他の変更が無いattributesもズラッと表示されてますね。

version 0.14

では同じ変更を0.14でやるとどうなるか。まずはversionの確認です。 014-version terraform planしてみます。 014-diff network_interface_ids部分の差分が表示されるのは同じです。注目すべきはその下の#(16 unchanged attributes hidden)#(2 unchanged blocks hidden) の部分です。こんな感じで変更がないattributesやblocksは隠蔽化され、差分がよりわかりやすくなりました。

Sensitive values in Terraform

変数値

sensitive

引数sensitiveをtrueと設定した変数は、Terraform 実行時の出力結果として表示されなくなります。

これは、Terraformコントロール下のシステム外に変数値の流出を防ぐための機能です。例えば、Terraformのアウトプットを何らかのロギングシステムやVCS(バージョンコントールシステム)に記録している場合、この機能が役立つでしょう。

ただしこの機能は、Stateファイルにその変数値が書き込まれることを防ぐものではありません。依然としてSteteファイルへのアクセス権の設定は慎重に行ないましょう。

デモ

以下の様に、storage_typeadmin_usernameという変数(Input Variables)のsensitive引数をtrueとしました。 sensitive-demo terraform planします。 storage_type-sensitive storage_type変数を使った、storage_account_typeというattributeの値が (sensitive)と隠蔽化されています。Warningも表示されていますね。

admin_username-sensitive 同様にadmin_usernameも隠蔽化されています。

providerリソースの引数値

providerがsensitiveと定義したリソース引数値、これをより露出しないように設定することができます。

たとえば以下のようにTerraformのコードを書いたとします。aws_db_instanceはRDSのことです。 そこで指定したpasswordの値をoutputで使っています。

resource "aws_db_instance" "default" {
  allocated_storage    = 20
  storage_type         = "gp2"
  engine               = "mysql"
  engine_version       = "5.7"
  instance_class       = "db.t2.micro"
  name                 = "mydb"
  username             = "foo"
  password             = "foobarbaz"
  parameter_group_name = "default.mysql5.7"
}

output password {
  value = aws_db_instance.default.password
}

以下がこのコードのterraform planの結果です。 aws_db_instance リソース内のpasswordの値は「(sensitive value)」として隠蔽されています。これはaws providerがこの引数値をsensitiveと定義しているからです。 db-password

しかし、outputの方はそのまま出力されてしまっています。 password-as-output これがデフォルトの挙動です。つまり、providerがsensitiveと定義したリソース引数値は、引数値はsensitiveとして扱われ隠蔽されますが、その値を参照したoutput値ではそのまま(=隠蔽されず)表示されます。

この挙動を変更する機能provider_sensitive_attrsが 0.14からexperimental featureつまり実験的機能として追加されました。experimental featureは今後stable releaseされなかったり、されたとしても破壊的な変更が入る場合がりますので、まだプロダクション環境で使用するのは控えたほうがよいでしょう。

で、どういう変更かというと、先程terraform planで表示されてしまったoutput値、つまり providerでsensitiveと定義された引数値を参照しているoutput値があった場合、エラーにするというものです。

先程と同じコードをprovider_sensitive_attrsを有効化した状態で、terraform planしてみます。すると以下のようにエラーになります。 sensitive-error

エラーを解消するには、output値もsensitive値であると定義します。

output password {
  value = aws_db_instance.default.password
  sensitive = true
}

こうすると、「(sensitive value)」と隠蔽化された状態でoutput値もterraform planの結果に現れます。 db-password-sensitive

なお、この機能provider_sensitive_attrsは![experimental featureであり、experimental featureはオプトインの機能であるので、terraformブロックで以下のように明示的に有効化する必要があります。

terraform {
  required_version = "~> 0.14.3"
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "3.23.0"
    }
  }

  experiments = [provider_sensitive_attrs]
}

現在はexperimental featureですが、今後のバージョンアップでデフォルトの挙動にしていきたいとの考えだそうです。

Provider Lockfile

Providerのバージョンを「ピン留め」する機能です。terraform init時に.terraform.lock.hclというロックファイルが作成されます。この中には、使用しているproviderのバージョンやそのハッシュ値が記録されます。ここに記録されているバージョンやハッシュ値が異なるproviderを使おうとするとエラーになります。そうやって毎回のterraformコマンド実行時に、同じproviderを利用していることを保証する機能です。このファイルはGit等のバージョン管理システムで管理するようにしましょう。

バージョンを上げたい、providerを追加したいといった際はterraform init -upgradeでロックファイルも更新することができます。

また、terraform providers lockというコマンドも追加されました。 provider-lock これは、特定のケースにおいて上記terraform initでロックファイルを作成できない場合に使います。たとえば Network MirrorやFilesystem Mirrorを使ってProviderをインストールしている場合、providerのオリジンレジストリにアクセスできないためにハッシュが生成できない場合があります。そういった場合にこのコマンドを使って、オリジンレジストリにアクセスしてハッシュを作成しロックファイルを更新することができます。

デモ

まずterraform provider lockコマンドを実行してみます。 demo-terraform-provider-lock ロックファイルが作成されます。中身を見てみます。

Azureのprovider(azurerm)がversion 2.35.0であることがわかります。 demo-lockfile 注目すべきはその下constraints = ">= 2.0.0" の部分です。これはProviderの設定で以下のように書いたためこのように吐かれます。 demo-azurerm この状態で terraform initを実行してみましょう。 demo-init

Azureのproviderはversion 2.35.0がインストールされます。これは先程のロックファイルに2.35.0が書かれているからです。

では、constraints = ">= 2.0.0"を満たす最新のバージョンにアップデートしたい場合はどうするか。terraform init -upgradeを使います。 demo-upgrade 2.39.0がインストールされましたね。

ロックファイルも更新されました。
demo-lockfile-after

このように、ロックファイルを使うことで、providerが新バージョンをリリースしても、それがあなたを驚かす(=勝手にアップデートされる)ことはなくなりました。

New Conditions for variable validations

  • alltrue Function
    • listを引数に持ち、その中全ての要素がtrueである場合にtrueを返す。(引数が空の場合もtrueになる)
  • anytrue Function
    • listを引数に持ち、その中のいずれかの要素がtrueであればtrueを返す。(引数が空の場合はfalseを返す)

デモ

locationという変数を用意しました。この変数を使ってリソースがデプロイされるリージョンを設定します。が、デプロイ先をUS EASTのいずれかのロケーションに限定したいです。

こういう場合、anytrue関数が使えます。 validationブロックのconditionにて、以下のように書けます。 anytrue

変数値にwestusを指定してみましょう。 westus エラーになりました。エラーメッセージは先程のコードのerror_messsage引数に書かれていたものです。

次はalltrueのデモです。vm_sizeという、Virtual Machineのサイズを設定する変数を用意します。ただし使えるサイズを限定したい。

こういう場合、以下のようにalltrueで正規表現一致判定を組み合わせることで実現可能です。 alltrue

vm_sizeStandard_A7を指定してみると… Standard_A7 エラーになります。

ARM64 builds for Linux

ARM64-builds-for-Linux Linux向けのTerraformのARM64バイナリーも提供開始しています。これにより、AWSのGravitonインスタンスやRaspberry PiでもTerraformを動作させることができます。Apple M1チップへの対応は現在対応中です。

Terraform State Compatibility

terraform-state-compatibility バージョン0.14のStateファイルのフォーマットは、今後リリースされる0.15さらには1.0と前方互換性があります。これまでは、うっかりバージョンアップをしてしまうと(Stateのフォーマットが違うがために)元のバージョンに戻せない、といったつらみが発生していました。そのため今もなお0.12や0.13を使っているユーザーが居ることも知っています。0.14以降はこのような心配は無用です。

No upgrade tool

no-upgrade-tool 0.13から0.14へのアップグレードツールはありません。必要ないからです。ほんの少しの変更で0.14を始めることができます。とはいえ、 アップグレードガイドは一読いただきたいと思います。とはいえ、簡単なのは現在0.13を使っている場合の話です。それ以前を使っている場合は一度0.13にアップグレードする必要があります。その作業は骨が折れるかもしれません。

動画

あわせて読みたい