Terraformを使うなら！おすすめのツール6選

# はじめに
Terraformは、インフラをコードで管理する「Infrastructure as Code（IaC）」ツールです。まるでプログラミングのようにインフラを記述することで、構築や変更作業を自動化でき、効率的かつ安全に管理できます。

今回は自分がTerraformを使っている中で便利だなと思ったツールたちを紹介していきたいと思います！

# ツール6選
## バージョン・パッケージ管理編
### 1.tenv
Terraformのバージョン管理といえばtfenvでしたが、最近は更新の頻度も落ちてきていてやや不安な状態です。 

https://github.com/tfutils/tfenv/actions

そこで現在のバージョン管理にはtenvがおすすめです。

https://tofuutils.github.io/tenv/

tenvはGoで書かれたオープンソースのバージョン管理ツールです。
Terraformだけでなく、OpenTofu、Terragrunt（後で紹介します）、などの複数のバージョンを容易に管理することが出来ます。

Homebrewにも対応しているのでインストールもお手軽です。

使い方は以下の要領です。
```
tenv <tool> <command>
```
\<tool>に対象のツール名を、\<command>に実行したい内容を指定します。
例えばTerraformのv1.5.4をインストールしたい場合は以下のようになります。
```bash:terraform v1.5.4 インストール
tenv tf install 1.5.4
```
インストール済みのバージョンと現在利用しているバージョンもlistで同時に確認できます。
```bash:tenv list
❯ tenv tf list
  1.5.4 (never used)
  1.6.0 (never used)
* 1.9.4 (used 2024-12-20, set by /home/user/.tenv/Terraform/version)
```

後述のTerragruntも同時に管理できる点や動作が軽量な点がお気に入りポイントです。


### 2.aqua
バージョンの使い分けにも対応しているパッケージ管理ツールとしてacuaを紹介します。

aqua は、Go 言語で記述された宣言型の CLI バージョンマネージャーです。   

https://aquaproj.github.io/

YAML 形式の設定ファイルを用いて、コマンドラインツール (CLI) のバージョンを管理できます。

macOS、windows、Linuxに対応しており、チームやプロジェクトでツールバージョンの統一と管理がとても簡便になります。

使い方は以下のような設定ファイルを用意し、インストールコマンドを実行するだけです。

```yaml
registries:
- type: standard
  ref: v4.281.0 # renovate: depName=aquaproj/aqua-registry
packages:
- name: hashicorp/terraform@v1.10.3
- name: gruntwork-io/terragrunt@v0.71.1
- name: tofuutils/tenv@v3.2.11
```

設定ファイルの作成・編集もコマンドで自動的に行うことが可能です。

また、設定ファイルのバージョンを変更することで、簡単にバージョンを切り替えられます。

上記のような使い方も含めて以下の記事で大変分かりやすく解説されています。（そもそもaquaはとても使いやすいツールですが）

https://zenn.dev/shunsuke_suzuki/books/aqua-handbook/viewer/index

tenv以外にも必要なパッケージを多人数で共有したい場合などはaquaによる管理がおすすめです！

## 作業効率化編
### 3.Terragrunt
Terraformを使ってある程度の規模のインフラを構築していくと、コードの重複、設定の複雑化、環境間の差異など、いくつかの課題が出てくると思います。
そんな課題の解決にビッタリなツールがTerragruntです。

https://terragrunt.gruntwork.io/

TerragruntはTerraformを使っていく中で感じやすい課題に対して、Terraform のラッパーとして機能することで解決することができるツールです。

Terragruntは本当に色々なことができるツールなので、全てを紹介することは難しいですが、ここでは比較的簡単に導入できるDRYなTerraformの管理方法を紹介しようと思います。

下記のようなディレクトリ構成を採用しているとします。
stateファイルをなるべく小さくする意図で、[「詳解 Terraform 第３版 Infrastructure as Codo を実現する」（オライリージャパン:2023）](https://www.oreilly.co.jp/books/9784814400522/)を参考にしています。
```
environment/
├── production
├── stage
└── develop
    ├── vpc
    ├── services
    │   ├── webserver1
    │   │   ├── main.tf
    │   │   ├── provider.tf
    │   │   ├── backend.tf
    │   │   └── variable.tf
    │   └── webserver2
    │       ├── main.tf
    │       ├── provider.tf
    │       ├── backend.tf
    │       └── variable.tf 
    └── database
```
このとき、service配下に新たに"webserver3"を追加する場合、とりあえず"webserver1"や"webserver2"の中のtfファイルをコピペしてから、stateファイルの格納先のプレフィックスを変えていませんか？

リソースなどの部分は注意しているので差分を修正するのですが、backendの部分って忘れてしまって、ついコピペ元と同じstateファイルを読み込んじゃいますよね（私です。)

そんなうっかりを回避するためにTerragruntを利用して、自動で異なるbackend.tfが作成できるようにしてみます。
以下のように"terragrunt.hcl"を配置します。

```
environment/
├── producion
├── stage
└── develop
    ├── terragrunt.hcl　#親設定ファイル
    ├── vpc
    ├── services
    │   ├── webserver1
    │   │   ├── main.tf
    │   │   ├── provider.tf
    │   │   ├── backend.tf
    │   │   └── variable.tf
    │   └── webserver2
    │   │   ├── main.tf
    │   │   ├── provider.tf
    │   │   ├── backend.tf
    │   │   └── variable.tf
    │   └── webserver3
    │       └── terragrunt.hcl # 小設定ファイル
    └── database
```
ファイルの中身は以下です。
```hcl:親設定ファイル
remote_state {
  backend = "s3"
  generate = {
    path      = "backend.tf"
    if_exists = "overwrite"
  }
  config = {
    bucket = "hogehoge"
    key = "${path_relative_to_include()}/terraform.tfstate"
    region = "ap-northeast-1"
  }
}
```
```hcl:小設定ファイル
include "root"{
  path = find_in_parent_folders()
}
```
上記のように配置し、小設定ファイルのあるディレクトリで"terragrunt init"を実行すると、対応したプレフィックスの切られたbackend.tfが自動で生成されます。

```hcl:生成されたbackend.tf
terraform {
  backend "s3" {
    bucket = "hogehoge"
    key    = "webserver3/terraform.tfstate"
    region = "ap-northeast-1"
  }
}
```
今回はbackendの設定だけでしたが、設定ファイルをさらに作り込むことで、provider.tfや共通する変数なども自動で読み込めるようになり、作業がかなり効率的になります！

学習コストは少し高めですが、使いこなせるとどんどんDRYな構成に近づくTerragrunt。
興味を持たれた方はぜひ試してみてください！

### 4.Infracost
InfracostはTerraformのコードから作成されるリソースの費用を計算してくれるツールです。

https://www.infracost.io/

CLIのツールもありますがVSCodeの拡張機能もあり、おおまかにコストを把握したい場合ならこちらで十分だと思います！

https://www.infracost.io/docs/features/vscode/

導入後は以下のように、リソースを記述するとコストが表示されるようになります。
![スクリーンショット 2024-12-21 10.57.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945505/7436e177-9d23-93b7-2c13-6354c4b32c46.png)

リソースの内容を変更し、コストに影響があった場合にも自動で再計算されるので手間いらずです。

こちらのブログ記事で、再計算される動作を確認できますので、興味が湧いた方は確認してみてください。

https://techblog.ap-com.co.jp/entry/2023/11/30/185751

また、呼び出しているモジュールごとのコストも計算してくれるので、システム全体のコストバランスも理解しやすいです。

![スクリーンショット 2024-12-21 11.25.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945505/39834e89-b5ca-50c8-4d30-acfca49b9405.png)

VSCODE版では通信料など、反映されないものもありますが、ざっくりとしたコストを把握するには非常に有用なツールだと思います。

## チェック自動化編
### 5.TFlint
TFLintは、Terraformのファイルをスキャンし、潜在的な問題、ベストプラクティス違反を特定する静的コード解析ツールです。
特にチームで作業を行なっている場合などは、基本的な書式が統一されいないと認知的な負荷が高まり、結果的に重大な事故につながってしまうかもしれません。
しかし、人力でチェックを行う場合だとコード量が多ければ地獄ですし、見逃しも必ず生じてしまいます。

そこでTFLintによって、チェックを自動化してしまいましょう。

https://github.com/terraform-linters/tflint

利用方法は対象のディレクトリで"tflint"コマンドを実行するだけです。

```bash
❯ tflint
1 issue(s) found:

Warning: `network` variable has no type (terraform_typed_variables)

  on variables.tf line 31:
  31: variable "network" {

Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.10.0/docs/rules/terraform_typed_variables.md
```
問題がある場合は問題点とその理由、リファレンスのURLが表示されるので、それらを読み取りながら対応していきましょう。

ちなみに上記は変数networkのtypeが指定されていないよーという警告でした。型重要。

検知するルールについても個別に設定できるので、自分の環境に合わせたチェックが実現できます。

また、各クラウドプロバイダーごとのプラグインもあるので、利用しているプロバイダーに合わせて導入してみてください。

https://github.com/terraform-linters/tflint-ruleset-aws

このTFlintは次のCheckovと合わせてGitHub ActionsなどのCI/CDパイプラインに組み込んで実行されることが多い印象です。
静的コードチェックも自動で行うことによって、より強固なインフラ環境を目指したいところですね。

### 6.Checkov
Checkovは、Terraformのファイルをスキャンし、潜在的な脆弱性を検出するように設計された静的コード解析ツールです。
TFlintと同様の静的なチェックツールですが、こちらはよりセキュリティを重視したチェックとなっています。

https://www.checkov.io/

検出結果例は以下のようになります。

```bash
Check: CKV_AWS_260: "Ensure no security groups allow ingress from 0.0.0.0:0 to port 80"
	FAILED for resource: module.ec2.aws_vpc_security_group_ingress_rule.http
	File: /../../../modules/ec2/main.tf:65-72
	Calling File: /main.tf:1-6
	Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/aws-policies/aws-networking-policies/ensure-aws-security-groups-do-not-allow-ingress-from-00000-to-port-80

		65 | resource "aws_vpc_security_group_ingress_rule" "http" {
		66 |   from_port                    = 80
		67 |   to_port                      = 80
		68 |   ip_protocol                  = "tcp"
		69 |   referenced_security_group_id = data.aws_security_group.ec2.id
		70 |   security_group_id            = aws_security_group.ec2.id
		71 |   description                  = "${var.common.system}-${var.common.env}-sg"
		72 | }
```

これはセキュリティグループのインバウンドルールで、ポート80が全開放されているという警告になります。

より詳細な内容については、Guideに記載されているURLにアクセスすれば確認することができます。
今回だと以下のリンクです。

https://docs.prismacloud.io/en/enterprise-edition/policy-reference/aws-policies/aws-networking-policies/ensure-aws-security-groups-do-not-allow-ingress-from-00000-to-port-80

チェックに引っかかった部分があった場合には、このドキュメントを見ながらリソースを修正すべきか、Checkovのチェックから除外するかを検討するといった流れになります。

最終的には、意図的に除外したものを除き、全てのチェックが成功した状態でリソースをデプロイできることが理想です。

Checkovは公式でGitHub Actionsのアクションも用意してくれているので、CI/CDへの導入ハードルも低いかと思います！

https://www.checkov.io/4.Integrations/GitHub%20Actions.html

# まとめ
今回は自分がTerraformを使っている中で便利と感じたツールについて紹介しました。

全部知っているよ！という人も多いとは思いますが、まとめておくと環境を新しく構築するときに便利なので備忘録も兼ねて書いてみました。

このほかにもこんなツールがあるよー、このツールにはこんな使い方があるよー、という場合は教えていただけると嬉しいです！