🎼

Terraform & Azure での実環境との差分チェック

2024/08/27に公開

関わっている案件で Terraform の実行後に構成が意図しない状態になっていた (Terraform が悪いのか、誰かが悪いのかは微妙に不明) ということで、本当に意図した設定になっているか、どう確認するか、というお話になりました。

Terraform は、改めて plan の実行をすることで一応 state ファイルの状態と実際の環境とで差分を比較し、検出することができます。

terraform plan -refresh-only

Azure Storage Account を Terraform でデプロイ後、Azure Portal から「構成」ブレードの「BLOB 匿名アクセスを許可する」の設定を変更した後、「terraform plan -refresh-only」コマンドを実行した結果が下記です。

> terraform plan -refresh-only

azurerm_resource_group.example: Refreshing state... [id=/subscriptions/xxxxxxxxxx/resourceGroups/rg-test]

azurerm_storage_account.example: Refreshing state... [id=/subscriptions/xxxxxxxxxx/resourceGroups/rg-test/providers/Microsoft.Storage/storageAccounts/stsouterratest1]

Note: Objects have changed outside of Terraform

Terraform detected the following changes made outside of Terraform since the last "terraform apply" which may have affected this plan:

azurerm_storage_account.example has changed
~ resource "azurerm_storage_account" "example" {
  ~ allow\_nested\_items\_to\_be_public    = true -> false
    id                                 = "/subscriptions/xxxxxxxxxx/resourceGroups/rg-test/providers/Microsoft.Storage/storageAccounts/stsouterratest1"
    name                               = "stsouterratest1"
    tags                               = {
        "environment" = "staging"
    }
    # (96 unchanged attributes hidden)
    # (3 unchanged blocks hidden)
}
This is a refresh-only plan, so Terraform will not take any actions to undo these. If you were expecting these changes then you can apply this plan to record the updated values in the Terraform state without changing

any remote objects.

このように、「allow_nested_items_to_be_public」が true から false になったことが検出できます。

ひとまず、定期的 or 任意のタイミングで本コマンドの実行結果を確認することで、差分の検知はできますね。

差分の有無をリターンコードから判定したい

さて、自動化等において、差分の検出をリターンコードで判定したいときもあると思います。そんなときに使えるのが「-detailed-exitcode」オプションです。以下は PowerShell でのリターンコードです。詳しくは、こちらのマニュアルも参照してください。

差分 -refresh-only -detailed-exitcode
なし True True
あり False True

なお、参考までに、変化がない (=実環境と Terraform コードの差異が無い) 場合は下記のような出力とリターンコードになります。

> terraform plan -detailed-exitcode

azurerm_resource_group.example: Refreshing state... [id=/subscriptions/xxxxxxxxxx/resourceGroups/rg-test]

azurerm_storage_account.example: Refreshing state... [id=/subscriptions/xxxxxxxxxx/resourceGroups/rg-test/providers/Microsoft.Storage/storageAccounts/stsouterratest1]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

> $?
True

ということで、「-detailed-exitcode」オプションを付与することで、Terraform コードと実際の環境との差分のあるなしをリターンコードから判定できるようになります。

おわりに

以上、デプロイ後の Terraform コードと実際の環境との差分は上記の方法で検出することができそうです。

なお、そもそも設定値バグがある場合や、Terraform 側のバグ等で設定が反映されないような状況の場合は、この方法では検出することはできないと思います。Terraform 側で取り回しできないケースも救おうとするなら、最悪サンプリング目検も避けられないですね…

どこまでを Terraform でやらせたいか、どこまで品質を確認したいか、考えながらプロセスを固めていくと良いと思います。

Discussion