Terraformの「Objects have changed outside of Terraform」について

こんにちは。 エキサイト株式会社の三浦です。

AWSGCPで環境を構築するとき、Terraformを使用する方も多いかと思います。 今回は、Terraformでたまに起きる「Objects have changed outside of Terraform」について説明していきます。

Terraformとは

Terraformは、公式では以下のように紹介されています。

Terraform is an open-source infrastructure as code software tool that provides a consistent CLI workflow to manage hundreds of cloud services.

端的に言えば「クラウドサービス用のIaC」と言ったところで、AWSGCPなどのクラウドサービスで環境構築する際に、Webコンソール上で作成するのではなくコードとして作成・管理することで、環境構築の再現性を担保したり、コード自体にドキュメントとしての意味を持たせたものになります。

Terraformを実行すると、コードで記述したサービスがクラウドサービス上に作成され、同時に初回実行であれば現在のサービスの状態を保存するための状態管理ファイルが作成されます。 2回目以降にTerraformを実行する場合は、状態管理ファイルを使用することで、前回の実行時との差分などを判定します。

基本的には、コードを全く変更せずに2回連続でTerraformを実行した場合、クラウドサービスの実態と状態管理ファイルの中身には差分は無いはずです。 ですが、たまに「変更された」判定が起きる場合があります。

Objects have changed outside of Terraform

コードが変更されていないにもかかわらず「変更された」判定が起きる場合、「Objects have changed outside of Terraform」というメッセージが表示されます。 このとき、原因としては以下の2点が考えられます。

  1. Terraformを使わずに、以前Terraformで作成したサービスを変更した
  2. それ以外

1の、「Terraformを使わずに、以前Terraformで作成したサービスを変更した」であれば話は簡単で、Terraformのコードを変更された後の状態に修正するか、もしくは修正せずにTerraformを実行することで現状のTerraformのコードの状態にサービス側を戻せば良いでしょう。 もしTerraform外で変更されるのが必然的な状況であれば、 ignore_changes という設定を使い、該当部分の変更をTerraform側で関知しないようにするのもいいかもしれません。

問題は、2の「それ以外」の場合です。

「それ以外」の場合、考えられるパターンとしては

  • 一度のTerraformの実行で複数サービスが作成されるとき、サービス作成順の関係で初回実行ではサービスの状態が完全には状態管理ファイルに反映されず、2回目の実行で「変更された」判定となってしまう
  • 作成に改行文字などを使用するサービスの場合、環境ごとの改行文字の細かい違いによって、サービスで実際に保存されている文字列と状態管理ファイルに保存されている文字列が違っており、2回目の実行で「変更された」判定となってしまう

などが挙げられ、おそらく上記以外にも様々なパターンがあると思われます。

f:id:excite-takayuki-miura:20210830114847p:plain
「それ以外」の例

もちろん可能であればこの表示が出ないようにTerraformを修正したいところですが、なかなか修正が難しいというのが現状だと思います。 こういった場合は、 terraform applyterraform apply -refresh-only などで状態管理ファイルを更新するのが現状だと現実解でしょう。

最後に

初めてこういった差分が出ると、何かミスをしてしまったのかと思ってしまうのではないでしょうか。 そのような状況のときに、この記事が役に立てれば幸いです。

なお上記は Terraform v1.0.5 にて確認したメッセージなので、バージョンが上がることでメッセージが変わったり、もしかしたらこういった差分は起こらないようになっていく可能性があります。 あらかじめご了承ください。