Terraform で作ったEC2インスタンスのタイプを変更するには

  • 4
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

Terraform で作ったEC2インスタンスのタイプを変更するには、Terraformだけでは行えません。
そのままtfファイルを変更してしまうと recreate されてしまい、既存のインスタンスは破棄されてしまいます。

簡単にまとめると、以下の手順を行います。

  1. InstanceをStopする
  2. Instance Typeを変更する
  3. tfファイルを変更する
  4. InstanceをStartする

もしくは、ignore_changes を使うという手段もあります。

パターン1: Instance TypeをTerraform外で変更する

  • tf ファイル
provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_instance" "instance1" {
  ami                    = "ami-29160d47" # Amazon Linux AMI 2016.03.1 x86_64 HVM GP2
  instance_type          = "t2.micro"
  key_name               = "key"
  vpc_security_group_ids = ["sg-deadbeef"]
  subnet_id              = "subnet-badcafe"

  root_block_device {
    volume_type           = "gp2"
    delete_on_termination = true
  }
}
output "instance_id" {
  value = "${aws_instance.instance1.id}"
}

まず、t2.microでインスタンスを起動します。

$ terraform apply
(snip)
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate

Outputs:

instance_id = i-08718c36c1b7e95cb

AWS CLIを使いInstanceをStop状態にします。
Management Consoleを使ってもよいです。
TerraformでStopしたいというIssueは上がってますが、対応は未定のようです。

$ aws ec2 stop-instances --instance-ids i-08718c36c1b7e95cb
{
    "StoppingInstances": [
        {
            "InstanceId": "i-08718c36c1b7e95cb",
            "PreviousState": {
                "Code": 16,
                "Name": "running"
            },
            "CurrentState": {
                "Code": 64,
                "Name": "stopping"
            }
        }
    ]
}

AWS CLIを使い、Instance Typeを変更します。
Management Consoleを使ってもよいです。

$ aws ec2 modify-instance-attribute --instance-id i-08718c36c1b7e95cb --instance-type t2.nano

最後に、tfファイルを変更します。
これをしない場合は以下のようにリソースが作り直されます。

$ terraform plan
Refreshing Terraform state prior to plan...

aws_instance.instance1: Refreshing state... (ID: i-08718c36c1b7e95cb)

The Terraform execution plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning. Green resources
will be created (or destroyed and then created if an existing resource
exists), yellow resources are being changed in-place, and red resources
will be destroyed. Cyan entries are data sources to be read.

Note: You didn't specify an "-out" parameter to save this plan, so when
"apply" is called, Terraform can't guarantee this is what will execute.

-/+ aws_instance.instance1
    ami:                                       "ami-29160d47" => "ami-29160d47"
    availability_zone:                         "ap-northeast-1a" => "<computed>"
    ebs_block_device.#:                        "0" => "<computed>"
    ephemeral_block_device.#:                  "0" => "<computed>"
    instance_state:                            "stopped" => "<computed>"
    instance_type:                             "t2.micro" => "t2.nano" (forces new resource)
    key_name:                                  "key" => "key"
    placement_group:                           "" => "<computed>"
    private_dns:                               "ip-172-31-7-110.ap-northeast-1.compute.internal" => "<computed>"
    private_ip:                                "172.31.7.110" => "<computed>"
    public_dns:                                "" => "<computed>"
    public_ip:                                 "" => "<computed>"
    root_block_device.#:                       "1" => "1"
    root_block_device.0.delete_on_termination: "true" => "true"
    root_block_device.0.iops:                  "24" => "<computed>"
    root_block_device.0.volume_size:           "8" => "<computed>"
    root_block_device.0.volume_type:           "gp2" => "gp2"
    security_groups.#:                         "0" => "<computed>"
    source_dest_check:                         "true" => "true"
    subnet_id:                                 "subnet-badcafe" => "subnet-badcafe"
    tenancy:                                   "default" => "<computed>"
    vpc_security_group_ids.#:                  "1" => "1"
    vpc_security_group_ids.1346577894:         "sg-deadbeef" => "sg-deadbeef"


Plan: 1 to add, 0 to change, 1 to destroy.
  • tfファイル差分
-  instance_type          = "t2.micro"
+  instance_type          = "t2.nano"

修正後、planを実行すると無事No changesになります。

$ terraform plan
Refreshing Terraform state prior to plan...

aws_instance.instance1: Refreshing state... (ID: i-08718c36c1b7e95cb)

No changes. Infrastructure is up-to-date. This means that Terraform
could not detect any differences between your configuration and
the real physical resources that exist. As a result, Terraform
doesn't need to do anything.

パターン2: ignore_changes を利用する

  • tf ファイル
provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_instance" "instance1" {
  ami                    = "ami-29160d47" # Amazon Linux AMI 2016.03.1 x86_64 HVM GP2
  instance_type          = "t2.micro"
  key_name               = "key"
  vpc_security_group_ids = ["sg-deadbeef"]
  subnet_id              = "subnet-badcafe"

  root_block_device {
    volume_type           = "gp2"
    delete_on_termination = true
  }

  lifecycle {
    ignore_changes = ["instance_type"]
  }
}
output "instance_id" {
  value = "${aws_instance.instance1.id}"
}

lifecycle ルールで instance_type が変化しても無視するようになります。
パターン1で行ったAWS CLIやManagement Consoleで自由に変更できます。

ただ、この方法だと tf ファイルでの定義と実際の状態が異なることになるため、管理上よくないことになるかもしれません。
運用方法と相談してご使用下さい。