はじめに
Terraform初学者です。
『実践Terraform』という書籍で勉強しています。
書籍の中でaws_instance.example must be replaced
という出力が想定されている箇所がありました。
しかし、現在のバージョンで試してみるとaws_instance.example will be updated in-place
と出力されてしまいます。
この違いの原因について調べたので備忘録としてまとめます。
この記事におけるバージョンは Terraform v1.9.5 です。
一方で書籍のバージョンは Terraform v0.12.5 です。
問題
第2章 基本操作
の2.2 リソースの更新
のサンプルコードが対象です。
まず、次のようにEC2インスタンスにNameタグを追加してterraform apply
した状態があります。
resource "aws_instance" "example" {
ami = "ami-0c3fd0f5d33134a76"
instance_type = "t3.micro"
tags = {
Name = "example"
}
}
その後、Apacheをインストールするために次のようにmain.tf
を修正する流れです。
resource "aws_instance" "example" {
ami = "ami-0c3fd0f5d33134a76"
instance_type = "t3.micro"
user_data = <<EOF
#!/bin/bash
yum install -y httpd
systemctl start httpd.service
EOF
}
ここでterraform apply
を実行すると、aws_instance.example must be replaced
というメッセージが出る想定となっています。
このメッセージは「既存のリソースを削除して新しいリソースを作成する」という意味です。
実際の動作
ところが僕のローカル環境では代わりに、aws_instance.example will be updated in-place
というメッセージが出ました。
example % terraform apply
aws_instance.example: Refreshing state... [id=i-0473f6955dab192a1]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
# aws_instance.example will be updated in-place
~ resource "aws_instance" "example" {
id = "i-0473f6955dab192a1"
~ tags = {
- "Name" = "example" -> null
}
~ tags_all = {
- "Name" = "example" -> null
}
+ user_data = "5f11f9fb893f5c269243dd3d8efe2bc57983f538"
# (38 unchanged attributes hidden)
# (8 unchanged blocks hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
実行結果も異なる
書籍では元のEC2インスタンスを削除して新しいEC2インスタンスが作成される想定となっています。
しかし実際には、新しいEC2インスタンスが作成されることなく、元のEC2インスタンスが更新されていました。
結論
結論として、Terraform自体の問題ではなくterraform-provider-aws
のバージョンが原因でした。
terraform-provider-aws
とは?
terraform-provider-aws
とは、TerraformでAWSのリソースを管理するためのプラグインです。
このプラグインによりTerraformへAWS固有の機能を追加できます。
terraform init
コマンドを実行したときに自動でダウンロードされていました。
terraform-provider-aws
のバージョン4.2.0から仕様変更されたようです。
- 4.1.0まで: リソースの置き換えで
user_data
を更新 - 4.2.0から: リソースは置き換えずそのまま
user_data
を更新
下記のPRで変更がマージされていました。
再現方法
第2章の最初のコードでterraform-provider-aws
のバージョン指定を追記した上で、terraform init
を実行します。
# この部分を追加
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.1.0" # このバージョンだと must be replaced が出る
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
resource "aws_instance" "example" {
ami = "ami-0c3fd0f5d33134a76"
instance_type = "t3.micro"
}
その後は流れに沿って進めると、書籍と同様にaws_instance.example must be replaced
のメッセージが出ました。
EC2インスタンスの立ち上がり方も書籍と同様でした。
おわりに
『実践Terraform』はとてもわかりやすいため、初学者にもおすすめです。
ただし出版が2019年なので現在とは異なる点もあります。
今後もそういった箇所が見つかったら、適宜調べてさらにTerraformの理解を深めていきたいと思います。
また、この記事に誤りがありましたらコメントにて教えていただけますと幸いです。
参考資料