🌊
terraform設計(ディレクトリ構成など)
最初に
皆さん、terraformを使ってクラウドをデプロイしたりしていますでしょうか。
私は最近使うことがだんだん増え、設計をしていく内に色々な悩みが出てきました。
特に
どの構成もいいところがあれば悪いところもある、果たして正解はあるのでしょうか。
と、いつも思ってしまいます・・・
そこで、自分が今までに使った構成の特徴とおすすめポイントやその他設計ポイントをまとめてみました。
今回はAWSでのデプロイを想定
1. ディレクトリ構成
1.1. ノンモジュール
個人的には一番好きでよく使うので、最初に紹介させてください。
terraform
├── backend
│ ├── develop.tfbackend
│ ├── staging.tfbackend
│ └── product.tfbackend
├── config
│ ├── develop.tfvars
│ ├── staging.tfvars
│ └── product.tfvars
├── main.tf
├── variables.tf
├── vpc.tf
│・
│・
│・
├── terraformplan.out
├── .gitignore
├── Makefile <- for terraform planなどのコマンドを簡単に実行可能にする
└── README.md
【構成説明】
- リポジトリ直下にリソースの.tfファイルを配置する
- tfstateはbackendフォルダに.tfbackendを配置し、terraformコマンドを実行する際に指定することで切り替える
- 環境変数はconfigフォルダに.tfvarsを配置し、terraformコマンドを実行する際に指定する
- プロジェクト固有の変数は直下のvariables.tfファイルに記載する
【特徴】
- 構成がシンプルなので小規模の場合は管理、運用しやすい
- 規模が大きくなると、ファイルが無秩序に並んでるように見え、反って管理しづらくなる
- 変更は.tfvarsを更新する
【細かいところ】
- backend
環境毎のバックエンドを格納(よくS3などが使われる) - config
環境毎の環境変数を格納 - main.tf
providerやモジュールなど - variables.tf
環境に依存せず、共通部分の変数を定義 - terraformplan.out
terraform planの結果をoutファイルに出力するとapply時に使える - .gitignore
git pushでリモートリポジトリにpushせず、除外したい対象を記載 - Makefile
terraform planなどのコマンドを簡単に実行可能にする
下記のようにオプションをつけすぎて、いちいち打つのがめんどくさいので
terraform plan -var-file var.tfvars
1.2. モジュール
一般的に多く使われているのがこちらの構成ですね。
terraform
├── env <- for 環境毎のバックエンドを格納
│ ├── develop
│ │ ├── main.tf
│ │ └── backend.tf
│ ├── staging
│ │ ├── main.tf
│ │ └── backend.tf
│ └── product
│ ├── main.tf
│ └── backend.tf
├── module
│ ├── network(例)
│ │ ├── vpc.tf
│ │ ├── subnet.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ ├── module1
│ │ ├── aws_resource.tf
│ │ └── variables.tf
│ └── module2
│ ├── aws_resource.tf
│ └── variables.tf
├── .gitignore
└── README.md
【構成説明】
- モジュールを使用し、データとテンプレートを分ける
- データをenv、テンプレートをmodulesに配置する
- テンプレートは機能毎にテンプレートを分ける
【特徴】
- 構成が分かれているので変更の着手ポイントがわかりやすい
- 規模が大きい場合は構成が分かれているので仕切りは見やすい
- モジュールが増えると複雑化し、管理のハードルが上がる。初心者には厳しい・・・
- 機能やサービスごとにテンプレートを分ける場合、連携などに注意しなければならない
【細かいところ】
- env
本ケースのように複数環境を管理する場合、それぞれの環境で呼び出したいモジュールをmian.tfに定義する
-> developではnetwork
とmodule1
を呼び出す
-> stagingではnetwork
とmodule2
を呼び出す - module
実際のリソース.tfを記載
1.3. ハイブリッド版
モンハンで言う亜種ですかね、使うか使わないかは好みだと思います。
terraform
├── backend
│ ├── develop.tfbackend
│ ├── staging.tfbackend
│ └── product.tfbackend
├── config
│ ├── develop.tfvars
│ ├── staging.tfvars
│ └── product.tfvars
├── module
│ └── module_name
│ ├── aws_resource.tf
│ └── variables.tf
├── main.tf
├── variables.tf
├── vpc.tf
│・
│・
│・
├── terraformplan.out
├── .gitignore
├── Makefile
└── README.md
【構成説明/特徴】
- 基本的には1.1.ノンモジュール構成と同じで、おまけにモジュールも使うだけ
(ぶっちゃけ構成がごちゃついてるのが嫌ならやめた方がよい)
2. backend管理(tfstate)
- backend.tfはS3に配置する
- DynamoDBによる競合回避対策は同時に触る開発メンバーの数で決める
3. 命名規則
- terraformリソース名はスネークケース( snake_case )を用いる
- AWSリソース名はケバブケース( kebab-case )を用いる
※ちなみにAWSのリソース名に
develop
やproduct
などの環境変数を入れるかは監視など
運用することまで考えて設計した方がよい - 必要に応じて序数を設定する。
4. 変数
- プロジェクト全体で使う変数は直下の
variables.tf
ファイルに記載 - その他環境毎に変わる変数は
環境.tfvars
を配置し、terraformコマンドを実行する際に指定
5. データリソース
- VPCなど他からよく参照されるリソースは基本的にデータリソースを使用する
6. 書式
- フォーマットの統一は
terraform fmt
を使用
terraform fmt -recursive
7. セキュリティ
- オペミスによるリソース削除を防ぎたい場合、
prevent_destory:true
を使って保護可能
この設定を入れるとterraformテンプレート上からリソースを削除しても、applyできない
8. ブランチ戦略
terraformを使う上でリソース管理は切っても切れないものですね。
なかなか奥深いのでまた別の機会に紹介させていただければと思います。
Discussion