Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 25 additions & 23 deletions documents/forTerraform/terraform_guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ Terraformの変数には以下の2種類がある。
Terraformではコレクション型として、tuple、list、map、objectといったデータ形式が提供されている。
それぞれの特徴は以下の通りであり、用途に合わせて利用する形式を選択すること。

| # | (1)tuple | (2)list | (1)map | (2)object |
| # | tuple | list | map | object |
| :----------- | :----------------- | :--------------------------------------------------------------- | :-------------------------------------------------------------------------- | :------------------------------------------------------------------------- |
| 説明 | 固定長の要素のペア | 同じ型で任意数の要素を保持 | キーと値のペア。タグのようなフラットな構造で利用 | 異なる型のプロパティを持つ複数の属性を格納する。構造的なデータの場合に利用 |
| 宣言 | `["v1", "2"]` | `["v1", "v2"]` | `{ k1 = "v1", 2 = "v2" }` | `{ attr1 = "v1", attr2 = "v2" }` |
Expand Down Expand Up @@ -356,7 +356,7 @@ resource "aws_lambda_function" "foo_example_api" {

```tf
resource "aws_instance" "foo_example_webapi" {
count = "dev" == terraform.workspace ? 0 : 1 # dev環境では作成しない
count = "dev" == var.environment ? 0 : 1 # dev環境では作成しない
# ...中略...
}
```
Expand Down Expand Up @@ -526,7 +526,7 @@ resource "aws_instance" "example" {

- for_eachを付けたリソースにおいて、Dynamic Blocks で for_eachを利用することの制限はない。可読性などを考慮して適切に利用すること
- ネストした変数の繰り返し処理は、原則、(1)flattenを利用し、コードベースをシンプルに保つ
- モジュール化の是非は「modules」章を参考にする
- モジュール化の是非は[モジュール](#モジュール)章を参考にする

【参考】

Expand Down Expand Up @@ -592,7 +592,7 @@ provider "aws" {

default_tags {
tags = {
Env = terraform.workspace,
Env = "dev",
System = "Foo",
Owner = "FooTeam",
}
Expand Down Expand Up @@ -813,7 +813,7 @@ Terraformを利用してパスワードなどの機密情報を作成する場

# 削除保護

terraform planで表示されるリソース数が多い場合に、本来削除すべきではないリソースを誤って削除(または、削除してからの再作成)してしまい、データ消失してしまうなどの懸念がある。そのため、影響度が大きいリソースに対しては、誤操作を防ぐためのガードレールを入れておくことが好ましい。
`terraform plan` で表示されるリソース数が多い場合に、本来削除すべきではないリソースを誤って削除(または、削除してからの再作成)してしまい、データ消失してしまうなどの懸念がある。そのため、影響度が大きいリソースに対しては、誤操作を防ぐためのガードレールを入れておくことが好ましい。

代表的な手法を下表にあげる。

Expand Down Expand Up @@ -860,17 +860,19 @@ resource "aws_s3_bucket" "important_bucket" {
- [terraform applyをより安全に実行するためにできること](https://blog.mmmcorp.co.jp/2022/10/31/terraform-apply-safely/) のように、タグとIAM権限で保護する手法がある
- [AWS S3でバケット自体も中身も削除禁止のバケットを作る - もりはやメモφ(・ω・ )](https://blog.morihaya.tech/entry/2019/02/02/112211) のように、本気で消したくないのは、IAM権限でRootアカウント以外は削除不可とする設計が可能

# 環境識別子
# 環境分離

::: tip 環境識別子

[AWSインフラ命名規約 | Future Enterprise Coding Standards](https://future-architect.github.io/coding-standards/documents/forAWSResource/AWS%E3%82%A4%E3%83%B3%E3%83%95%E3%83%A9%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E5%91%BD%E5%90%8D%E8%A6%8F%E7%B4%84.html#%E7%92%B0%E5%A2%83%E8%AD%98%E5%88%A5%E5%AD%90) から、環境識別子は以下の通り。
[AWSインフラ命名規約 | Future Enterprise Coding Standards](https://future-architect.github.io/coding-standards/documents/forAWSResource/AWS%E3%82%A4%E3%83%B3%E3%83%95%E3%83%A9%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E5%91%BD%E5%90%8D%E8%A6%8F%E7%B4%84.html#%E7%92%B0%E5%A2%83%E8%AD%98%E5%88%A5%E5%AD%90) から、環境識別子は以下の通り。本ガイドラインもこれに則る。

| 識別子 | 説明 |
| :----- | :-------------------- |
| dev | 開発環境(development) |
| stg | 検証環境(staging) |
| prod | 本番環境(production) |

# 環境分離
:::

Terraformで複数のデプロイメント環境を切り替える方法は下表のように複数案存在する。ここでのバックエンド分離とは、ステートを環境ごとに別のオブジェクトストレージに配備することを指す。

Expand Down Expand Up @@ -952,8 +954,8 @@ infrastructure
- ワークスペースを用いないため、Terraform の学習コストを多少なり下げることができる
- 特定の環境だけにリソースを追加する必要がある場合、count分出来はなくルートモジュール側に追加できる脱出ハッチがあり、柔軟性がある
- モジュールと組み合わせることで、デプロイメント環境ごとの統制も図りやすい
- ワークスペースは、環境分離で利用することは公式ドキュメントから推奨されている訳ではないと考えられるため
- `count = terraform.workspace == "dev" ? 0 : 1` といったコードの頻出により、可読性が低下するため
- ワークスペースを環境分離で利用することは公式ドキュメントの記述から非推奨である考えられるため
- `count = var.environment == "dev" ? 0 : 1` といったコードの頻出により、可読性が低下するため
- count制御の場合、どの環境にどのリソースがデプロイされているかの把握が、(1)のディレクトリ分離より下がるため

::: tip Terraform Stacks
Expand Down Expand Up @@ -1063,9 +1065,9 @@ resource "aws_hogehoge" "sample_resource" {
| :--------- | :--------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ |
| 例 | main.tf <br>---<br>backend.tf <br>providers.tf <br>terraform.tf <br>locals.tf <br>variables.tf | network.tf <br>storage.tf <br>db.tf <br>compute.tf <br>---<br> ・・・ | s3_bucket.tf <br>s3_bucket_acl.tf <br>s3_bucket_cors_configuration.tf <br>---<br> ・・・ |
| 説明 | main.tfにリソース定義を一括で記載するケース。 | 何かしらの論理グループごとにmain.tfを分割したパターン。論理グループの作成粒度が肝となる | Terraformのリソース種別ごとにファイルを分割するパターン。例えば、S3バケットを新規作成する場合も、複数のファイルへ定義の追加が必要となる場合がある |
| 設計難易度 | ✅️容易 | ⚠️ファイル粒度の設計が必要。 | ✅️容易 |
| 設計難易度 | ⚠️中規模以上ではモジュール運用が必須 | ⚠️ファイル粒度の設計が必要。 | ✅️容易 |
| 運用難易度 | ✅️容易 | ⚠️論理グループの設計によっては、後で再設計が必要となる懸念 | ✅️容易 |
| 拡張性 | ❌️中規模以上では難しい | ⚠️設計時の見積もり以内であればハマるが、想定外のリソース追加に弱い | ✅️最小粒度に近く、拡張に強い |
| 拡張性 | ✅️モジュール運用前提であれば柔軟に拡張可能 | ⚠️設計時の見積もり以内であればハマるが、想定外のリソース追加に弱い | ✅️最小粒度に近く、拡張に強い |

本ガイドラインの推奨は以下。

Expand Down Expand Up @@ -1096,7 +1098,7 @@ resource "aws_hogehoge" "sample_resource" {

推奨は以下の通り。

- .tfファイルあたりの20を超えるなど、リソース数が多くなりそうであれば、機能分類などでグループを作り、コメントで区切る
- .tfファイルあたり20を超えるなど、リソース数が多くなりそうであれば、機能分類などでグループを作り、コメントで区切る

▼例: コメントでAWS Lambdaを2つのグループに分類

Expand Down Expand Up @@ -1316,7 +1318,7 @@ variable "instance_count" {
- できる限り、入力パラメータの数を減らす(少なければ少ないほど良い)
- 利用者の認知負荷を減らす・コードオーナーの保守運用負荷を減らす・実装の複雑度を下げる、という目的のため
- その上で入力パラメータは、できる限りデフォルト値を設定とし、パラメータ指定なしでも動くようにする
- ただし、誤ったリソース作成がなされる可能性がある場合は、必須設定とさせるべきである
- ただし、誤ったリソース作成がなされる可能性がある場合は、必須入力とすべきである
- 変数の型やdescriptionは明示的に記載する
- validationは可能な限り設定する

Expand Down Expand Up @@ -1353,7 +1355,7 @@ variable "instance_count" {
- 予期しないモジュールの更新により、期待したリソースの作成ができなくなることを防ぐため
- 可読性の向上のため
- サードパーティモジュールは汎用的に書かれていることが多く、自身で不要なパラメータについてもチェック対象になりうるため
- 以下の条件に全て一致する場合は、利用を許容する
- 以下の条件に複数一致する場合は、利用を許容する
- 技術検証(PoC)など限定された期間でのみ利用する
- 何よりクイックなインフラ構築が優先される場合
- サードパーティモジュールで作成できる構成をそのまま利用する場合
Expand Down Expand Up @@ -1667,7 +1669,7 @@ Terraform上で管理すべきバージョンは以下2種類存在する。

それぞれについて方針を記載する。

なお、モジュールについてのバージョンはモジュール章を参照すること。
なお、モジュールについてのバージョンは[モジュール](#モジュール)章を参照すること。

### 1. Terraform自体のバージョン管理

Expand Down Expand Up @@ -1764,7 +1766,7 @@ Terraformについてはマイナーアップデートの対応がメインだ

▼[「楽」する前のTerraformバージョンアップ方針と運用整理(とポエム) - 東京ガス内製開発チーム Tech Blog](https://tech-blog.tokyo-gas.co.jp/entry/2024/05/07/113451) の記事から引用

![](image1.jpg)
![Terraformのバージョンアップ作業フロー](image1.jpg)

# テスト

Expand All @@ -1774,7 +1776,7 @@ Terraformについてはマイナーアップデートの対応がメインだ

```tf [s3_bucket.tf]
resource "aws_s3_bucket" "test001" {
bucket = "${terraform.workspace}-${local.project_name}-test001"
bucket = "${var.environment}-${local.project_name}-test001"
}
```

Expand All @@ -1787,7 +1789,7 @@ run "test" {
command = plan

assert {
condition = aws_s3_bucket.test.bucket == "${terraform.workspace}-${local.project_name}-test"
condition = aws_s3_bucket.test.bucket == "${}-${local.project_name}-test"
error_message = "S3 bucket name did not match expected"
}
}
Expand Down Expand Up @@ -1841,7 +1843,7 @@ run "test" {
- ※CI側で1日1回、 `terraform plan` を実施し、なにか検知すれば自動で管理システムに起票する仕組みを整えるなどで緩和可能であるが、目的に対して手段が重厚である

::: tip リンター
テスト以外の品質の高め方としては、リンターを用いたセキュリティやポリシーの検証も行われている。リンター章を確認すること。
テスト以外の品質の高め方としては、リンターを用いたセキュリティやポリシーの検証も行われている。[リンター](#リンター)章を確認すること。
:::

【関連】
Expand Down Expand Up @@ -1975,7 +1977,7 @@ AWSでterraform planのみ実行できるようにする例を示す。ReadOnlyA
- ローカルPC上は、dev環境でのplan操作のみ許容する
- 開発生産性のため
- CI/CD上でのplan、applyは開発生産性の観点で、できる限り取り入れる。これ1本に統一することは必須ではない
- 詳細は「開発ワークフロー」の章を参考にすること
- 詳細は[開発フロー](#開発フロー)章を参考にすること
- どの方法であってもAWSであればAWS Config、AWS CloudTrail等にて変更の証跡を保存し追跡できるようにすること

実行可能な操作を、Terraform実行環境別にまとめると下表となる(凡例 ✅️実行可能 ❌️実行不可)
Expand Down Expand Up @@ -2012,7 +2014,7 @@ GitHub ActionsなどのCI/CDパイプラインでのterraformコマンドを実

## ローカル端末で認証

ローカルPC上で `terraform plan` や `terraform apply` を、どのデプロイメント環境まで許可するかは、Terraform実行環境章を参考にする。仮にローカルPC上で実行を許容する場合は、利用するアクセスキーは強い権限を保持することとなる。そのためキーの漏洩はリスクが高く、安全なキーの保管や認証が必要である。各クラウドサービスのプラクティスは下表の通り。
ローカルPC上で `terraform plan` や `terraform apply` を、どのデプロイメント環境まで許可するかは、[Terraform実行環境](#terraform実行環境) 章を参考にする。仮にローカルPC上で実行を許容する場合は、利用するアクセスキーは強い権限を保持することとなる。そのためキーの漏洩はリスクが高く、安全なキーの保管や認証が必要である。各クラウドサービスのプラクティスは下表の通り。

| # | AWS | Google Cloud | Azure |
| :------- | :------------------------------------------------------------------------------- | :---------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------ |
Expand Down Expand Up @@ -2044,7 +2046,7 @@ Gitブランチフローの詳細は、[Gitブランチフロー規約 | Future
推奨は以下の通り。

- CI/CD時にdev環境に対して、 `terraform apply` を実行し、予期しない差分が無いか、プランが想定通りか開発者とレビュアー双方が確認可能とする
- CI/CDで、プルリクエスト作成時に、静的解析(terraform validatetflinttrivy)などを実行する<「リンター」章を参照>
- CI/CDで、プルリクエスト作成時に、静的解析(`terraform validate` `tflint` `trivy`)などを実行する。[リンター](#リンター)章を参照する
- developブランチマージ後は、CI/CDでdev環境に `terraform apply` する
- mainブランチマージ後、ステージング環境に `terraform apply` する
- ステージングでの動作確認が問題なければ、プロダクション環境に `terraform apply` する
Expand Down