しばやん雑記

Azure Serverless とメイドさんが大好きなフリーランスのプログラマーのブログ

Terraform Provider for Azure を 2.0 へアップグレードする

少し前に Terraform Provider for Azure を 2.0 へアップグレードしようとして、軽い気持ちでバージョンを上げたらいきなりエラーが出たり、terraform plan で予期しない変更が大量に出て心が折れました。

即オチ 2 コマみたいなツイートをしてしまうぐらいでしたが、冷静に対応すると大したことなかったです。

Azure Provider のドキュメントは既に 2.0 ベースになっているので、早いうちに対応しておいた方が良いです。アップグレードガイドに従って対応すれば、自分のようにいきなりエラーではまることもないです。

今のドキュメントでは Provider のバージョンは明示的に指定した方が良いと書いてあったので、provider での定義は大体以下のようになるでしょう。

既に 2.1.0 がリリースされているので、バージョンだけ少し変更しています。

provider "azurerm" {
  version = "=2.1.0"
  features {}
}

上のように変更するだけで 2.0 へのアップグレードが完了する環境もあるはずですが、Azure Functions を使っている場合には terraform plan で replaced が大量に出てきて焦ることになります。

実際に Azure Functions を含む定義に対して 1.44.0 から 2.1.0 へのアップグレードを行うと、大量にリソースの作り直しが行われるプランが出てきます。

f:id:shiba-yan:20200316022055p:plain

本番で利用していた Terraform の場合は Azure Functions をたくさん使っていたので、プランを見た瞬間に心が折れてしまいましたが、作り直しになった原因を調べると全て Storage Account の種類でした。

account_kind の値が Storage から StorageV2 に変わったので Storage Account が作り直しになり、関連するリソースが全て作り直しになるという話でした。

f:id:shiba-yan:20200316022102p:plain

このようなプランになった理由は、バージョン 2.0 から一部のプロパティのデフォルト値が変わっていることにありました。アップグレードガイドからデフォルト値が変更されたリソースを引っ張ってきました。

Resource: azurerm_application_gateway
The default value for the body field within the match block will change from * to an empty string.

Azure Resource Manager: 2.0 Upgrade Guide - Terraform by HashiCorp

Resource: azurerm_availability_set
The default value for the field managed has changed from false to true.

Azure Resource Manager: 2.0 Upgrade Guide - Terraform by HashiCorp

Resource: azurerm_storage_account
The default value for the field enable_https_traffic_only has changed from false to true.
The default value for the field account_kind has changed from Storage to StorageV2.

Azure Resource Manager: 2.0 Upgrade Guide - Terraform by HashiCorp

Application Gateway と Availability Set は良いとして、Storage Account は account_kind のデフォルト値が Storage から StorageV2 に変わっています。そして account_kind は変更されると作り直しになるように設計されているので、明示的に指定しないと上のようなプランになります。

なので、今回の例の場合は provider の変更と同時に account_kindStorage を追加すれば解決します。enable_https_traffic_onlytrue が望ましいのでそのままにしておきます。

f:id:shiba-yan:20200316022110p:plain

新規で作成する場合でも明示的に指定しない限り StorageV2 になりますが、StorageV2 は課金方法が少し変わっているので、ワークロードによっては割高になる可能性があるので注意が必要です。

修正後に terraform plan を実行すると、replaced は発生せず enable_https_traffic_only の変更だけになりました。これまで enable_https_traffic_onlyfalse だったのがあり得ないので、1.x 系を使い続ける場合には注意したいです。

f:id:shiba-yan:20200316022118p:plain

デフォルト値が変わった部分以外は廃止扱いだったプロパティがごっそり削除されているぐらいなので、大抵は terraform plan などで容易に捕捉可能です。

単純に削除していけば大体問題ないので、このデフォルト値の変更だけ気を付けましょう。

補足 : Storage V2 への移行方法

本来なら Storage から StorageV2 への移行はダウンタイム無しで行えるはずですが、Terraform の仕様によって現在は作り直し扱いになっているようです。

しかし ARM レベルでは問題なく対応可能なので、Azure CLI や Portal から StorageV2 に手動で変更してから Terraform の定義を直すことでダウンタイム無しで変更が行えます。

f:id:shiba-yan:20200316025026p:plain

将来的には StorageV2 への移行がすんなり行えるようになると思いますが、現状は手動での対応が必要になりそうです。1 回だけなので我慢は出来るレベルです。