How to apply using Terraform to launch multiple EC2 Resource with different configs (VPC not maintained by TF)

6,084

You can use a remote backend as a data source. That is working well for us thus far but this project is not very mature and we will likely refactor a time or ten.

data "terraform_remote_state" "network" {
  backend = "s3"
  config {
    // some variables related to config would likely go here
  }
}

then for the teams not managing the network to consume that data you could create an instance like (special attention to the subnet_id here):

resource "aws_instance" "oracle_ec2" {
  ami           = "${lookup(var.ami, var.region)}"
  instance_type = "${var.instance_type}"
  key_name      = "${var.key_name}"
  subnet_id     = "${data.terraform_remote_state.network.subnet_id}"
}

The network team should be able to manage the networking infrastructure and you should be able to consume those values based on current state.

Terraform Remote State Data Source

2) If new instances launch as t2.large(Instance type passed as variable) while old ones run on t2.micro

If you change the instance type from t2.micro to t2.large then yes the t2.micro instances will be destroyed and replaced with the t2.large. The name of the game is immutability outside of meta data changes like altering tags. Look into lifecycle hooks to alleviate some of this pain

lifecycle {
  create_before_destroy = true
}

will it recreate old instances too if I just increase the count

No, current instances would not be destroyed. Terraform will check the state to see how many instances you currently have. If more instances are necessary, terraform will know how many instances to create and create the instances necessary

Also, is there a way to automate this process i.e. append something like a template for new EC2 instance to existing .tf file.

Not sure what exactly you mean by this one. What I will say is that having the data coupled to the instance itself makes instance immutability and using terraform more difficult. A (untested and unproven) thought and potential solution in my head is to:

//create an ebs volume
resource "aws_ebs_volume" "oracle-data" {
  ...
}

//attach that volume to the instance
resource "aws_volume_attachment" "oracle-data-attachment" {
  ...
}

with some bash involved for an init script that creates and mounts the new volume to be used in conjunction with the aws_volume_attachment resource. That could potentially create a new instance preserving the EBS volume then reattaching it to the new instance.

Share:
6,084

Related videos on Youtube

Dvusrgme
Author by

Dvusrgme

Updated on September 18, 2022

Comments

  • Dvusrgme
    Dvusrgme over 1 year

    We are planning to use Terraform for provisioning EC2 instance which will host Oracle DB. While we are able to achieve this, there are some questions for which I am searching for suggestions / feedback's.

    Below is the directory structure we are planning:

    |aws      
      |Environments
        |STAGING
            |Modules
               |Compute
               |Networking
    
        |PRODUCTION
            |Modules
               |Compute
               |Networking
    

    Questions:

    • We are able to create EC2 instances using existing VPC. As VPC is not something that will be owned by my team. Is it enough to keep VPC ID, SUBNET ID, etc as variables in EC2 resource or is there a best practice to keep them in modules for existing VPC ? Overall, our tf codes are not going to manage the VPC's, just use what is being giving to us, but want to make it dynamic so that changes are simple, yet DRY

    • We are planning for Continuous Development, meaning, developers / requester will have the ability to request for a new ec2 instance with certain version of database. Right now, we are installing db with bootstrap scripts. Though this works as expected. Increasing count for more than 1 instance works, but what if the configuration slightly changes.

    For example:

    1) If I need more capacity on root volume for the new instance, changing the existing resource shows a plan that will destroy existing resource and recreate. How can we achieve this ? Is duplicating the aws_instance resource, the only way when the configuration changes for new EC2 instance?

    2) If new instances launch as t2.large(Instance type passed as variable) while old ones run on t2.micro, will it recreate old instances too if I just increase the count

    Also, is there a way to automate this process i.e. append something like a template for new EC2 instance to existing .tf file.

    What do we have now

    Main.tf

    provider "aws" {
      access_key = "${var.access_key}"
      secret_key = "${var.secret_key}"
      region     = "${var.region}"
    }
    
    resource "aws_instance" "oracle_ec2" {
      ami           = "${lookup(var.ami, var.region)}"
      instance_type = "${var.instance_type}"
      key_name      = "${var.key_name}"
      subnet_id     = "${var.subnet_id}"
    
      vpc_security_group_ids = ["${aws_security_group.oracle_sg_new.id}"]
    
      root_block_device {
        volume_type           = "gp2"
        volume_size           = 10
        delete_on_termination = true
      }
    
      ebs_block_device {
        device_name           = "/dev/xvdb"
        volume_type           = "gp2"
        volume_size           = 200
        delete_on_termination = true
      }    
    
      count = "${var.instance_count}"
    
      tags {
        Name = "Ora"
      }
    
    }
    
  • Dvusrgme
    Dvusrgme over 6 years
    Thanks @TechDawg for the details answer, just had the opportunity to get back to Terraform. I will try to rephrase my last question. Assuming, I have 5 t2.medium EC2 instances running already. I would like to add 5 more EC2 Instances but with a different set of configuration, this new change is going to flow from ServiceNow which the user will be using to choose the type of hardware. Should this new request, be turned into a template for EC2 instance and get appended as new set of EC2 resources in the TF file ?
  • Dvusrgme
    Dvusrgme over 6 years
    For example: For example: ----Current--> resource "aws_instance" "oracle_ec2" { ami = "${lookup(var.ami, var.region)}" instance_type = "t2.medium" count = 5 } ----Append ---> resource "aws_instance" "oracle_ec2" { ami = "${lookup(var.ami, var.region)}" instance_type = "m4.xlarge" count = 5 }