ignore_changes の正しい使い方と落とし穴

1. 概要

  • ignore_changesを使う目的と注意点
  • 「all」指定の危険性
  • ignore_changesが効かないケース
  • 正しい使い方とアンチパターン

ignore_changesは「Terraformの管理外で変更された属性を無視する」ためのメタ引数です。便利ですが、使い方を誤るとTerraformが変更を検知しなくなり、意図しない設定のドリフトが発生します。


2. ignore_changes の基本

terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

variable "environment" {
  description = "環境名"
  type        = string
  default     = "dev"
}

data "aws_ami" "amazon_linux_2023" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  lifecycle {
    # AMIが変わっても既存インスタンスを維持する
    ignore_changes = [ami]
  }

  tags = {
    Name        = "${var.environment}-web"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

3. ignore_changes = all の危険性

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  lifecycle {
    # ❌ 危険: すべての変更をTerraformが無視する
    # → Terraformでのコード変更が一切反映されない
    # → セキュリティ設定の変更も反映されない
    ignore_changes = all
  }

  tags = {
    Name        = "${var.environment}-web"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

ignore_changes = allは「一時的な回避策」として使っても、実質的にTerraformでリソースを管理しないのと同じ状態になります。使用する場合はコメントで理由を明記し、計画的に外します。


4. ignore_changesが効かないケース

# ⚠️ ignore_changesは「更新(update in-place)」には効くが
# 「置換(destroy then create)」には効かない場合がある

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  lifecycle {
    ignore_changes = [instance_type]
    # ↑ instance_typeをignoreしても、AMI変更(forces replacement)には無力
  }

  tags = {
    Name        = "${var.environment}-web"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

5. 正しい使いどころ

# ✅ 有効な使いどころ1: Auto Scalingでインスタンス数が外から変わる
resource "aws_autoscaling_group" "web" {
  min_size         = 1
  max_size         = 10
  desired_capacity = 2

  # desired_capacityはAuto Scalingポリシーが変更するため無視
  lifecycle {
    ignore_changes = [desired_capacity]
  }

  tag {
    key                 = "Name"
    value               = "${var.environment}-web-asg"
    propagate_at_launch = true
  }
  tag {
    key                 = "Environment"
    value               = var.environment
    propagate_at_launch = true
  }
  tag {
    key                 = "ManagedBy"
    value               = "terraform"
    propagate_at_launch = true
  }
}

# ✅ 有効な使いどころ2: 外部ツールが変更するタグを無視
resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  lifecycle {
    # コスト管理ツールが自動追加するタグを無視
    ignore_changes = [
      tags["LastScanned"],
      tags["PatchStatus"],
    ]
  }

  tags = {
    Name        = "${var.environment}-web"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

6. ignore_changes のアンチパターン

アンチパターン問題代替案
ignore_changes = allすべての変更を無視具体的な属性を指定する
管理すべき属性を永続的に無視ドリフトを検知できない問題を根本解決する
デバッグ中に追加したまま忘れる意図しない設定が永続化解決後に必ず削除する

7. 関連記事


8. まとめ

  • ignore_changesはTerraform管理外で変更される属性(Auto Scalingのdesired_capacity・外部ツールのタグ)に使う
  • ignore_changes = allはすべての変更を無視し、実質的にTerraform管理外になる(危険)
  • 置換(forces replacement)にはignore_changesは効かない
  • 使用する際は必ずコメントで理由を書き、不要になったら削除する
  • 根本的にはドリフトを許容せず、Terraform以外がリソースを変更しない設計を目指す

動作確認バージョン: Terraform >= 1.9 公式ドキュメント: https://developer.hashicorp.com/terraform/language/resources/lifecycle#ignore_changes