個人的な備忘録：Terraformを本気で学ぶために、改めて設計思想や考え方を自分なりに調べてみた

## はじめに
Terraformの設計思想は、一貫性・再現性・可読性・運用の安全性を重視しており、IaCを実践するうえで非常に強力なツールです。

:::note info
**今回の内容は、Terraformを個人学習でキャッチアップする中で、私自身が設計思想やディレクトリ構成について調べた内容をまとめたものです。**
:::

そのため、あくまで個人の備忘録レベルとなっています。より詳細な情報については、以下の公式ガイドを参考にしてください。

https://www.terraform.io/

https://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/terraform-aws-provider-best-practices/structure.html

## 困っていたこと
マイクロサービス環境では、インフラを構成するリソースの数がサービス数に応じて肥大化していきました。

***その中で改めて、Terraformの設計思想やディレクトリ構成、ベストプラクティスについて調べ直すことにしました。***

現状は単一のファイルで全てを管理していますが、この方法では第三者が見たときの可読性が低いと考えています...。

**まとめている記事**

https://qiita.com/free-honda/items/52386ac5bad7e0a29ff8

**ソースコード**

https://github.com/Winter-Hackathon-2025-A-Team/skill-typing-infra

## Terraformの設計思想について

- **1. Infrastructure as Code（IaC）**
  - インフラをコードとして記述し、バージョン管理を可能にする。
  - インフラの設定をプログラム可能な形で表現し、再利用や変更を容易にする。

https://qiita.com/free-honda/items/682e29d92e60e2d17681

- **2. 宣言的な構成（Declarative Configuration）**
  - 「どのように（How）」ではなく、「何を（What）」実現したいかを記述する。
  - 例えば、「EC2インスタンスを作成する」ではなく、「この設定のEC2インスタンスが存在するべき」と定義する。

**例：EC2インスタンスをコードで定義**

```hcl
provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "example" {
  ami           = "ami-12345678"
  instance_type = "t2.micro"

  tags = {
    Name = "ExampleInstance"
  }
}
```

- **3. 実行計画（Plan & Apply）**
  - `terraform plan` で変更を事前にシミュレーションし、適用前に変更点を確認できる。
  - `terraform apply` で実際にインフラを構築・変更する。

**実行例**

```bash
terraform init     # 初期化
terraform plan     # 変更点をシミュレーション
terraform apply    # 変更を適用
```

- **4. 状態管理（State Management）**
  - `terraform.tfstate` というファイルで現在のインフラの状態を管理し、差分を適用する。
  - `remote backend` を使うことで複数人での管理を可能にする。

```hcl
terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "state/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "terraform-lock"
  }
}
```

- **5. モジュール化と再利用性**
  - `module` を活用して、汎用的なインフラ構成を再利用できる。
  - 例えば、VPCやDBのセットアップをモジュール化し、他のプロジェクトでも流用可能。

**例：VPCのモジュール化**

`modules/vpc/main.tf`

```hcl
resource "aws_vpc" "main" {
  cidr_block = var.cidr_block

  tags = {
    Name = var.name
  }
}
```

`modules/vpc/variables.tf`

```hcl
variable "cidr_block" {}
variable "name" {}
```

**モジュールの利用**

```hcl
module "vpc" {
  source      = "./modules/vpc"
  cidr_block  = "10.0.0.0/16"
  name        = "my-vpc"
}
```

- **6. プロバイダ（Provider）による抽象化**
  - AWS、Azure、Google Cloud、Kubernetes など、多様なプロバイダをサポート。
  - クラウド間で共通の記述が可能になり、ベンダーロックインを避けやすくする。

**例：AWSとAzureのプロバイダを利用**

```hcl
provider "aws" {
  region = "us-east-1"
}

provider "azurerm" {
  features {}
}
```

- **7. 変更の自動適用ではなく、手動確認**
  - Terraformは自動的に変更を適用しない（`terraform apply` を明示的に実行する必要がある）。
  - これにより、意図しないインフラの変更を防ぐ。

明示的な `apply` の実行

```hcl
terraform plan
terraform apply -auto-approve  # 確認なしで適用（通常は非推奨）
```

- **8. コミュニティとエコシステム**
  - Terraform Registry による公式・非公式のモジュール提供。
  - Open Source のため、コミュニティによる拡張が活発。

**例：Terraform Registry からRDSモジュールを利用**

```hcl
module "rds" {
  source  = "terraform-aws-modules/rds/aws"
  version = "5.0.0"

  identifier = "mydb"
  engine     = "mysql"
  instance_class = "db.t2.micro"
  allocated_storage = 20
}
```

## まとめ
これまでTerraformをキャッチアップし、50個以上のテンプレートを作成してきましたが、改めて設計思想の根幹を復習することで良い学びとなりました。

:::note warn
**次回は、Terraformのディレクトリ構成について、小規模・中規模・大規模の観点から体系的にまとめていきます。**
:::

今回の内容は個人の備忘録程度ですが、どなたかの学習の参考になれば幸いです。