🌊

terraform設計(ディレクトリ構成など)

2023/01/29に公開

最初に

皆さん、terraformを使ってクラウドをデプロイしたりしていますでしょうか。
私は最近使うことがだんだん増え、設計をしていく内に色々な悩みが出てきました。

特に \textcolor{red}{ディレクトリ構成}
どの構成もいいところがあれば悪いところもある、果たして正解はあるのでしょうか。
と、いつも思ってしまいます・・・
そこで、自分が今までに使った構成の特徴とおすすめポイントやその他設計ポイントをまとめてみました。
今回はAWSでのデプロイを想定

https://www.terraform.io/
https://blog.dcs.co.jp/aws/20210401-terraformaws.html#about
https://www.fenet.jp/infla/column/technology/terraformとは基本知識とterraformのメリット4つを紹介/

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ではnetworkmodule1を呼び出す
    -> stagingではnetworkmodule2を呼び出す
  • 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のリソース名にdevelopproductなどの環境変数を入れるかは監視など
    運用することまで考えて設計した方がよい

  • 必要に応じて序数を設定する。

4. 変数

  • プロジェクト全体で使う変数は直下のvariables.tfファイルに記載
  • その他環境毎に変わる変数は環境.tfvarsを配置し、terraformコマンドを実行する際に指定

5. データリソース

  • VPCなど他からよく参照されるリソースは基本的にデータリソースを使用する

6. 書式

  • フォーマットの統一はterraform fmtを使用
    terraform fmt -recursive

7. セキュリティ

  • オペミスによるリソース削除を防ぎたい場合、prevent_destory:trueを使って保護可能
    この設定を入れるとterraformテンプレート上からリソースを削除しても、applyできない

8. ブランチ戦略

terraformを使う上でリソース管理は切っても切れないものですね。
なかなか奥深いのでまた別の機会に紹介させていただければと思います。

Discussion