AmaziaでのTerraform構成について
はじめに
Amazia インフラチームの吉田です。
弊社ではAWSの構築管理のためのIaCツールとしてterraformを使用しております。
時間の経過とともに、当初作成していたterraformの構成では設定に不都合が出るなどしたため、
terraformの構成の変更を実施しましたので共有いたします。
発生していた問題
基本的にリソースの種別ごとにterraformの実行単位を分割していたのですが、
dataブロックのterraform_remote_stateを多く使用していたため、
蜜結合になり、terraformそのものや、aws providerのバージョンアップのたびに、
各実行単位に順番でterraform applyが必要でした。
もちろん最新バージョンを保つことは良いことなのですが、
ライフサイクルの違うリソースを同時に更新する必要があったため、
効果の小さいところにも工数を割いている状態でした。
そこで、少ない労力で、大きい効果を得るため、
問題となっている設定値の変更含め構成変更を検討しました。
変更前のプロジェクトの概要
変更前のプロジェクトの概要としてはこんな感じです。
terraformコードはgithubで管理
1プロジェクト1リポジトリ
リソースの種別ごとにterraformの実行単位を分割
別々のterraform実行単位で参照するリソースがある場合、terraform_remote_stateで参照
共通で利用する処理はモジュール化
workspaceを使用し、developemnt/staging/productionを構築
terraformの分割/集約の単位を調査
構成変更のため、よく採用される分割/集約の単位を調査しました。
パターンとしては下記のケースが多いようです。
リソースの種別ごとに分ける
チームで管理しているリソースの単位で分ける
システム的に結び付きが強い単位で分ける
変更頻度で分ける
今回の変更では主に、システム的に結び付きが強い単位で分けること、
変更頻度で分けることを意識して変更実施しました。
対応方針
terraformの分割/集約の単位を調査も参考に、弊社組織にあった構成変更の対応方針を立てました。
システム的に結び付きが強い単位でグルーピング
似たようなリソースをグルーピングすることで、モジュールを作成。各モジュールは、他のモジュールやコンポーネントから呼び出すことができる。
1.でできたグループをさらに変更頻度でグループを分ける。
terraform-versionなども個別に配置、terraform_remote_stateを使用している箇所はlocal変数など変更し、蜜結合になる依存を減らす。
共通化できる箇所はmoduleにする
単一のリソースを定義するために、より小規模なコンポーネントを作成することができる。
ディレクトリ構成
上記を踏まえ、検討した結果のディレクトリ構成はこのような構成。
.
├── 更新頻度が高いグループ
│ ├── 実行単位
│ │ └── modules(実行単位で分割が必要なら)
│ └── modules(再利用する設定単位で集合)
├── 更新頻度が低いグループ
│ ├── 実行単位
│ │ └── modules(実行単位で分割が必要なら)
│ └── modules(再利用する設定単位で集合)
・・・
実際のディレクトリを抜粋で記述すると下記のようになります。
.
├── high_frequency
│ ├── .terraform-version
│ ├── README.md
│ ├── modules
│ │ ├── lambda
│ │ │ ├── README.md
│ │ │ ├── config.tf
│ │ │ ├── main.tf
│ │ │ ├── outputs.tf
│ │ │ └── variables.tf
│ │ ・・・
│ ├── provider_config.tf
│ └── root
│ ├── api
│ │ ├── README.md
│ │ ├── config.tf
│ │ ├── data.tf
│ │ ├── locals.tf
│ │ ├── main.tf
│ │ ├── modules
│ │ │ ├── alb
│ │ │ ・・・
│ │ ├── provider_config.tf -> ../../provider_config.tf
│ │ ├── s3.tf
│ │ ├── setup.sh
│ │ └── variables.tf
│ ・・・
└── low_frequency
├── .terraform-version
├── provider_config.tf
└── root
├── ecr
│ ├── README.md
│ ├── config.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── provider_config.tf -> ../../provider_config.tf
│ └── setup.sh
・・・
重複するような箇所は出てしまいますが、以前より運用しやすい構成になりました。
実行手順
terraformでの反映に必要な環境変数等はdirenvで設定、
api などの実行単位のディレクトリに移動し、setup.shに初期化処理をまとめて実行し、初期化を実施します。
初期化実施後、terraform planで差分確認を実施し、terraform applyコマンドで反映していきます。
設定、構成変更した効果
この変更で、設定、構成変更したことで、蜜結合な状態が減り、反映がやりやすくなりました。
また、terraformのバージョンアップなどの大きな変更がある場合、
変更頻度のディレクトリ配下単位(high_frequencyなど)で更新すれば良いので、
ほぼ塩漬けで変更する必要がないリソースの更新を都度実施しなくて良くなりました。
課題
workspaceを分けており、stateを分割したことで、何かの要因で即時反映できない場合、
どこまで反映したかの管理が必要という課題を感じてきております。
解消方法を検討中です。
おわりに
現在更新頻度の高いプロジェクトで変更を完了し運用中です。
こういった正解がないところには、まだまだより良い構成がないかと考えてしまいますね……
現時点でのterraform構成はこのようになりましたが、
時間の経過による周辺環境の変化、運用していくことで、さらに課題が出てきて、
構成も変わっていくものだと思います。
また変更があれば共有できればと思います。
良い構成、設定、考え方で解決できること、ツールなどございましたらご共有、ご指摘いただければ嬉しいです!
こういった点を一緒に改善していきたいエンジニアの方含め、現在Amaziaでは、エンジニアを募集中です!
ご興味ある方はぜひエンジニア採用にご応募ください!