フューチャー技術ブログ

TFLintを使ってみる(GCP×Terraform)

はじめに

terraform validateterraform planでは検知できないエラーを見つけるために、TFLintを利用してみました。TFLintを用いれば、例えばインスタンスタイプの誤りや命名規約違反を検知できます。

本記事では、インストールから利用方法までを記載しています。

TFLintとは?

いわゆるTerraformのためのLinter。JavaScriptでいうと、ESLintのようなものです。構文やパラメータがルールに違反していないかをチェックしてくれるツールです。

環境やバージョン

今回利用した環境です。

tflintをインストール

  1. tflint/releasesからtflint_windows_amd64.zipをダウンロード
  2. tflint_windows_amd64.zipを解凍
  3. tflint.exeをパスが通ってるところに配置
  4. 以下を実行し、バージョン情報が出たら成功
PowerShell
$ tflint --version

TFLint version 0.34.0

※他OSでのインストール手順は以下を参照ください。

.tflint.hclの作成

.tflint.hcl とは、Pluginをインストールするための設定ファイルです。

今回は、GCPの RuleSet Pluginをインストールする例を記載します。

  • .tflint.hclはホームディレクトリか、カレントディレクトリに配置する必要がある
    • 今回は、ホームディレクトリに配置とする
.tflint.hcl
plugin "google" {
enabled = true
version = "0.15.0"
source = "github.com/terraform-linters/tflint-ruleset-google"
}

※参考

tflint –initの実施

.tflint.hcl を記載したあとに、Pluginをインストールするために、以下のコマンドを実行します。初回のみ実施で問題ないです。

PowerShell
tflint --init

tflintの動作確認をしてみる

  1. google_compute_instancemachine_typeに存在しないインスタンスタイプを記載してみます。
example.tf
resource "google_compute_instance" "gce_test" {
project = "testest"
name = "testtest-gce001"
zone = "asia-northeast1-a"
# ここで存在しないインスタンスタイプを指定
machine_type = "n2-standard-200"
...
}
  1. tflintを実行してみる。そうするとエラーがでます
PowerShell
$ tflint

1 issue(s) found:

Error: "n2-standard-200" is an invalid as machine type (google_compute_instance_invalid_machine_type)

on main.tf line 6:
6: machine_type = "n2-standard-200"

応用:moduleも対象とする

Terraformにはmoduleと呼ばれるカスタムリソースを作る機能があります。詳しくはTerraformerとしてコードを書いて思うことを参照ください。

これをTFLintでチェックするためには、Module Inspectionに記載がある通り、.tflint.hclmodule = trueを追記するだけです。

.tflint.hcl
# add
config {
module = true
}

plugin "google" {
enabled = true
version = "0.15.0"
source = "github.com/terraform-linters/tflint-ruleset-google"
}

応用:ルールを有効化する

TFLintに多くのチェックルールが予め用意されています。どんなルールがあって、どれがデフォルトで有効になっているかは以下に記載があるので確認すると良いでしょう。

今回は例として、「terraform_unused_declarations」を有効化してみます。内容としては、「使っていないlocalsを検知できる」というルールです。

チェックするために、 先程の .tflint.hclterraform_unused_declarationsを追記します。

.tflint.hcl
config {
module = true
}

plugin "google" {
enabled = true
version = "0.15.0"
source = "github.com/terraform-linters/tflint-ruleset-google"
}

# add
rule terraform_unused_declarations {
enabled = true
}

使っていないlocalsを宣言したtfファイルを追加します。

example-valiable.tf
locals {
unused = "test"
}

これに対して、TFLint実行します。ルール違反を検知したことがわかります。どのファイルの何行目に違反があったか表示してくれていますね。

PowerShell
$ tflint

1 issue(s) found:

Warning: local.unused is declared but not used (terraform_unused_declarations)

on example-valiable.tf line 2:
168: unused = "test"

Reference: https://github.com/terraform-linters/tflint/blob/v0.34.0/docs/rules/terraform_unused_declarations.md

利用上の注意点

TFLintを使っていくなかで、注意しなければと思ったものをあげていきます。

1. Local Valuesは評価されない

TFLint skips expressions that reference static local values #571にも記載があります。以下のように不正なインスタンスタイプをlocalsで定義してもエラーにならないです。

example.tf
locals {
machine_type = "n2-standard-200"
}

resource "google_compute_instance" "gce_test" {
project = "testest"
name = "testtest-gce001"
zone = "asia-northeast1-a"
machine_type = local.machine_type
...
}
tflintの実行
$ tflint
# ルール違反を検知できない

2. 利用しているTerraformのバージョンとTFLintを揃える必要がある

Compatibility with Terraformのドキュメントに記載がある通り、TFLintはTerraformを内蔵しています。そのため、利用しているTerraformのバージョンに合わせて、該当バージョンのTFLintを利用する必要がある

直近のバージョン対応表をあげます。

Terraform TFLint
v1.1.0 v0.34.0
v1.0.0 v0.30.0~v0.33.2
v0.15.0 v0.27.0~v0.29.1
v0.14.9 v0.26.0
v0.14.7 v0.25.0

※参考

3. Deep Checkingを利用する場合の注意事項

Deep Checkingは、GCPのAPIを利用してより厳密なチェックを行うことができるオプションです。

以下のようにdeep_check = trueを追加することで、Deep Checkingが有効になります。ただし、serviceusage.googleapis.comが有効になっている必要があります。つまり、PJ作成時(APIが有効になっていない状態)にtflintを実行するとエラーになってしまうのでご注意ください。

.tflint.hcl
plugin "google" {
enabled = true
version = "0.15.0"
source = "github.com/terraform-linters/tflint-ruleset-google"
# add
deep_check = true
}

※Projectは、providerのprojectを参照している

example.tf
provider "google" {
project = "testtest"
}

.tflint.hcl のサンプルを用意したので、TFLintを動かしてみよう

全ルールをenableにした.tflint.hcl をサンプルとして用意しました。全ルールとは以下に記載のあるルールです。

.tflint.hcl
config {
module = true
}

plugin "google" {
enabled = true
version = "0.15.0"
source = "github.com/terraform-linters/tflint-ruleset-google"
deep_check = false
}

rule "terraform_comment_syntax" {
enabled = true
}

rule "terraform_deprecated_index" {
enabled = true
}

rule "terraform_deprecated_interpolation" {
enabled = true
}

rule "terraform_documented_outputs" {
enabled = true
}

rule "terraform_documented_variables" {
enabled = true
}

rule "terraform_module_pinned_source" {
enabled = true
}

rule "terraform_module_version" {
enabled = true
}

rule "terraform_naming_convention" {
enabled = true
}

rule "terraform_required_providers" {
enabled = true
}

rule "terraform_required_version" {
enabled = true
}

rule "terraform_standard_module_structure" {
enabled = true
}

rule "terraform_typed_variables" {
enabled = true
}

rule "terraform_unused_declarations" {
enabled = true
}

rule "terraform_unused_required_providers" {
enabled = true
}

rule "terraform_workspace_remote" {
enabled = true
}

rule "google_composer_environment_invalid_machine_type" {
enabled = true
}

rule "google_compute_instance_invalid_machine_type" {
enabled = true
}

rule "google_compute_instance_template_invalid_machine_type" {
enabled = true
}

rule "google_compute_reservation_invalid_machine_type" {
enabled = true
}

rule "google_container_cluster_invalid_machine_type" {
enabled = true
}

rule "google_container_node_pool_invalid_machine_type" {
enabled = true
}

rule "google_dataflow_job_invalid_machine_type" {
enabled = true
}

rule "google_project_iam_audit_config_invalid_member" {
enabled = true
}

rule "google_project_iam_binding_invalid_member" {
enabled = true
}

rule "google_project_iam_member_invalid_member" {
enabled = true
}

rule "google_project_iam_policy_invalid_member" {
enabled = true
}

実運用上は利用しないルールを、個別にdisableにし、検知結果に対して運用が回るように調整していくことが重要かなと思います。

まとめ

TFLintを使うことで、terraform validateterraform planで検知できないエラーを見つけることができました。

RuleSetに限りがあるので全エラーを検知できるとまでいきませんが、TFLintを導入することでterraform applyで失敗するケースが減っていくと考えています。