NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

注目のタグ

    TerraformのState Lockについて触ってみた(AWS, Terraform v1.11)

    クラウド事業推進部の石倉です。

    Terraform、使ってますか?
    私は仕事ではネットコムに入ってから使うようになりました。

    個人でTerraformを使っていた時は気にしていなかったのですが、チームでTerraformを使って開発をしていくようになり出くわしたのが今回のState Lockです。

    State Lockは作成されるリソースとstateファイルの整合性を保つためのものだと認識していますが、改めて自分で触ってみたのでまとめてみました。

    State Lockとは

    チームでTerraformを使って開発する場合、stateファイルをAWSであればS3などの共有ストレージで管理することになっていきます。
    そこで起きるのが、複数人で開発を進めている中で場合によっては同じタイミングでTerraformの作業を実行するということです。 そうするとstateファイルの更新タイミングが重複して、予期せぬ挙動を起こす場合があります。
    それを防ぐためのものがState Lockです。 State Lockをしないとどうなるのか、実際に手を動かして試してみます。

    Terraform v1.11では、S3を使用する際のState LockにDynamoDBの設定がいらず、use_lockfileの設定をするだけで良くなっているので今回はその方法で試しています。

    developer.hashicorp.com

    再現準備

    • 端末はMacを使用しています
    • Terraformのバージョンは1.11です
    • stateファイルの置き先はS3を使用します
    • コードはシンプルにRDSを1つ作成するだけの内容です
    terraform {
      required_providers {
        aws = {
          source  = "hashicorp/aws"
          version = "~> 5.0"
        }
      }
      
      backend "s3" {
        bucket         = "dev-s3-ishikura"
        key            = "ishikura-tfstate"
        region         = "ap-northeast-1"
      }
    }
    
    provider "aws" {
      region = "ap-northeast-1"
    }
    
    resource "aws_db_instance" "default" {
      allocated_storage    = 10
      db_name              = "mydb"
      engine               = "mysql"
      engine_version       = "8.0"
      instance_class       = "db.t3.micro"
      username             = "foo"
      password             = "foobarbaz"
      parameter_group_name = "default.mysql8.0"
      skip_final_snapshot  = true
    }

    State Lockを有効にしなかった場合

    State Lockを有効にしないで複数のところからTerraform作業が同じタイミングで発生した場合を見てみます。

    まずMacのターミナルを2つ立ち上げ、上記のコードで各ターミナルでterraform applyコマンドを実行します。

    各ターミナルでyesを押下しリソースを作成します。
    するとそれぞれでRDSが作られていることが確認できます。(作成されているRDSのidが違いますね)

    コンソール上でもRDSが2つ作られています。

    ではstateファイルを見てみます。
    S3バケットからstateファイルをダウンロードし確認してみると、どちらか一方の情報しか保存されていないことが確認できるかと思います。

    {
      ...(略)
      "resources": [
        どちらか一方の1つ分のRDSの情報しかない
      ],
      ...(略)
    }

    このようにState Lockを有効にしていない場合、Terraform作業が同じタイミングで行われた時に、作成されるリソースとstateファイルの整合性が取れなくなる可能性があります。

    次の作業に行く前にterraform destroyでRDSリソースを削除しておきます。
    片方はstateファイルで管理されていないため、手動で削除する必要があります。

    State Lockを有効にした場合

    ではState Lockを有効にしてみましょう。 コードにuse_lockfileの設定を足します。

    terraform {
      required_providers {
        aws = {
          source  = "hashicorp/aws"
          version = "~> 5.0"
        }
      }
    
      backend "s3" {
        bucket       = "dev-s3-ishikura"
        key          = "ishikura-tfstate"
        region       = "ap-northeast-1"
        use_lockfile = true  // 追加
      }
    }
    
    ...(略)

    この状態で先ほどと同じように、Macのターミナルを2つ立ち上げ、各ターミナルでterraform applyコマンドを実行し、yesを押下します。

    Tip
    この時、stateファイルの管理方法の設定を変更したことで、terraform init -migrate-stateterraform init -reconfigureのどちらかを実行してください、というようなエラーになるかと思いますが、今回はどちらでも大丈夫です。

    するとどうでしょうか。
    片方のターミナルでは以下のようにterraform applyができなくなっているかと思います。

    │ Error: Error acquiring the state lock
    │ 
    │ Error message: xxxxxxxxxxxxxxxxxxxx
    │ Lock Info:
    │   ID:        xxxxxxxxxxxxxxxxxxxx
    │   Path:      dev-s3-ishikura/ishikura-tfstate
    │   Operation: OperationTypeApply
    │   Who:       xxxxxxxxxxxxxxxxxxxx
    │   Version:   1.11.3
    │   Created:   2025-03-30 08:51:03.485744 +0000 UTC
    │   Info:      
    │ 
    │ 
    │ Terraform acquires a state lock to protect the state from being written
    │ by multiple users at the same time. Please resolve the issue above and try
    │ again. For most commands, you can disable locking with the "-lock=false"
    │ flag, but this is not recommended.

    最初にterraform applyをした時点でロックがかかります。(S3にlockファイルが作成されます)
    後からterraform applyを行おうとした方はロックがかかっているため、ロックが終わるまでapplyできないというわけです。

    terraform applyできた方でリソースを作成し終わると、S3のlockファイルが削除されます。
    その後もう片方でterraform applyすると、上記のエラーは出なくなり、既にリソースは作成されているため、変更を加える必要がないと表示されます。

    aws_db_instance.default: Refreshing state... [id=db-2FW7M7JR574ELXGUSW6AZOLRQE]
    
    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.
    
    Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

    State Lockを有効にすることでこのようにして、作成されるリソースとstateファイルの整合性を保つことができます。

    最後に

    仕事で出くわした「なんだろうこれ?」について、改めて自分で手を動かしてみると、より深く自分の腑に落ちる気がしました。
    TerraformのState Lockについて、どなたかの理解の参考になれば幸いです。