Terraform

TerraformとBicep両方さわってみて思ったこと

Bicepとは勝手が違う

AzureでのIaC

さて、クラウド使うのにポチポチしてる時代は縄文時代にもう終わっています。

時代はIaCです。IaCそれすなわちInfrastructure as Codeです。

IaCのメリットだとか、そういう語り尽くされた内容については今さら私が述べる必要もないでしょう。

私が業務で使うクラウドはもっぱらAzureですが、AzureでのIaCとなるとまず挙がるのが純正のARM Templateです。しかし、ARM TemplateはJSONのため、人間が書き下すのはかなりのしんどさがあります。

そこで、azコマンドにも組み込まれるようになった独自DSLであるBicepがあります。これはazコマンドに組み込まれるだけあって、MSサポート対象です。

一方で、awsなどでも広く使われているマルチプラットフォーム対応のTerraformも当然ですが使えます。TerraformといえばIaC界では完全にデファクトです。

私はBicepをTerraformより先に使い始めました。しばらく触ってみてBicepはそれなりに使えるようになりましたが、デファクトのTerraformを知らないというのではやはり居心地が悪いです。

そんなワケで最近はTerraformもひと通りさわってみて使えるようになりました。今回は、その所感です。

触ってみて感じた違い

まず、参照関係の解決が大きく異なるので、いわゆるよい書き方がガラッと変わる印象を持ちました。

ここで言う「よい書き方」とは、DRYと読みやすさと書きやすさをエエ感じにした状態だと思ってください。トレードオフの要素もあるため、曖昧な言い方になってしまいますが、まあエエ感じということで。

Bicepは1つのファイルが起点

Bicepの場合、デプロイにはaz deployment group create -f file.bicepのようなコマンドで単一のBicepファイルを指定します。

そのため、起点となるのはあくまで1つのBicepファイルであり、そこにデプロイ対象として参照先をもれなくキッチリ記述していくスタイルです。

Terraformはディレクトリ内がすべて対象

対するTerraformでは、*.tfファイルが含まれるディレクトリ上でterraform applyコマンドを叩きます。

このとき、ディレクトリ内(サブディレクトリを除く)に含まれる*.tfファイルはデプロイのすべて対象となり、参照関係を明示的に記述するのは外部のstateファイルやmoduleに限ります。

そのため、ファイル分割はBicepより気軽です。一方で後述のstate管理があるため、なんでもかんでも気軽というわけでもなく、ボトルネックが異なってくる印象を受けました。

自ずとディレクトリ構成も大きく変わる

Terraformを使うと、同一ディレクトリ内にある限り、あらゆる記述はブロック単位で気軽にファイル分割できます。

一方、Bicepの場合は「ファイルを分ける=参照関係を記述する」となるため、同一ライフサイクルの別リソースをどこまでまとめるかの問題がよりシビアになる気がします。 プログラミングでいうところのmain関数のような役目をするファイルが必要になるイメージです。

このため、ディレクトリ構成は大きく異なってきます。

stateファイルの有無

さらに大きな違いとしてstateファイルの有無があります。

Terraformにはstateファイルが、ある

たとえばvirtual networkをデプロイするとしましょう。このとき、virtual networkのresource IDは実際にデプロイするまで確定しません。

Terraformのstateファイルには、こういったデプロイ後にはじめて確定する情報等々を含めて、実リソースの状態がテキストで保存されます。

このstateファイルにより、IaCファイルを変更した際に差分が発生するリソースを正確に特定できる(=IaCファイルの変更にリソースを追従させられる)のがメリットです。

ただし、このstateファイルを壊さないための運用が煩雑になります。しかも、stateファイルは実際のリソース状態をありのままに記述するゆえ、秘匿情報も含まれることになります。

チーム開発ではこの管理が重要になるでしょう。ほとんどのケースで、本体の*.tfファイルはリモートリポジトリに、stateファイルはクラウドのBlobストレージに保存することになろうかと思います。

リポジトリのコードがマージされる前にstateファイルが更新されていてはなりませんが、stateファイルを分割・統合するシーンは必ず発生します。

そういった場面でstateファイルをいかに破壊せず動作確認するかなどの点が課題となるでしょう。その方法についての話は、前回の記事で書いています。

Bicepにはstateファイルが、ない

一方のBicepではstateファイルを持ちません。

そのため、実リソースとIaC定義の差分を厳密に管理するのが原理的に難しいです。クラウドの構成を頻繁に、かつインクリメンタルに変更したい場合に思ったとおりにいかないことが結構あったりもします。

一方で煩雑なstate管理は一切不要のため、チーム開発でもコードをリポジトリにpushするだけでよいです。ローカルでstateファイルの大手術を行う必要はありません。

たとえば、「とにかく作って壊してを繰り返すので、デプロイ作業は冪等に行いたいが、デプロイ後にプロパティ変更することはほとんどない」といったケースであるとか、テスト用の環境をサクッと立てるといったときにBicepはかなり役に立つと思います。

Bicepの差分管理に関しては、今もいろいろと開発に動きがあるようなので、3ヶ月先はこの記事の限りではないと思います。

プロダクトの若さと互換性

ある程度の成熟が見えるTerraformと比較して、Bicepは若いです。大きな機能アップデートが頻繁に行われており、これからどんどん育っていくプロダクトになるでしょう。

さらにBicepは、AzureのデフォルトテンプレートであるARMと互換性があります。あくまでサードパーティ製ツールであるTerraformに対し、BicepはAzureのサポート対象です。

Azure CLIにも含まれているため、Terraformのように追加で各種バイナリをインストールする必要がありません。

ファイルの見通しの良さ

好みの問題かもしれませんが、Bicepは*.bicepファイルで完結するため、シンプルです。

Terraformは*.tfを本体に、*.tfvas*.tfstateなどに分かれます。さらにマルチプラットフォームなのでproviderの定義や、state管理場所であるbackendの定義も必要になり煩雑です。

ここへさらにmodule参照なども入ると、普段コードを書き慣れていないエンジニアが見ても**いったいこの値はどこから来ているんだ?**と陥りやすいような気がします。

おわりに

ざっくりここまで書いてみての結論です。

  • スクラップ&ビルドではなく、すべてのリソースをIaCで構成変更していくスタイルであればTerraformが向いてそう
  • 逆に、「作る」部分に重きが置かれるケースだと面倒なstate管理も必要なくシンプルなBicepが向いてそう

個人的にはBicepの今後の機能アップデートが楽しみです。