Terraformの共有とstatusの管理

2019.10.17 (木)

Terraformでインフラを管理する場合、いわゆる冪等性を担保するためにステータスを共有する必要があります。このステータスを管理するためにTerraformのBackend機能というものがあります。Backend機能を使ってステータス情報を共有のストレージに格納し共有します。terraform applyを実行する際にはこの共有ステータスを見に行くことになるので、複数のリモート環境から実行するこが可能です。
今回はGCPのCloud storageを使ってみます。

仕組み

正直terraformのbackanedなるものがどこまでを指しているんだかわからないのですが、おそらくterraform.tfstateを指しているんだということでよいかと思います。このステータス管理しているterraform.tfstate.d以下の内容を共有のストレージで管理しようという感じです。
クレデンシャルがややこしくなりますが、GCSにアクセスするクレデンシャルはTerraformをapplyするプロジェクトとは別なので別で発行します。(あるいは同じ場合もあるかもしれないけど、同じ環境で管理するのはあんまりよろしくないのではと。。)と、いうような仕組みです。

設定

  • GCSを作成するプロジェクトのサービスアカウントを作成する。
  • クレデンシャルのjsonのパスを環境変数に設定する。
  • GCSを作成するtfファイル、そしてステータスを保存するtfファイルを設定する。

サーバー間での本番環境アプリケーションの認証の設定

サービスアカウントを設定したら、LinuxやMacの環境の場合は、.bash_profileなどに環境変数に以下を設定します。

export GOOGLE_CLOUD_KEYFILE_JSON="{{path}}"
export GOOGLE_APPLICATION_CREDENTIALS=$GOOGLE_CLOUD_KEYFILE_JSON

保存したらsourceしてください。
それから、上記クレデンシャルを設定した先のプロジェクトに予めBucketを作成しておいてください。(ここではhoge-terraform-bucketというやつです。)

tfファイルは以下のようになります。これでバケットを作成します。

terraform {
  backend "gcs" {
    bucket  = "hoge-terraform-bucket"
  }
}

設定が終わったらbackendの設定を反映するために、初期化します。

$ terraform init

これでいつものように実行すればOKです。

初期化が失敗する場合があります。

Error: Error inspecting states in the "gcs" backend:
    querying Cloud Storage failed: storage: bucket doesn't exist

よくわからんけど、手動で作成してあげたらinitが通った。
当たり前だけどbackendの実行はapplyするプロジェクト(つまりprovider)とは別なので、Bucket自体は予め何らかのかたちで作ってあげないとダメなわけですね。(それを別のTerraformで作ってもよいわけだけど)

Error各種

Error: Error locking state: Error acquiring the state lock: 2 errors occurred:
    * writing "gs://hoge-terraform-bucket/product.tflock" failed: googleapi: Error 403: Insufficient Permission, insufficientPermissions
    * storage: object doesn't exist

なんか起動時に環境変数が通らないのが原因だった。$ source ~/.bash_profileを実行すればよいのだけど、なんか面倒くさい。Terraformの問題ではないので、.bash_profileや.bashrcの変更が反映されない問題を解決するで試みてください。これが原因じゃないとしたら、ログインシェルが違っていて~/.zprofile.bash_profileと同じこと書けばいいかもとか、ユーザースイッチするときにハイフンつけてないとか。