stateファイル(tfstate)をS3からTerraform Cloudに移行してみる

2023.02.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

「tfstateはTerraform Cloudで管理したいな。どうやって移行すればいいんだろう。」

AWSで Terraformを使っていると、stateファイル管理用のリソース(S3やDynamoDB)が増えてきて管理が大変になることがあると思います。

そんな時はTerraform Cloudでstateファイルを管理すると楽です。

Terraform Cloudで管理することで、stateファイル管理用のリソースを自分で作成する必要がなくなります。 ちなみに、stateファイルの管理自体はFreeプランでも可能です。

今回は、stateファイルの管理をS3からTerraform Cloudに移行してみます。

やってみた

移行前(stateファイルをS3管理)

検証用にstateファイルをS3管理するパターンでAWSリソースを作ってみました。

main.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
  backend "s3" {
    bucket         = "terraform-state-sample"
    key            = "terraform.tfstate"
    region         = "ap-northeast-1"
    encrypt        = true
    dynamodb_table = "terraform-state-sample"
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_vpc" "example" {
  cidr_block = "10.0.0.0/16"
}

VPCを作成するといった内容のサンプルコードです。

コードが用意できたら、initとplanでデプロイの準備と確認をします。

$ terraform init
$ terraform plan
  # aws_vpc.example will be created
  + resource "aws_vpc" "example" {
      + arn                                  = (known after apply)
      + cidr_block                           = "10.0.0.0/16"
      + default_network_acl_id               = (known after apply)
      + default_route_table_id               = (known after apply)
      + default_security_group_id            = (known after apply)
      + dhcp_options_id                      = (known after apply)
      + enable_classiclink                   = (known after apply)
      + enable_classiclink_dns_support       = (known after apply)
      + enable_dns_hostnames                 = (known after apply)
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = (known after apply)
      + id                                   = (known after apply)
      + instance_tenancy                     = "default"
      + ipv6_association_id                  = (known after apply)
      + ipv6_cidr_block                      = (known after apply)
      + ipv6_cidr_block_network_border_group = (known after apply)
      + main_route_table_id                  = (known after apply)
      + owner_id                             = (known after apply)
      + tags_all                             = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.
aws_vpc.example: Creating...
aws_vpc.example: Creation complete after 2s [id=vpc-XXXXXX]

planの結果が問題なかったので、applyしてリソースを作成します。

$ terraform apply

S3バケットを見てみると、tfstateが存在することを確認できました。

$ aws s3 ls s3://terraform-state-sample
2023-02-07 13:46:54       1746 terraform.tfstate

Terraform Cloud ログイン

ここからは、Terraform Cloudにstateを移行する作業を行っていきます。

まだ、Terraform CloudのOrganizationがない場合は、以下サイトからOrganizationを作成します。

https://app.terraform.io/signup/account

アカウント作成とOrganization作成は以下の記事をみるとイメージがつくと思います。

Terraform Cloudの始め方 - Qiita

Organization作成して、Terraform Cloudのログインまで出来たら次の手順に進みます。

tfファイルの修正

cloudブロックを追加して、backend "s3"のブロックを削除します。

main.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
  cloud {
    organization = "[Organization名]"
    hostname = "app.terraform.io"

    workspaces {
      name = "[Workspace名]"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_vpc" "example" {
  cidr_block = "10.0.0.0/16"
}

Terraform Cloudログイン(CLI)

ローカルからTerraform Cloudを利用するために、コマンドを実行してログインします。

$ terraform login

Terraform Cloudへのstateファイル移行

準備が整ったらterraform initでバックエンドの設定変更を適用します。

$ terraform init

コマンドを実行すると以下のように移行の確認メッセージが表示されます。

Initializing Terraform Cloud...
Migrating from backend "s3" to Terraform Cloud.
Do you wish to proceed?
  As part of migrating to Terraform Cloud, Terraform can optionally copy your
  current workspace state to the configured Terraform Cloud workspace.
  
  Answer "yes" to copy the latest state snapshot to the configured
  Terraform Cloud workspace.
  
  Answer "no" to ignore the existing state and just activate the configured
  Terraform Cloud workspace with its existing state, if any.
  
  Should Terraform migrate your existing state?

  Enter a value:

yesを入力します。

今回は移行のため、S3にある既存のstateファイルをTerraform Cloudにコピーする必要があるのでyesを選択します。

この時点で自動的にTerraform Cloud上でtfファイルで指定した名前でWorkspaceが作成されます。

作成されたWorkspace -> States をみてみるとstateファイルが移行されたことを確認できます。

移行の確認メッセージで間違ってnoを選んだ場合

ちなみに、noを選択すると新規にstateファイルを作成します。

この場合、stateファイルが別になります。既存とは別にリソースが作成されます。今回だったら、もう1つVPCが作成されます。

誤って一度noを選択した場合は、以下の手順を踏むことで移行をやり直せます。

  1. .terraformディレクトリの削除
  2. tfファイルのbackendの記述をS3に戻す
  3. terraform initを実行(この時点でS3 Backendに戻る)
  4. terraform plan で差分がないことを確認
  5. tfファイルのbackendの記述をTerraform Cloudに変更
  6. terraform init実行・移行の確認メッセージが表示される

Terraform CloudのWorkspaceの設定

デフォルトではWorkspaceにAWS認証情報を設定されていないため、ローカルからterraform planを実行した際にエラーになります。

IAMアクセスキーまたはIAMロールをWorkspaceに設定する必要があります。

IAMロールを使う場合は、以下が参考になります。

設定後、planを実行出来ました。 結果はNo changesになっていたため、無事に移行できているようです。

$ terraform plan
~~ 省略 ~~
No changes. Your infrastructure matches the configuration.

自動で作成されたWorkspaceにはVCSやProjectが未設定のため、必要に応じて設定してください。

おわりに

Terraform BackendをS3からTerraform Cloudに移行する方法でした。

S3からTerraform Cloudに移行することで、Backend用のリソースの運用負荷を軽減できます。

Backend用のリソースの管理が辛いと感じている方は、是非お試しください。

以上、AWS事業本部の佐藤(@chari7311)でした。