terraform-aws-modules / terraform-aws-ec2-instance

Terraform module to create AWS EC2 instance(s) resources πŸ‡ΊπŸ‡¦
https://registry.terraform.io/modules/terraform-aws-modules/ec2-instance/aws
Apache License 2.0
754 stars 1.87k forks source link

Terraform wants to recreate instance #269

Closed kristianfzr closed 2 years ago

kristianfzr commented 2 years ago

Description

Hi there,

I am facing an issue when I deploy an instance and after that I try to plan it or add output(or even with no changes plan it), it tries to replace the instance and create a new one. I wanted to know is this normal and is it AWS related or there is something I am missing, it could be related to the ssh module, but its intended to create an SSH key for you and nothing else.

Versions

Module version = "~> 3.0"

Terraform v0.14.3

Reproduction Code [Required]

provider "aws" {
  region = var.region
}

locals {
  ami = "ami-01402852f45db7cf2"
  environment = "s"
  region_code = "apse2"
  app_code = "app"
  name = "ec2-${local.region_code}-${local.environment}-${local.app_code}"
}

resource "aws_eip" "openvpn" {
  instance = module.ec2_instance.id
  vpc      = true
  tags = {
    Name = "eip-${local.region_code}-${local.environment}-${local.app_code}"
  }
}

module "ec2_instance" {
  source  = "terraform-aws-modules/ec2-instance/aws"
  version = "~> 3.0"

  name = local.name

  ami                         = local.ami
  instance_type               = "t2.micro"
  key_name                    = module.ssh-key.key_name
  monitoring                  = false
  vpc_security_group_ids      = [data.terraform_remote_state.vpc.outputs.standard_app_security_group_id]
  subnet_id                   = data.terraform_remote_state.vpc.outputs.pub_subnet_ids[0]
  associate_public_ip_address = false

  root_block_device = [{
    delete_on_termination = true
    encrypted             = false
    volume_size           = "15"
    volume_type           = "gp3"
  }]

  tags = {
    Terraform   = "true"
    Environment = local.environment
    RegionCode  = local.region_code
    AppCode     = local.app_code
  }
}

module "ssh-key" {
  source    = "../../../../modules/ssh-key"
  namespace = local.name
}

Steps to reproduce the behavior:

terraform init after that terraform plan/apply

Expected behavior

After it being deployed once to not want to re-create it.

Actual behavior

Wants to re-create the instance even without changes to it.

Terminal Output Screenshot(s)

module.ec2_instance.aws_instance.this[0]: Refreshing state... [id=i-HIDDEN]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # module.ec2_instance.aws_instance.this[0] must be replaced
-/+ resource "aws_instance" "this" {
      ~ arn                                  = "HIDDEN" -> (known after apply)
      ~ associate_public_ip_address          = true -> false # forces replacement
      ~ availability_zone                    = "ap-southeast-2a" -> (known after apply)
      ~ cpu_core_count                       = 1 -> (known after apply)
      ~ cpu_threads_per_core                 = 1 -> (known after apply)
      ~ disable_api_termination              = false -> (known after apply)
      ~ ebs_optimized                        = false -> (known after apply)
      - hibernation                          = false -> null
      + host_id                              = (known after apply)
      ~ id                                   = "i-HIDDEN" -> (known after apply)
      ~ instance_initiated_shutdown_behavior = "stop" -> (known after apply)
      ~ instance_state                       = "running" -> (known after apply)
      ~ ipv6_address_count                   = 0 -> (known after apply)
      ~ ipv6_addresses                       = [] -> (known after apply)
      + outpost_arn                          = (known after apply)
      + password_data                        = (known after apply)
      + placement_group                      = (known after apply)
      + placement_partition_number           = (known after apply)
      ~ primary_network_interface_id         = "eni-HIDDEN" -> (known after apply)
      ~ private_dns                          = "ip-HIDDEN.ap-southeast-2.compute.internal" -> (known after apply)
      ~ private_ip                           = "HIDDEN" -> (known after apply)
      ~ public_dns                           = "HIDDEN.ap-southeast-2.compute.amazonaws.com" -> (known after apply)
      ~ public_ip                            = "HIDDEN" -> (known after apply)
      ~ secondary_private_ips                = [] -> (known after apply)
      ~ security_groups                      = [] -> (known after apply)
        tags                                 = {
            "AppCode"     = "app"
            "Environment" = "s"
            "Name"        = "HIDDEN"
            "RegionCode"  = "apse2"
            "Terraform"   = "true"
        }
      ~ tenancy                              = "default" -> (known after apply)
      + user_data                            = (known after apply)
      + user_data_base64                     = (known after apply)
        # (11 unchanged attributes hidden)

      ~ capacity_reservation_specification {
          ~ capacity_reservation_preference = "open" -> (known after apply)

          + capacity_reservation_target {
              + capacity_reservation_id = (known after apply)
            }
        }

      ~ credit_specification {
          - cpu_credits = "standard" -> null
        }

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + tags                  = (known after apply)
          + throughput            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      ~ enclave_options {
          ~ enabled = false -> (known after apply)
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_interface_id  = (known after apply)
        }

      ~ root_block_device {
          ~ device_name           = "/dev/sda1" -> (known after apply)
          ~ iops                  = 3000 -> (known after apply)
          + kms_key_id            = (known after apply)
          - tags                  = {} -> null
          ~ throughput            = 125 -> (known after apply)
          ~ volume_id             = "vol-HIDDEN" -> (known after apply)
            # (4 unchanged attributes hidden)
        }

        # (2 unchanged blocks hidden)
    }

Plan: 1 to add, 0 to change, 1 to destroy.

Additional context

antonbabenko commented 2 years ago

associate_public_ip_address = true -> false # forces replacement

It means, you're changing associate_public_ip_address in your configuration, and AWS wants to recreate this instance. This is expected behavior.

kristianfzr commented 2 years ago

@antonbabenko Thats really the case! But what stands out to me is: I deploy it initially with that statement to false after that with the EIP it gets associated with the instance after it has been deployed.. So it looks like the instance thinks it has no public IP address and when I re-apply/plan it catches the EIP attached and sets the it to false as it probably exists in the state file. My question will be if a set the value to true will that create a public_ip and on top add a EIP with the terraform EIP resource?

antonbabenko commented 2 years ago

I don't remember how it works internally, but the public IP of an instance and EIP are two different things in AWS.

Also, I just searched terraform AWS provider repo issues and found there were some similar: https://github.com/hashicorp/terraform-provider-aws/issues/8425

Search query: https://github.com/hashicorp/terraform-provider-aws/issues?q=is%3Aissue+associate_public_ip_address+aws_instance+is%3Aopen

I will close this one because this is not a problem with the module itself.

Please ask on https://discuss.hashicorp.com where much more people are.

github-actions[bot] commented 1 year ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.