TerraformのBackendにObject Storageを利用する

こんにちは id:dhigashi です。

Terraform では管理対象のインフラを管理するために、デフォルトではローカルに terraform.tfstate というファイルを作成し現在の状態を保存しています。
一人で開発している時には特に問題はありませんが、複数人で開発する場合では最新の状態を共有する必要があるなど管理が困難になります。

この問題を解決するため Terraform では Backend という機能により、リモートに状態を保存する事ができます。

現在 Terraform では様々な Backend Types がサポートされています。

今回はこれらの内、HTTPS3 Type を利用し Object Storage を Backend として利用してみたいと思います。

Using the Object Store for Terraform State Files

事前準備

本記事は、Terraform が利用できる事を前提としています。
Terraform の導入がまだの場合は、以下の記事をご覧ください。

cloudii.atomitech.jp

また、今回はテストの為に以下の単純な VCN を作成しています。

f:id:dhigashi:20180820171026p:plain

構成ファイルは以下のリポジトリから参照してください。

github.com

HTTP backend

HTTP backend は GET による状態の取得、POST による状態の更新など、REST を利用し状態を管理します。

この時 Object Storage に対して資格情報無しで操作を行うために、事前承認リクエスト を利用します。
事前承認リクエストについては、以下の記事をご覧ください。

cloudii.atomitech.jp

terraform.tfstate オブジェクトに対し、読み書きができる事前承認リクエストを作成します。

f:id:dhigashi:20180820154100p:plain

f:id:dhigashi:20180820154538p:plain

Backend のタイプに http を指定し、address に 発行されたリクエスト URL を update_methodPUT を設定します。

terraform {
  backend "http" {
    address = "https://objectstorage.us-phoenix-1.oraclecloud.com/<my-access-uri>/example-terraform-state/o/terraform.tfstate"
    update_method = "PUT"
  }
}

Terraform の初期化と構成の適用を行います。

$ terraform init
略
Terraform has been successfully initialized!
$ terraform apply

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:

  + oci_core_default_route_table.DefaultRT
      略

  + oci_core_internet_gateway.ExampleIG
      display_name:                                                      "Example Internet Gateway"
      vcn_id:                                                            "${oci_core_vcn.ExampleVCN.id}"
      略

  + oci_core_security_list.AllowSSH
      display_name:                                                      "Allow SSH"
      vcn_id:                                                            "${oci_core_vcn.ExampleVCN.id}"
      略

  + oci_core_subnet.ExamplePublicSubnet
      availability_domain:                                               "dArW:PHX-AD-1"
      cidr_block:                                                        "172.16.1.0/24"
      display_name:                                                      "Example Public Subnet"
      略

  + oci_core_vcn.ExampleVCN
      cidr_block:                                                        "172.16.0.0/16"
      display_name:                                                      "Example VCN"
      略


Plan: 5 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

oci_core_vcn.ExampleVCN: Creating...
略
Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

リソースの作成が成功し、Web コンソールからも作成した VCN を確認する事ができます。

f:id:dhigashi:20180820194400p:plain

また、Object Storage には terraform.tfstate ファイルが作成されている事が確認できます。

f:id:dhigashi:20180820171900p:plain

以上のように 事前承認リクエストHTTP backend により Object Storage を Backend として利用する事ができました。

但し、事前承認リクエスト はリクエスト URL が有効な限り、URL にアクセスできれば誰でも操作を行う事ができます。
tfstate ファイルには機密情報が含まれる場合もあるため、事前承認リクエスト を利用できるか慎重に検討する必要があります。

S3 backend

続いて S3 backend で状態を保存します。

S3 backend は Object Storage の S3 互換 API を利用し状態を管理します。

 

まず Amazon S3 Compatibility API Key (S3 互換 API キー) を作成します。

Object Storage に対して操作権限をもったユーザーで Secret Key を生成します。

f:id:dhigashi:20180820184447p:plain

適当な名前を指定し、生成された Secret Key と Access Key を控えておきます。

f:id:dhigashi:20180820184451p:plain

f:id:dhigashi:20180820184506p:plain

f:id:dhigashi:20180820184503p:plain

資格情報 を ~/.aws/credentials へ格納します。

$ cat ~/.aws/credentials
[profile_name]
aws_access_key_id=<access_key>
aws_secret_access_key=<secret_key>

さきほど http を指定した Backend を s3 に変更し、各パラメータを設定します。
profile には credentials に格納した時に指定したプロファイル名を指定します。

terraform {
  backend "s3" {
    bucket   = "<bucket_name>"
    key      = "terraform.tfstate"
    profile  = "<profile_name>"  # ~/.aws/credentials
    region   = "us-phoenix-1"
    endpoint = "https://<namespace>.compat.objectstorage.us-phoenix-1.oraclecloud.com"

    skip_region_validation      = true
    skip_credentials_validation = true
    skip_requesting_account_id  = true
    skip_get_ec2_platforms      = true
    skip_metadata_api_check     = true
    force_path_style            = true
  }
}

Backend を変更したので、再度 terraform init コマンドを実行します。

$ 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 "http" to "s3".

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
略
Terraform has been successfully initialized!

Backend の設定の変更が完了したので、再度 terraform apply コマンドにより構成を適用してみます。

$ terraform apply
略
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

構成に変更が無く、何も実行されませんでした。
Backend を変更しても同じ tfstate ファイルを指定し参照している為、構成の状態を引き継いでいる事が確認できました。

まとめ

Terraform の HTTPS3 Backend を利用し Object Storage に構成の状態を保存できる事が確認できました。

また、Terraform には State Lock という機能により、複数人が同時に構成を変更できないようロックする事ができます。

www.terraform.io

S3 backend では DynamoDB を用いてロック機能を利用する事ができますが、今回ご紹介した方法では実現できていないため、 本番で利用するには更に工夫が必要かもしれません。