どのrevisionでterraform applyされたものか分かるようにtfstateに情報を埋め込む

背景

  • Terraformでリソースをコード管理をしている場合、大抵gitでバージョン管理している
  • terraform applyしたものがまずかった場合、どの差分によるものか、いつから発生していたものなのか、誰の実行によるものかといった情報が欲しくなる
    • backendをgcsなどにしている場合、オブジェクトのバージョニングを有効にしていれば、いつオペレーションが実行されたかなどを追える
    • 事故ってたケースの調査などで特に欲しい
  • revisionの情報や実行者の情報は素のTerraformでは分からないので、何かしらの形で情報を埋め込みたい

やってみたこと: makeで情報を外から与える

varで外から情報を与えてみる形を考えてみました。こんな感じで変数とoutputを定義しておきます。

variable "current_revision" {
  description = "terraform applyを実行した際のgitのrevision"
  type        = string
}

variable "username" {
  description = "terraform applyを実行した人のusername"
  type        = string
}

output "current_revision" {
  value = var.current_revision
}

output "username" {
  value = var.username
}

実際のrevisionや実行者の情報はMakefileの中でvarの引数で与えます。

CURRENT_REVISION := $(shell git rev-parse --short HEAD)
USERNAME := $(shell whoami)

plan:
  terraform plan \
      -var="current_revision=${CURRENT_REVISION}" \
      -var="username=${USERNAME}"

apply: 
  terraform apply \
      -var="current_revision=${CURRENT_REVISION}" \
      -var="username=${USERNAME}"

そうするとtfstateのoutputsの項目にterraform applyした際のrevisionの情報やusernameが埋め込まれるようになります。調査が捗りそうですね。

% terraform state pull | jq .outputs
{
  "current_revision": {
    "value": "abcdefg",
    "type": "string"
  },
  "username": {
    "value": "syou6162",
    "type": "string"
  }
}

validationを強化する

先程までのやり方はちょっと穴があります。git diffで差分が出ている状態でapplyされてしまうと、revisionと実際のTerraformのコードが一致しないという問題点です。こういったケースは避けたいので、差分がある状態ではそもそもmake applyが失敗するようにpre-conditionに入れておきます。これで安心ですね。

GIT_DIFF_VALIDATE_MESSAGE="gitの差分がある状態でapplyしようとしています。差分をcommitした状態でapplyしましょう"

validate-apply:
  git diff --diff-filter=ad --quiet || \
      (echo "${GIT_DIFF_VALIDATE_MESSAGE}" && exit 1)

apply: validate-apply
  terraform apply \
      -var="current_revision=${CURRENT_REVISION}" \
      -var="username=${USERNAME}"

その他調べたこと