Closed13

tfstateファイルを読んでみる

not75743not75743

terraformのリソースの状態はterraform.tfstateファイルに保存されています。
いままでスルーしてきたのですが、今回はこれを読んでみようと思います

not75743not75743

題材

これをapplyしました

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

provider "aws" {
  region = "ap-northeast-1"
  default_tags {
    tags = {
      env       = "test"
      provision = "terraform"
    }
  }
}

resource "aws_s3_bucket" "s3" {
}
not75743not75743

terraform.tfstateの中身

よくわからんですね

{
  "version": 4,
  "terraform_version": "1.4.6",
  "serial": 1,
  "lineage": "d16af0bd-c329-ff5e-25d3-ae6de0058ef2",
  "outputs": {},
  "resources": [
    {
      "mode": "managed",
      "type": "aws_s3_bucket",
      "name": "s3",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "acceleration_status": "",
            "acl": null,
            "arn": "arn:aws:s3:::terraform-xxxxxxxxxxxxxxxxxxxxxxxxxx",
            "bucket": "terraform-xxxxxxxxxxxxxxxxxxxxxxxxxx",
            "bucket_domain_name": "terraform-xxxxxxxxxxxxxxxxxxxxxxxxxx.s3.amazonaws.com",
            "bucket_prefix": "terraform-",
            "bucket_regional_domain_name": "terraform-xxxxxxxxxxxxxxxxxxxxxxxxxx.s3.ap-northeast-1.amazonaws.com",
            "cors_rule": [],
            "force_destroy": false,
            "grant": [
              {
                "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                "permissions": [
                  "FULL_CONTROL"
                ],
                "type": "CanonicalUser",
                "uri": ""
              }
            ],
            "hosted_zone_id": "xxxxxxxxxxxx",
            "id": "terraform-xxxxxxxxxxxxxxxxxxxxxxxxxx",
            "lifecycle_rule": [],
            "logging": [],
            "object_lock_configuration": [],
            "object_lock_enabled": false,
            "policy": "",
            "region": "ap-northeast-1",
            "replication_configuration": [],
            "request_payer": "BucketOwner",
            "server_side_encryption_configuration": [
              {
                "rule": [
                  {
                    "apply_server_side_encryption_by_default": [
                      {
                        "kms_master_key_id": "",
                        "sse_algorithm": "AES256"
                      }
                    ],
                    "bucket_key_enabled": false
                  }
                ]
              }
            ],
            "tags": null,
            "tags_all": {
              "env": "test",
              "provision": "terraform"
            },
            "timeouts": null,
            "versioning": [
              {
                "enabled": false,
                "mfa_delete": false
              }
            ],
            "website": [],
            "website_domain": null,
            "website_endpoint": null
          },
          "sensitive_attributes": [],
          "private": "xxxxxxxxxxxx"
        }
      ]
    }
  ],
  "check_results": null
}
not75743not75743

destroy後

destroyした後のtfstateがこちら

{
  "version": 4,
  "terraform_version": "1.4.6",
  "serial": 3,
  "lineage": "d16af0bd-c329-ff5e-25d3-ae6de0058ef2",
  "outputs": {},
  "resources": [],
  "check_results": null
}
~```
not75743not75743

再度applyする

もう一度applyします。
attributesはリソースのパラメータなので最初のtfstateともちろん異なっていますが、それ以外はserialのみ2ずつインクリメントされているようです。
lineageも変化していません。

{
  "version": 4,
  "terraform_version": "1.4.6",
- "serial": 1,
+ "serial": 5,
  "lineage": "d16af0bd-c329-ff5e-25d3-ae6de0058ef2",
  "outputs": {},
  "resources": [
    {
      "mode": "managed",
      "type": "aws_s3_bucket",
      "name": "s3",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "acceleration_status": "",
            "acl": null,
            "arn": "arn:aws:s3:::terraform-xxxxxxxxxxxxxxxxxxxxxxxxxx",
            "bucket": "terraform-xxxxxxxxxxxxxxxxxxxxxxxxxx",
            "bucket_domain_name": "terraform-xxxxxxxxxxxxxxxxxxxxxxxxxx.s3.amazonaws.com",
            "bucket_prefix": "terraform-",
            "bucket_regional_domain_name": "terraform-xxxxxxxxxxxxxxxxxxxxxxxxxx.s3.ap-northeast-1.amazonaws.com",
            "cors_rule": [],
            "force_destroy": false,
            "grant": [
              {
                "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                "permissions": [
                  "FULL_CONTROL"
                ],
                "type": "CanonicalUser",
                "uri": ""
              }
            ],
            "hosted_zone_id": "xxxxxxxxxxxx",
            "id": "terraform-xxxxxxxxxxxxxxxxxxxxxxxxxx",
            "lifecycle_rule": [],
            "logging": [],
            "object_lock_configuration": [],
            "object_lock_enabled": false,
            "policy": "",
            "region": "ap-northeast-1",
            "replication_configuration": [],
            "request_payer": "BucketOwner",
            "server_side_encryption_configuration": [
              {
                "rule": [
                  {
                    "apply_server_side_encryption_by_default": [
                      {
                        "kms_master_key_id": "",
                        "sse_algorithm": "AES256"
                      }
                    ],
                    "bucket_key_enabled": false
                  }
                ]
              }
            ],
            "tags": null,
            "tags_all": {
              "env": "test",
              "provision": "terraform"
            },
            "timeouts": null,
            "versioning": [
              {
                "enabled": false,
                "mfa_delete": false
              }
            ],
            "website": [],
            "website_domain": null,
            "website_endpoint": null
          },
          "sensitive_attributes": [],
          "private": "xxxxxxxxxxxx"
        }
      ]
    }
  ],
  "check_results": null
}
not75743not75743

outputを追加する

このように追加しました

resource "aws_s3_bucket" "s3" {
}

+output "s3_bucket_domain_name" {
+  value = aws_s3_bucket.s3.bucket_domain_name
+}

tfstateは

{
  "version": 4,
  "terraform_version": "1.4.6",
  "serial": 6,
  "lineage": "d16af0bd-c329-ff5e-25d3-ae6de0058ef2",
  "outputs": {
    "s3_bucket_domain_name": {
      "value": "terraform-xxxxxxxxxxxxxxxxxxxxxxxxxx.s3.amazonaws.com",
      "type": "string"
    }
  },
  "resources": [
    {
      "mode": "managed",
      "type": "aws_s3_bucket",
      "name": "s3",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
// 略

outputsに値が格納され、serialには1インクリメントされました(?)

not75743not75743

dataを追加する

適当に転がっていたEC2をdataで追加してみます。

resource "aws_s3_bucket" "s3" {
}

+data "aws_instance" "foo" {
+  instance_id = "i-xxxxxxxxxxx"
+}

tfstateは

{
  "version": 4,
  "terraform_version": "1.4.6",
  "serial": 7,
  "lineage": "d16af0bd-c329-ff5e-25d3-ae6de0058ef2",
  "outputs": {
    "s3_bucket_domain_name": {
      "value": "terraform-xxxxxxxxxxxxxxxxxxxxxxxxxx.s3.amazonaws.com",
      "type": "string"
    }
  },
  "resources": [
    {
      "mode": "data",
      "type": "aws_instance",
      "name": "foo",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
// 略
    {
      "mode": "managed",
      "type": "aws_s3_bucket",
      "name": "s3",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
// 略

modedataであるEC2リソースが追加され、serialに1インクリメントされました

not75743not75743

まとめ

疲れたのでまとめます

seriallineage

  • serial:tfstateの変更回数。
    outputでdataを追加した場合は1,applyで変更した場合は2インクリメントされました。
  • lineage:環境に対して払い出されるUUID。
    最初のterraform init時に確定され、applyしても変化しない。

この2つでterraformは状態を管理していると思われます

2つについて説明しているディスカッションがこちら
https://discuss.hashicorp.com/t/terraform-state-schema/48660/2

not75743not75743

所感

わからないことはまだまだ多いですが、
serialがapply毎に変化するという点から、バックエンドでバージョン管理を行うのが大事なんだなあ
とざっくり思いました。

次回はtfstate周りのcliコマンドを試してみたいと思う

このスクラップは2023/06/17にクローズされました