Terraform ステート管理

LinuxBeginner
オンラインで実践に進む

はじめに

Terraform は、管理対象のインフラストラクチャに関する情報を格納するためにステートファイルを使用します。このステートファイルは、設定ファイルで定義されたリソースと現実世界のリソースをマッピングするため、極めて重要です。このステートを維持することにより、Terraform はどのリソースを作成、更新、または破棄するかを判断できます。

この実験(Lab)では、Terraform のステートを管理する実践的な経験を積みます。ここでは、さまざまな terraform state サブコマンドを使用して、現在のステートの検査、管理されているリソースの一覧表示、ステート内でのリソース名の変更、および実際のインフラストラクチャと整合させるためのステートの更新(リフレッシュ)方法を学びます。これらは、すべての Terraform ユーザーにとって基本的なスキルです。

terraform show で現在のステートを表示する

このステップでは、terraform show コマンドを使用して現在のステートを表示する方法を学びます。このコマンドは、ステートファイルに記録されている、Terraform が現在管理しているリソースの人間が読み取り可能な出力を提供します。これは、インフラストラクチャのステートを検査するための安全な読み取り専用の方法です。

この実験(Lab)のセットアップスクリプトは、すでに Terraform を初期化し、リソースを作成して terraform.tfstate ファイルを生成しています。これを検査してみましょう。

ターミナルで次のコマンドを実行します。

terraform show

Terraform が管理している local_file リソースを説明する詳細な出力が表示されます。

## local_file.example:
resource "local_file" "example" {
    content              = "This is an example file managed by Terraform."
    content_base64sha256 = "F5EYZhFNzSXdE4CUftwQoDVqvdiufZpVyiLMqyZVOcQ="
    content_base64sha512 = "m1hvaxMuc/EhaKintyI54NSTTJ5yXpqHPCBNoHubF0rvF3JAj36lMj20aPcv21+3/OK+SqkiTlnT/LdvLCwqDA=="
    content_md5          = "a43bdd236c2f0f4d87452ba2ef0867e4"
    content_sha1         = "ec3adcab998872def2df6200fb03992ac6f237a4"
    content_sha256       = "17911866114dcd25dd1380947edc10a0356abdd8ae7d9a55ca22ccab265539c4"
    content_sha512       = "9b586f6b132e73f12168a8a7b72239e0d4934c9e725e9a873c204da07b9b174aef1772408f7ea5323db468f72fdb5fb7fce2be4aa9224e59d3fcb76f2c2c2a0c"
    directory_permission = "0777"
    file_permission      = "0777"
    filename             = "./example.txt"
    id                   = "ec3adcab998872def2df6200fb03992ac6f237a4"
}

この出力は、Terraform が local_file.example という 1 つのリソースを認識しており、そのすべての属性がリストされていることを確認します。

ステートファイル terraform.tfstate の検査

このステップでは、生のステートファイルである terraform.tfstate を検査します。terraform show はユーザーフレンドリーな表示を提供しますが、生の JSON ファイルを見ることで、Terraform がどのようにデータを格納しているかを理解するのに役立ちます。

警告: terraform.tfstate ファイルを手動で編集することは、ほとんどの場合避けるべきです。不適切な変更はステートを破損させ、深刻な問題を引き起こす可能性があります。ここでは教育目的でのみ表示します。

cat コマンドを使用して、ステートファイルの内容を表示します。

cat terraform.tfstate

出力は JSON オブジェクトになります。これには、Terraform のバージョンなどのメタデータと、最も重要な resources の配列が含まれています。

{
  "version": 4,
  "terraform_version": "1.13.3",
  "serial": 1,
  "lineage": "2a568739-a81d-ced7-dee1-7a92a1666022",
  "outputs": {},
  "resources": [
    {
      "mode": "managed",
      "type": "local_file",
      "name": "example",
      "provider": "provider[\"registry.terraform.io/hashicorp/local\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "content": "This is an example file managed by Terraform.",
            "content_base64sha256": "...",
            "content_base64sha512": "...",
            "content_md5": "...",
            "content_sha1": "...",
            "content_sha256": "...",
            "content_sha512": "...",
            "directory_permission": "0777",
            "file_permission": "0777",
            "filename": "./example.txt",
            "id": "ec3adcab998872def2df6200fb03992ac6f237a4",
            "sensitive_content": null,
            "source": null
          },
          "sensitive_attributes": [
            [
              {
                "type": "get_attr",
                "value": "sensitive_content"
              }
            ]
          ],
          "identity_schema_version": 0
        }
      ]
    }
  ],
  "check_results": null
}

この生データが、Terraform が実行計画(execution plan)を作成するために使用するものです。

リソース一覧表示のために terraform state list を実行

このステップでは、terraform state list を使用して、ステート内のすべてのリソースの簡潔なリストを取得します。インフラストラクチャが大きくなり、数十または数百のリソースを持つ場合、terraform show は冗長になりすぎる可能性があります。state list コマンドは、リソースアドレスの単純な改行区切りのリストを提供します。

ターミナルで次のコマンドを実行します。

terraform state list

出力は非常に直接的で、作成したリソースのアドレスのみが表示されます。

local_file.example

このコマンドは、スクリプト作成時や、他のコマンドで特定のターゲットを指定する必要がある場合に、特定のリソースアドレスを素早く特定するのに非常に役立ちます。

リソース名を変更するために terraform state mv を使用

このステップでは、terraform state mv を使用してステートファイル内のリソース名を変更する方法を学習します。これは、Terraform コードをリファクタリングする際によくある作業です。.tf ファイル内のリソースブロックの名前を変更すると、Terraform は古いリソースを破棄し、新しいリソースを作成したいと見なします。state mv コマンドを使用すると、コードの変更に合わせてステートファイルを更新し、不要な破棄と作成を防ぐことができます。

まず、設定ファイル内のリソース名を変更します。nano エディタで main.tf を開きます。

nano main.tf

リソース名を example から example_renamed に変更します。ファイルは次のようになるはずです。

resource "local_file" "example_renamed" {
  content  = "This is an example file managed by Terraform."
  filename = "${path.module}/example.txt"
}

Ctrl+X、次に Y、そして Enter を押して保存して終了します。

次に、Terraform が実行しようとしていることを確認するために terraform plan を実行します。

terraform plan

プランでは、Terraform が local_file.example を破棄し、local_file.example_renamed を作成しようとしていることが示されます。これは望ましい動作ではありません。

local_file.example: Refreshing state... [id=ec3adcab998872def2df6200fb03992ac6f237a4]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create
  - destroy

Terraform will perform the following actions:

  ## local_file.example will be destroyed
  ## (because local_file.example is not in configuration)
  - resource "local_file" "example" {
      - content              = "This is an example file managed by Terraform." -> null
      - content_base64sha256 = "F5EYZhFNzSXdE4CUftwQoDVqvdiufZpVyiLMqyZVOcQ=" -> null
      - content_base64sha512 = "m1hvaxMuc/EhaKintyI54NSTTJ5yXpqHPCBNoHubF0rvF3JAj36lMj20aPcv21+3/OK+SqkiTlnT/LdvLCwqDA==" -> null
      - content_md5          = "a43bdd236c2f0f4d87452ba2ef0867e4" -> null
      - content_sha1         = "ec3adcab998872def2df6200fb03992ac6f237a4" -> null
      - content_sha256       = "17911866114dcd25dd1380947edc10a0356abdd8ae7d9a55ca22ccab265539c4" -> null
      - content_sha512       = "9b586f6b132e73f12168a8a7b72239e0d4934c9e725e9a873c204da07b9b174aef1772408f7ea5323db468f72fdb5fb7fce2be4aa9224e59d3fcb76f2c2c2a0c" -> null
      - directory_permission = "0777" -> null
      - file_permission      = "0777" -> null
      - filename             = "./example.txt" -> null
      - id                   = "ec3adcab998872def2df6200fb03992ac6f237a4" -> null
    }

  ## local_file.example_renamed will be created
  + resource "local_file" "example_renamed" {
      + content              = "This is an example file managed by Terraform."
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "./example.txt"
      + id                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 1 to destroy.

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

これを修正するために、リソースを移動しただけであることを Terraform に伝えます。古いアドレスと新しいアドレスを指定して terraform state mv コマンドを実行します。

terraform state mv local_file.example local_file.example_renamed

確認メッセージが表示されます。

Move "local_file.example" to "local_file.example_renamed"
Successfully moved 1 object(s).

ここで、再度 terraform plan を実行します。

terraform plan

今度は、ステートが設定と一致しているため、Terraform は変更が必要ないことを報告します。

local_file.example_renamed: Refreshing state... [id=ec3adcab998872def2df6200fb03992ac6f237a4]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

ステートを更新するために terraform refresh を実行

このステップでは、terraform refresh を使用して、ステートファイルと実際のインフラストラクチャを照合する方法を学習します。インフラストラクチャに変更が加えられることがありますが、それは Terraform の制御外で行われる場合があります。これは「ドリフト (drift)」として知られています。refresh コマンドは、これらの変更を反映するようにステートファイルを更新します。

Terraform が作成したファイルを手動で削除することにより、ドリフトをシミュレートしてみましょう。

rm example.txt

ここで、プランを実行すると、Terraform はファイルが存在しないこと、再作成が必要であることを検出します。

terraform plan
local_file.example_renamed: Refreshing state... [id=ec3adcab998872def2df6200fb03992ac6f237a4]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  ## local_file.example_renamed will be created
  + resource "local_file" "example_renamed" {
      + content              = "This is an example file managed by Terraform."
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "./example.txt"
      + id                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

しかし、terraform refresh コマンドは、ステートを明示的に更新するためにも使用できます。このコマンドは実際のリソースをチェックし、それに応じてステートファイルを更新します。

terraform refresh
local_file.example_renamed: Refreshing state... [id=ec3adcab998872def2df6200fb03992ac6f237a4]

ステートが最新であることを確認するために、再度 terraform plan を実行します。

terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  ## local_file.example_renamed will be created
  + resource "local_file" "example_renamed" {
      + content              = "This is an example file managed by Terraform."
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "./example.txt"
      + id                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

terraform refresh を使用してステートドリフトを正常に修正しました。

まとめ

Terraform ステート管理に関するこの実験(Lab)の完了、おめでとうございます!

この実験(Lab)では、必須の terraform state サブコマンドに関する実践的な経験を積みました。以下の方法を学習しました。

  • terraform show を使用して、インフラストラクチャのステートの人間が読みやすい表現を表示する方法。
  • 生の terraform.tfstate JSON ファイルを検査して、その構造を理解する方法。
  • terraform state list を使用して、管理されているすべてのリソースのクリーンなリストを取得する方法。
  • 設定内のリソースを安全に名前変更し、それに応じてステートを更新するために terraform state mv を使用する方法。
  • terraform refresh を使用してステートファイルを実際のインフラストラクチャと照合し、ドリフトを修正する方法。

これらのコマンドを習得することは、Terraform を使用してインフラストラクチャを効果的かつ自信を持って管理するための基本となります。