【Terraform】Terraform ~ tfstate / Backend ~

■ はじめに

https://dk521123.hatenablog.com/entry/2023/04/20/172823

において、
エラー「AlreadyExistsException: Workflow with name 'xxx-xxxx' already Exists」
について、ひとまずの回避案を提示したが、ちゃんとした解決案が分かった。
その解決案に、tfstateファイルってのが深くかかわってくるので、メモ。

目次

【1】前提知識:Terraformの環境への適用の仕方について
【2】tfstateファイル
【3】目的
【4】terraform init コマンドでの生成物について
【5】tfstateファイル関連のコマンド
 1)terraform state
【6】Terraform Backend
 0)前提知識:tfstateファイルの管理場所
 1)terraform init -backend-cnfig
 2)その他Tips

【1】前提知識:Terraformの環境への適用の仕方について

 terraform では、
terrafrom apply の後に、再度、terrafrom apply を行うと、
前回までの差分のみを適用して、実行される
 => この前回の状態などを保持する役割をするものが
  「tfstateファイル (TerraForm State;Terraform状態ファイル)」になる

【2】tfstateファイル

* Terraformが管理しているリソースの現在の状態を表すファイル
* 形式は、JSON
* デフォルトのファイル名は、「terraform.tfstate」

https://qiita.com/masaaania/items/0ed291b267032a7699ad

【3】目的

* 「terraform plan」を実行した場合、現在の状態との差分が表示されるが
 これは、tfstateファイルに記述されている現在の状態と
 HCLで記述された定義との差分で表示する
 => 詳細は、以下の公式ドキュメントを参照のこと。

https://developer.hashicorp.com/terraform/language/state/purpose

【4】terraform init コマンドでの生成物について

* tfstateファイルを含む terraform init コマンドでの生成物について説明する

[1] .terraformディレクト

* terraformがキャッシュされたプラグインとモジュールを
 管理するディレクトリ

[2] .tfstateファイル

* Terraformによって作成された現在の構成状態を記録してあるファイル
 => ★今回のテーマ★

[3] .terraform.lock.hclファイル

* プロバイダーとモジュールの依存関係や互換性が記録

https://rurukblog.com/post/terraform-lock-hcl/

【5】tfstateファイル関連のコマンド

1)terraform state

Command Explanation Memo
terraform state list 使用しているリソースを一覧表示
terraform state mv State内のリソース名を変更
terraform state rm . リソースをTerraformの管理から外す ★お勧め★
terraform state pull 現在のStateをBackendからダウンロードし、表示
terraform state push ローカルのStateファイルをリモートのBackendにアップロードする
terraform state show リソースの詳細を表示 terraform showコマンドのリソース指定版

[1] terraform state list
https://developer.hashicorp.com/terraform/cli/commands/state/list

[2] terraform state rm
https://developer.hashicorp.com/terraform/cli/commands/state/rm

* Stateファイルで管理されているリソースを削除(除外)する

https://zenn.dev/toritori0318/articles/983bd73e2d2158

にあるように、不整合が起きて、
terrraform refresh しても
状況が変わらない時に、使用したら解決できた。

【6】Terraform Backend

* Terraformのtfstateを管理するストレージを「Backend(バックエンド)」と呼ぶ

https://developer.hashicorp.com/terraform/language/settings/backends/configuration

0)前提知識:tfstateファイルの管理場所

* デフォルトでは、ローカルに生成される
 => 1人で開発している場合であればローカルでもいいが(それでもダメだが)
  複数で開発していた場合、以下の関連記事で扱ったようなエラーになる等
  トラブルの原因になる

https://dk521123.hatenablog.com/entry/2023/04/20/172823

解決案

* AWSであれば、S3に置く
* 可能であれば、「Terraform Cloud」ってのもあり
 (外部サイトに繋ぐので、できない現場が多いかもしれないが)
 => 利点については、以下のサイトを参照

https://dev.classmethod.jp/articles/terraform_tfstate_management_tfc/

* 「backend "s3"」を指定した後に「terraform init」を実行

https://developer.hashicorp.com/terraform/language/settings/backends/s3

backend.tf

terraform {
  # ★ここに注目★
  backend "s3" {
    bucket  = "your-s3-bucket"
    key     = "tf/dev/terraform.tfstate"
    region  = "us-west-2"
    encrypt = true
  }

1)terraform init -backend-cnfig

terraform init -backend-config="./dev.tfbackend"

dev.tfbackend

bucket  = "your-s3-dev-bucket"
key     = "tf/dev/terraform.tfstate"
region  = "us-west-2"
encrypt = true

別例:Key-value
https://developer.hashicorp.com/terraform/language/settings/backends/configuration#command-line-key-value-pairs

# terraform init時にbackend-configオプションを使う
terraform init \
 -backend-config="bucket=your-prod-s3-bucket"\
 -backend-config="key=tf/prod/terraform.tfstate"

main.tf (修正版)

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }

  required_version = ">= 0.14.9"

  backend "s3" {
    # bucket  = "your-s3-bucket"
    # key     = "tf/dev/terraform.tfstate"
    region  = "us-west-2"
    encrypt = true
  }

2)その他Tips

[1] S3をbackendに利用する場合

* S3をbackendに利用する場合、S3のバージョンニング機能を有効にすること

[2] State Locking(複数人での開発のために)

* DynamoDB 使うと実現可能

参考文献

https://zenn.dev/sway/articles/terraform_staple_sharestate
https://techgrowup.net/2022/04/18/terraform%E3%81%A7tfstate%E3%82%92s3%E3%81%A7%E7%AE%A1%E7%90%86%E3%81%99%E3%82%8B/
https://zenn.dev/sway/articles/terraform_staple_sharestate

関連記事

Terraform ~ 環境構築編 ~
https://dk521123.hatenablog.com/entry/2023/04/05/000224
Terraform ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2019/12/09/222057
Terraform ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2023/05/03/000000
Terraform ~ Workspace ~
https://dk521123.hatenablog.com/entry/2024/06/01/144048
Terraform ~ AWS S3 ~
https://dk521123.hatenablog.com/entry/2023/04/09/104204
Terraform ~ AWS IAM ~
https://dk521123.hatenablog.com/entry/2023/04/12/214311
Terraform ~ AWS Glue ~
https://dk521123.hatenablog.com/entry/2023/04/08/220411
Terraform ~ AWS Secrets Manager ~
https://dk521123.hatenablog.com/entry/2023/04/11/152801
Terraform ~ Docker ~
https://dk521123.hatenablog.com/entry/2023/04/10/193239
Terraform ~ 特定リソースのみデプロイする ~
https://dk521123.hatenablog.com/entry/2023/04/20/172823
Terraform ~ 複数環境へデプロイすることを考える ~
https://dk521123.hatenablog.com/entry/2023/05/06/003645
Terraform ~ 機密情報の扱いを考える ~
https://dk521123.hatenablog.com/entry/2023/05/18/005103