How to avoid the destroy action in terraform apply?

18.3k views Asked by At
My Terraform resource file looks like this :

resource "aws_instance" "ubuntu14" {
    instance_type = "t2.medium"
    ami = "${lookup(var.aws_amis_ubuntu14,var.aws_region)}"
    tags {
        Name = "${var.user_label} - Ubuntu 14 - Fresh Agent Install - ${count.index}"
    }
    key_name = "${var.aws_key_name}"
    vpc_security_group_ids = ["${lookup(var.security_group_id,var.aws_region)}"]
    count = "${var.count}"

....

I already have a machine running and do not want to destroy it .

How do i achieve that in terraform apply?

Terraform plan shows the following : Plan: 2 to add, 0 to change, 1 to destroy.

I want to keep all 3

2

There are 2 answers

1
mcheshier On BEST ANSWER

Unfortunately you'll have to take the information out of your state file. You can do this by hand (tedious and not recommended) or you can use Terraform state rm.

See documentation at: https://www.terraform.io/docs/commands/state/rm.html

0
Yevgeniy Brikman On

I already have a machine running and do not want to destroy it

There are two ways to interpret this statement:

  1. You deployed this same EC2 Instance using something other than Terraform (e.g. using the AWS console or AWS CLI) and now you want to manage it with Terraform instead.
  2. You deployed this EC2 Instance using Terraform, you've changed some parameter (e.g. the AMI ID), and now you want to deploy that change.

Depending on which of these statements is true, you need to take different actions:

Option 1: using Terraform to manage existing infrastructure

You can use the Terraform import command to allow Terraform to manage this existing instance. Look up the existing instance's ID in the EC2 console and run the following command:

terraform import aws_instance.ubuntu14 <YOUR_INSTANCE_ID>

Now, when you run terraform plan, the only changes will be any differences in the code versus what's actually running.

Option 2: using Terraform to deploy changes to EC2 Instances

For most changes to an EC2 Instance, such as changing the AMI ID, user data, or IAM role, Terraform will destroy the old Instance and deploy a new one. There is no way to update those parameters "in place" with Terraform, as AWS itself doesn't let you update them!

Therefore, you have a few options:

  1. If you just want to update the code running on the Instance (e.g. run apt-get install to add some new dependency), SSH to the Instance and make your updates on it directly. Alternatively, you could use a configuration management tool such as Chef, Puppet, or Ansible to manage all of that for you.
  2. Otherwise, your only option is to replace the Instance. There are ways of doing this with no visible downtime for your users. The typical approach is to put an Elastic IP (EIP) Address or Elastic Load Balancer (ELB) in front of the Instance, point users to that EIP or ELB, and when deploying changes, you create a new Instance first, attach it to the EIP or ELB once it's booted, and then remove the old Instance. Check out my answer to Terraform and Updates for details and sample code. (Note: if your Instance is stateful—that is, it stores data on its local hard-drive—then you'll need to store that data on an EBS volume, detach it from the old Instance, and attach it to the new one. This cannot be done instantaneously, so with a single Instance, you won't be able to do it without downtime.)