Terraformでテンプレートのアップデート時に特定のリソースの変更を適用しない方法

2017.03.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、岩本です。

Terraformを利用する際にある一部のリソースを変更すると、再作成となってしまう場合、
もしくは、変更を無視したい場合などがあると思います。
そこで、テンプレートのアップデートの際に、特定のリソースの変更を無視する方法です。

結論

コマンド実行時に-target=を指定する。

  • -target=とは? plan/applyのオプションで、特定のリソースを指定し、適用を実施することができます。
    つまり適用されるリソースは指定したもののみとなるため、それ以外は除外されます。

lifecycle を利用する。

  • lifecycleとは?
    対象となるリソースに記載することで、そのリソースに変更が発生する際の挙動を変更できます。 lifecycleには下記にある3通りの挙動を選択できます。

  • create_before_destroy (bool)

    • 既存のリソースが有った場合に、一旦削除してから作り直すようになります。
  • prevent_destroy (bool)
    • この値があるリソースを削除しようとするとエラーになります。
  • ignore_changes (list of strings)
    • 実際のリソースとTerraform管理下のリソースの差分があった際、指定したリソースの変更が無視される様になります。

lifecycle ignore_changes の挙動を試してみる

検証

下記のようにAMIの指定を変数で行い、2台のEC2を作成します。

variable "ec2_ami" {
  default = "ami-56d4ad31"
}

resource "aws_instance" "web-ec2_01" {
  ami           = "${var.ec2_ami}"
  instance_type = "${var.ec2_instance_type}"
  key_name      = "${var.ssh_keypaer_name}"
  lifecycle {
    ignore_changes = [
      "ami",
    ]
  }

resource "aws_instance" "web-ec2_02" {
  ami           = "${var.ec2_ami}"
  instance_type = "${var.ec2_instance_type}"
  key_name      = "${var.ssh_keypaer_name}"

指定したAMIを元に2台のEC2が作成されました。

次に、AMIを変更します。

#ec2_ami = "ami-56d4ad31"
ec2_ami = "ami-1bfdb67c"
  • 実行結果の確認
terraform plan
~ aws_eip.eip_web-ec2_02
    instance: "i-0e4810f1a843abcca" => "${aws_instance.web-ec2_02.id}"

-/+ aws_instance.web-ec2_02
    ami:                                       "ami-56d4ad31" => "ami-1bfdb67c" (forces new resource)
...
Plan: 1 to add, 1 to change, 1 to destroy.

lifecycleを指定したEC2はAMIの変更が無視され、指定しなかった02のみがリソース変更の対象となっています。

  • 適用
terraform apply
Apply complete! Resources: 1 added, 1 changed, 1 destroyed.

実行結果の確認通りlifecycleを指定しなかったEC2のみが再作成となりました。

まとめ

Terraformを使って、環境を構築後に環境のアップデートが発生する場合があるかと思います。
その際特にしていなくアップデートが可能なリソースもありますが、
意図しないアップデート・削除を防ぐためlifecycleを指定することで、
より安全なAWS環境の利用ができるかと思います。