AzureのリソースをTerraformを使って構築する際に、tfstateの管理をどうしようかと思っていたところ、AWSのS3でtfstateを管理するようにAzure Blob Storageでほぼ同じことができそうだったので試してみた。
tfstateとは
Terraformで管理しているリソースの状態を表すファイル qiita.com
デフォルトだとローカルに保存されるが、複数人で開発する時などに困る。 基本的にはAWSのS3だったり、今だとTerraform Cloudでも管理出来たりなど、 tfstate自体はリモートで管理することが多い。 tfstateには各リソースの機密情報も含まれてたりするので、GitHubでは管理するのは良くない。 dev.classmethod.jp
tfstateを管理するリソースグループ、Blob Storageを作成
今回はAzure CLIを使ってtfstateを管理する各リソースを作成していく
Azure CLI のインストール | Microsoft Docs
Azureにログインする
$ az login
サブスクリプションの指定行う(複数サクブスクリプションを持っている場合)
$ az account set --subscription "<サブスクリプション名>"
ちなみにaz account list
コマンドでサブスクリプションの状態が確認できます
$ az account list --output table
ログインができたら、リソースグループを作成する
$ RESOURCE_GROUP_NAME=tfstate $ az group create --name $RESOURCE_GROUP_NAME --location japaneast
ストレージアカウントを作成する
$ STORAGE_ACCOUNT_NAME=tfstate$RANDOM $ az storage account create --resource-group $RESOURCE_GROUP_NAME --name $STORAGE_ACCOUNT_NAME --sku Standard_LRS
ストレージアカウントのアカウントキーを取得する(Blobコンテナ作成時に必要となる)
$ ACCOUNT_KEY=$(az storage account keys list --resource-group $RESOURCE_GROUP_NAME --account-name $STORAGE_ACCOUNT_NAME --query [0].value -o tsv)
ちなみに当方の環境だと以下のようなエラーがでた
zsh: no matches found: [0]
原因、回避策はこちらが参考になった qiita.com
Blobコンテナの作成
$ CONTAINER_NAME=tfstate $ az storage container create --name $CONTAINER_NAME --account-name $STORAGE_ACCOUNT_NAME --account-key $ACCOUNT_KEY
Azure Storage Explorer等でBlobコンテナが作成されていることを確認できればOK
backendの設定
まずはmain.tfファイルを作成し、providerブロックを追加。ここではazurermを指定する
provider "azurerm" { version = "~>2.0" features {} }
次にterraformブロックを追加する。 backendを以下のように設定することでtfstateを上記で作成したBlob Storageで管理することができる
terraform { backend "azurerm" { resource_group_name = "tfstate" storage_account_name = "tfstate26723" container_name = "tfstate" key = "terraform.tfstate" } }
keyではtfstateのファイル名を指定している
次にterraform init
コマンドを実行して初期化を行い、リソース作成に必要なバイナリ等をダウンロードする。
この時にbackendの設定も行われる。
$ terraform init Initializing the backend... Successfully configured the backend "azurerm"! Terraform will automatically use this backend unless the backend configuration changes. Initializing provider plugins... - Checking for available provider plugins... - Downloading plugin for provider "azurerm" (hashicorp/azurerm) 2.26.0... Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.
問題がなければTerraform has been successfully initialized!
といった文言が出力される。
ちなみにダウンロードされたバイナリ等は.terraform
ディレクトリ以下に保存される。
今回だとこんな感じ
.terraform ├── plugins │ └── darwin_amd64 │ ├── lock.json │ └── terraform-provider-azurerm_v2.26.0_x5 └── terraform.tfstate
tfstateの状態を確認
サンプルとして適当にリソースグループを作成して、その状態をBlob Storageに作成されたtfstateで確認する。
先ほど作成したmain.tf
に以下のリソースを追加する
resource "azurerm_resource_group" "example" { name = "example" location = "japaneast" }
terraform apply
コマンドを実行しリソースの作成を行う。
$ terraform apply Acquiring state lock. This may take a few moments... An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_resource_group.example will be created + resource "azurerm_resource_group" "example" { + id = (known after apply) + location = "japaneast" + name = "example" } Plan: 1 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes azurerm_resource_group.example: Creating... azurerm_resource_group.example: Creation complete after 1s [id=/subscriptions/<サブスクリプションID>/resourceGroups/example] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
リソースの作成が始まると上記で作成したBlob Storageの中にterraform.tfstateというファイルが作成される。これがリソースの状態を管理しているファイルとなっている。リソースの作成中はこのファイルに対してロックがかかっており、他の人の操作による同時に状態が変更されるのを防止してくれる
terraform.tfstate
中身を見てみるとこんな感じ
{ "version": 4, "terraform_version": "0.12.26", "serial": 1, "lineage": "efe53c3f-7ddb-81e4-2d5b-24ce11859842", "outputs": {}, "resources": [ { "mode": "managed", "type": "azurerm_resource_group", "name": "example", "provider": "provider.azurerm", "instances": [ { "schema_version": 0, "attributes": { "id": "/subscriptions/<サブスクリプションID>/resourceGroups/example", "location": "japaneast", "name": "example", "tags": null, "timeouts": null }, "private": "*******************************" } ] } ] }
リソースを削除した場合の状態も確認してみる
terraform destory
コマンドでリソースの削除を行い、再度Blob Srogaeの中にあるterraform.tfstate
の中身を確認
{ "version": 4, "terraform_version": "0.12.26", "serial": 6, "lineage": "efe53c3f-7ddb-81e4-2d5b-24ce11859842", "outputs": {}, "resources": [] }
tfstateでリソースが削除できているのを確認できた
まとめ
今回はtfstateをAzure Blob Storageで管理するようにしてみたが、Terraform Cloudを使うとtfstateのバージョン管理ができたり他にもいろいろ機能がありそうだったので、そちらの方も調査&検証してみたい。