3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

terraform.tfstateをローカルやS3で管理する方法

Last updated at Posted at 2020-07-22

はじめに

Terraformを使っていた際に、ローカルやS3でterraform.tfstateを管理する方法に結構つまづきました。
そのため管理する各場所に対し、どんなコードを書いたりコマンドを実行したりするのかまとめました。

つまづきと解決

※管理方法のみを見たい人は、この項目はスキップしてください。

つまづき

いろんなサイトでterraform.tfstateを管理する方法が記載してあったため、それらのサイトを基に、S3のバケットで保存する方法を試していました。その際、紹介されていたコマンド(terrafrom init)を実行しても、S3のバケット内にterraform.tfstateが作成されませんでした。

なぜだろうと考え、以下2つの視点で原因を探りました。

  1. 誰かが経験したかもしれないのでGitHub Issueやブログ等を確認する
  2. ログを見ながらTerraformのソースコードを追いかける

1に関しては、以下のような点に着目した記事がありました。ですが実際に試しても問題は解決しませんでした。

  • この記事で書いてあるようなファイルの書き方
  • バケットのポリシー設定方法

2に関しては、Terraformの公式ページを基にして、terraformコマンド実行時にTF_LOG=TRACEをつけてログを確認しました。そのログを使ってTerraformのソースを見始めましたが、Go初心者である私にはざっとした流れしか分かりませんでした。

そのため1、2のどちらの方法でも、解決には至りませんでした。

解決

試行錯誤しながら進めていたとき、S3のバケットをふと見てみると、terraform.tfstateができている事に気づきました。そのためそれまで自分が行った修正やコマンドを振り返りながら、1つずつ切り分けし、ここに記載したパターンに行き着きました。

Goが分かる人であればコードで理解でき、パターンがすぐに分かったと思います。私はまだGoが分からない状態だったので、このような方法で解決に至りました。

環境

  • Mac:macOS Catalina Version 10.15.5
  • Terraform:v0.12.28

前提

ここではTerraformでVPCを作成する例をあげています。
また、この記事で紹介しているIAMユーザのポリシーやバケットの設定は、記事用としての設定です。実際の環境では、必要に応じたポリシーや設定を行ってください。

IAMユーザを作成する

TerraformでVPCを作成するため、以下の2つを満たしたIAMユーザを作成しておきます。

  • AmazonVPCFullAccessのアタッチ
  • AWSアクセスの種類に「プログラムによるアクセス・アクセスキーを使用」を設定

IAMユーザ作成時にアクセスキー、シークレットキーが表示されるので、後述するaccess_key、secret_keyに設定します。
Screen Shot 2020-07-22 at 19.34.14.png

ローカルで管理する

ファイルの作成とコマンド実行

以下のようにmain.tfを作成します。

main.tf
provider "aws" {
  region  = "ap-northeast-1"
  access_key = "xxxxx"
  secret_key = "yyyyy"
}

# VPC
resource "aws_vpc" "vpc" {
  cidr_block = "10.0.0.0/16"
  enable_dns_hostnames = true

  tags = {
    Name = "vpc-test"
  }
}

main.tfを作成したら、以下3つのコマンドを実行します。
※ここではterraform apply時に-auto-approveオプションをつけていますが、なくても問題ありません。

$ terraform init
$ terraform plan
$ terraform apply -auto-approve

terraform apply実行後、以下のように出力され、terraform.tfstateがローカルに作成されます。

$ terraform apply -auto-approve
aws_vpc.vpc: Creating...
aws_vpc.vpc: Creation complete after 4s [id=vpc-aaaaa]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

S3で管理する

IAMユーザにバケットアクセスのポリシーを追加する

Terraformで新たにバケットにアクセスするため、IAMユーザにポリシーを追加します。
アタッチするポリシーはAmazonS3FullAccessです。
Screen Shot 2020-07-23 at 1.37.11.png

S3でバケットを作成する

ここではバケット名をbucket-for-tfとして、「次へ」を押します。
Screen Shot 2020-07-21 at 21.10.21.png

特に設定を行わずに「次へ」を押します。
Screen Shot 2020-07-21 at 20.28.22.png

「パブリックアクセスをすべてブロック」のチェックを外し、「現在の設定により・・・を了承します。」にチェックをつけます。
Screen Shot 2020-07-21 at 6.59.37.png

確認画面が出るので、「バケットを作成」ボタンを押してバケットを作成します。
Screen Shot 2020-07-21 at 21.11.55.png

S3上に、指定したバケット(buekct-for-tf)が作成されます。
Screen Shot 2020-07-21 at 21.13.50.png

バケットにバケットポリシーを設定する

terraformがterraform.tfstateをS3に配置するためには、バケットポリシーの設定が必要です。terrformの公式ページを参照し、作成したIAMユーザやバケット名を使用して、以下のようにバケットポリシーを設定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111:user/terraform-bucket-manager"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::bucket-for-tf"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::11111:user/terraform-bucket-manager"
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::bucket-for-tf/*"
        }
    ]
}
Screen Shot 2020-07-21 at 21.25.34.png

ファイルの作成とコマンド実行

以下のようにmain.tfを作成します。
基本的には「ローカルでterraformを管理する」項目と同じです。異なる点は、backendにs3を指定している点です。

main.tf
provider "aws" {
  region  = "ap-northeast-1"
  access_key = "xxxxx"
  secret_key = "yyyyy"
}

terraform {
  backend "s3" { 
    access_key = "xxxxx"
    secret_key = "yyyyy"
    bucket  = "bucket-for-tf"
    region  = "ap-northeast-1"
    key     = "terraform.tfstate"
    encrypt = true
  }
}

# VPC
resource "aws_vpc" "vpc" {
  cidr_block = "10.0.0.0/16"
  enable_dns_hostnames = true

  tags = {
    Name = "vpc-test"
  }
}

作成したら以下3つのコマンドを実行します。

$ terraform init
$ terraform plan
$ terraform apply

terraform initを行うと、バックエンドにs3を設定完了のメッセージが表示されます。

$ terraform init

Initializing the backend...

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
・・・略・・・

terraform applyまで行うと、main.tfで指定したS3のバケット(bucket-for-tf)にterraform.tfstateが出来上がります。
Screen Shot 2020-07-21 at 21.40.55.png

ローカルでの管理からS3での管理に移す

ローカルでの管理

以下のようにmain.tfを作成します。
基本的には「S3でterraform.tfstateを管理する」項目と同じです。異なる点は、backendにlocalを指定している点です。

main.tf
provider "aws" {
  region  = "ap-northeast-1"
  access_key = "xxxxx"
  secret_key = "yyyyy"
}

terraform {
  backend "local" {
    path = "terraform.tfstate"
  }
}

# VPC
resource "aws_vpc" "vpc" {
  cidr_block = "10.0.0.0/16"
  enable_dns_hostnames = true

  tags = {
    Name = "vpc-test"
  }
}

作成したら以下3つのコマンドを実行します。

$ terraform init
$ terraform plan
$ terraform apply -auto-approve

terraform initを実行すると、バックエンドにlocalを設定完了のメッセージが表示されます。

$ terraform init

Initializing the backend...

Successfully configured the backend "local"! Terraform will automatically
use this backend unless the backend configuration changes.
・・・略・・・

S3での管理へ変更

terraform apply完了後、main.tfのbackendをs3に書き換えます。
ここで使用するIAMユーザ、S3のバケットについては、「IAMでユーザを作成する」、「S3でバケットを作成する」を参照してください。

main.tf
provider "aws" {
  region  = "ap-northeast-1"
  access_key = "xxxxx"
  secret_key = "yyyyy"
}

terraform {
  backend "s3" { 
    access_key = "xxxxx"
    secret_key = "yyyyy"
    bucket  = "bucket-for-tf"
    region  = "ap-northeast-1"
    key     = "terraform.tfstate"
    encrypt = true
  }
}

# VPC
resource "aws_vpc" "vpc" {
  cidr_block = "10.0.0.0/16"
  enable_dns_hostnames = true

  tags = {
    Name = "vpc-test"
  }
}

backendを変更したので以下コマンドを再実行します。

$ terraform init

terraform.tfstateをs3にコピーして良いか尋ねられるのでyesを入力します。

$ terraform init

Initializing the backend...
Backend configuration changed!

Terraform has detected that the configuration specified for the backend
has changed. Terraform will now check for existing state in the backends.


Terraform detected that the backend type changed from "local" to "s3".
・・・略・・・
 Do you want to copy this state to the new "s3"
  backend? Enter "yes" to copy and "no" to start with an empty state.

  Enter a value: yes

yesを入力後、バックエンドにs3を設定完了のメッセージが表示されます。

$ terraform init
・・・略・・・
  Enter a value: yes

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
・・・略・・・

このタイミングで、S3のバケットにterraform.tfstateが作成されます。
Screen Shot 2020-07-23 at 0.01.37.png

この後にterraform applyを実行します。
S3のバケットを見てみると、terraform.tfstateが更新されていることが分かります。

$ terraform apply -auto-approve
aws_vpc.vpc: Refreshing state... [id=vpc-aaaaa]

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Screen Shot 2020-07-23 at 0.02.09.png

おわりに

ローカルやS3でterraform.tfstateを管理する方法を記載しました。
Goが分かっていればもっと楽に解決できたと思います。

この記事が、未来の私や困っている誰かのお役に立てれば幸いです。

参考資料

terraformのbackendをs3にしてinitするまでの最低限の手順
Backend の S3 や DynamoDB 自体を terraform で管理するセットアップ方法
Terraformをしばらく書いて覚えた個人的なTipsについて
terraformを利用したtfstateファイルのS3へのアップロードができない

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?