Terraform触ってみたときのTips

こんにちは

仕事でAWSやGCPなどのクラウドを使っています
ただ、いちいち手順書を書いたり、手順書をにらめっこしながら、クラウドインフラを用意するのが面倒です

IaCに興味があったのと、IaCにすれば、インフラを明示的に構築できると思ったので、Terraformに挑戦してみました

その時につまづいたり、参考にしたものなどを紹介します

作ろうとしたのは、よくある3層アーキテクチャで使う要素です
さしあたりAWSを想定しています

- VPC
- サブネット
- EC2
- RDS

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267335/a2d2671b-8e5d-9dfe-9da6-62ae22c59c01.png">


# 公式ドキュメント便利

Terraformは公式ドキュメントが充実しているので、terraform ec2 とかググれば使い方は簡単に出てきます
世の実践例も参考になります
予想以上に敷居が低かったです

https://registry.terraform.io/providers/hashicorp/aws/latest/docs

# ネットワーク分からねぇ

IPAの応用情報の資格は持っているんですが、あらためて自分でネットワークを構築するとなると、よく理解していないことが多いことに気づきました

ですので、[マスタリングTCP/IP入門](https://www.ohmsha.co.jp/book/9784274224478/)を読んで勉強しました
おかげで、VPCやCIDRやサブネットなどの各種設定項目の意味が分かりました
古くからある本ですが、ネットワークの入門として今でも最適だと思います

# インターネットゲートウェイ

VPCのルールでインターネットからのインバウンド設定をしておけば、接続できると思っていたんですが、インターネットゲートウェイが必要でした

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_Internet_Gateway.html

さらにいうと、デフォルトVPCではないので、ルートテーブルを作成して、サブネットを関連付ける必要がありました

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_Route_Tables.html

ネットワークちょっとできるようになりました

そのうちロードバランサーとかも触ってみたいです

# Input variables

実行時につど変えたい値を variable として設定できます
defaultも設定できますし、`.tfvars` ファイルを実行時に指定できます

https://developer.hashicorp.com/terraform/language/values/variables

# for_each

複数の要素分、リソースを繰り返し定義したいときに使えます
key/valueの使い方など、最初はとまどいました
mapやvariableとうまく組み合わせることができると便利です

https://zenn.dev/wim/articles/terraform_loop

https://developer.hashicorp.com/terraform/language/meta-arguments/for_each

# sensitive

sensitive 関数や `local_sensitive_file` でログにシークレット情報などを表示しないようにできます

https://developer.hashicorp.com/terraform/language/functions/sensitive

https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/sensitive_file

# remote_state

あるリソース (e.g. VPC) は共用で、あるリソース (e.g. EC2) は個別に作りたい、といった状況がありました
個別側のリソースは共用リソースを参照したかったので、共用のほうをmodule化してoutputを利用しようとしました
すると、module側のリソースも再作成されてしまいました
`terraform_remote_state` を使うと既存の `.tfstate` ファイルをもとに、既存のリソースを参照することができました

https://developer.hashicorp.com/terraform/language/state/remote-state-data

とはいえ、あんまり依存を複雑にさせるのもよくないらしいですね

https://qiita.com/minamijoyo/items/3a7467f70d145ac03324#terraform_remote_state%E3%82%84%E3%82%81%E3%82%88%E3%81%86

# user_data

EC2を作成するときに、所定のスクリプトを実行することができます
あらかじめ入れておきたいパッケージや、設定したい事項などを指定できます

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/user-data.html

# RDSはサブネットをマルチAZにする必要がある

お試しのリソースなので、RDSはシングルAZで作るつもりでした
そのつもりで、サブネットもシングルAZにすると失敗しました

https://dev.classmethod.jp/articles/rds-has-two-configs-concerning-availability-zone/

インスタンス自体はシングルAZにできるのですが、サブネットは複数AZに紐づける必要があるようです

# S3 の暗号化アルゴリズムに `aws:kms` を使うと金がかかる

S3 もサーバーサイドでいいので暗号化しようと思いました
Terraformのドキュメントを参考に、ナチュラルに`sse_algorithm = aws:kms` を設定していました
するとレビュアーにKMS料金がかかるため、`AES256` にするほうがいいと注意されました

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/UsingServerSideEncryption.html

考えてみればKMS料金かかりますよね
同時にレビュアーがいないと気付かないこともあるので、ありがたいなと思いました

# Tag & Resource Group

provider 設定時にデフォルトタグをつけることができます
作成するリソースに一意のタグをつけて、リソースグループで追跡できるようにします
こうすることで、コストの管理やリソースの消し忘れなどを防げます

https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags

https://docs.aws.amazon.com/ja_jp/ARG/latest/userguide/resource-groups.html

# 終わり

以上です
Terraformを触ってみてよかったなと思うのは、リソースの作成と削除をコマンド1つでできるようになったことです
コンソールからポチポチしなくていいので、とても楽です
リソースの設定も明示されているので確認やレビューも簡単です
みなさんも是非挑戦してみてください