LINEで送る
Pocket

ディレクトリ構成

以下のように、terraform/provider/aws/env/stgとしました。
変数ファイルであるvariables.tfもメイン処理をするec2.tfも同じディレクトリに置きます。

環境ごとに完全にファイルを分断するイメージで、tfstateファイルも環境ごとに別にします。(保管場所はS3です)
なお、module化はしません。

変数の書き方

Before

これまでterraformの変数ファイルはこんな感じで書いてました。

実際のEC2のパラメータはこれだけではありません。もっとたくさんある上に、AWSのリソースは他にもあるとなるとかなり長い変数ファイルとなります。

特徴としては、variableが毎回並んでしまって行数が増える。読みにくい見にくい探しづらい。

これを解決するのにmapを使いました。

A map value is a lookup table from string keys to string values. This is useful for selecting a value based on some other provided value.
A common use of maps is to create a table of machine images per region, as follows:

After

一つのvariableに対してリソースの値をまとめます。
map型の宣言は省略可能みたいです。

こうすることで、リソースごとに値がまとまるので読みやすくなりました。
ではメイン処理をするec2.tfを見ていきましょう。

map型でのec2.tfの書き方

Before

これまでのリソース定義の書き方はこちらです。

そしてafter版に対するvariableに対応するリソース定義の仕方です。
map型で変数を格納したので、lookup関数を使って値を参照させます。

beforeのときよりやや長くなったように見えますが、ルールを覚えれば(後述)そこまで複雑ではない上、柔軟性は良くなっています。

注意点

resource定義内のami, instance_type, key_nameはterraform側で名前が決まっています。variables.tf内の変数名は任意ですが、こちらは自由には決められないので注意しましょう。
aws_instance

lookup

上記の書き方は、lookup関数でKeyを直接指定する方法を取っています。
こちらを参考にしています。
Terraformのoutputでmapを利用する方法

たとえば以下であれば
ami = "${lookup(var.ec2_config, "ami")}"

variables.tf内のec2_configamiの値を参照する」という意味になります。

format

最終行の"vtryo-${format("web%02d", count.index + 1)}" についてですが、変数格納後の値はvtryo-web01になります。
ちなみに"web%02d"を、"web%01d"にするとvtryo-web1になってしまうので注意です。

terraform init

さて実行です。

terraform plan

変数が格納されました!

ちょっと応用

さきほどのec2.tfでNameには"vtryo-${format("web%02d", count.index + 1)}" を書きました。
この出力結果はvtryo-web01です。
これをstg-vtryo-web01のように、環境を先頭に入れる方法を書いておきます。

variable “env”

variables.tfにvariable "env { }"を書きます。

{ }の中にdefaultを入れてもよいです。その場合は以下のように書きます。

 

${var.env}

一方でec2.tfには以下を書きます。

${var.env}をつけることで、terraform planしたときに入力を求められます。
入力した内容が、${var.env}に格納されるという仕組みです。

terraform plan

Enter a valueを求められるので今回はstgにしました。
すると、stgという文字列が格納されます。

ちなみにterraform plan -var "env=stg"とすることで入力なしで格納することが可能です。

今回の補足というか余談

「terraformのbest-practice、わかりづらくない?」

開発者が推奨している構成だとはわかっていますが、素直にそんな感想がありました。
terraform best-practice
(もちろんQiitaにかかれている記事も読んでいます
Terraform Best Practices in 2017

ファイルの中に何度も宣言をしないといけないようですし、どうにも読みづらい印象があります。
また、「Environmentで環境を分ける」構成になっていますが、公式曰く

Workspaces can be used to manage small differences between development, staging, and production, but they should not be treated as the only isolation mechanism.

とあります。我らがGoogle翻訳を使うとこんなことを言ってます。

ワークスペースは、開発、ステージング、およびプロダクションの小さな違いを管理するために使用できますが、唯一の分離メカニズムとして扱うべきではありません。

初見で解読するには骨がいる内容です。何度もterraformを使い込んだらわかるんでしょうか。
ま、単純に私の技術力が追いついていない可能性の方が高いですが(爆)

とはいえ誰でも彼でもterraformの技術力が高いわけではないので、より読みやすくメンテナンスしやすい書き方をしても良いと思っています。

terraformは一歩間違えるとインフラそのものが削除されることがあるので、それを踏まえて確実な方が良いだろうというきもちです。

シンプルに書きたい欲

terraformにはmodule化が出来る機能があって、それがやや難易度を上げているように思います。

変数をmodule化できることでメリットもありますが、利用ができなければ意味がない。terraformにはmoduleのレジストリ がありますが、仕組みを理解しないとやっぱり使うのは大変です。

学習コストばかりかかるくらいなら、いっそ使わずにシンプルにコードを書いて行こうということでした。

best-practiceに固執しない

重要なのは可読性ととっつきやすさだと思ったので、あえて固執せずにディレクトリを構成し、terraformを見やすく書く方法を考えました。
誰かの参考になれば幸いです。

参考

Terraformのoutputでmapを利用する方法 – Qiita
Terraform Best Practices in 2017 – Qiita
TerraformでのAWS環境構築の設定を分ける – Qiita
terraform
さらに一歩楽しむterraform. moduleでIAM UserとPolicy管理を簡素化しよう

Share on FacebookTweet about this on TwitterShare on Google+