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

repository·master·Indexed 21 days ago

https://github.com/terraform-aws-modules/terraform-aws-ec2-instance

A Terraform module for provisioning AWS EC2 instances. It supports single or multiple instances, Spot instances, and associated resources including IAM profiles, Elastic IPs, and Security Groups. Features include support for T2/T3 Unlimited credits, private network access via AWS Systems Manager (SSM) Session Manager, and dynamic AMI fetching via SSM parameters.

Tokens
9.1K
Snippets
21
Records
37
Agent score
73%

What's inside terraform-aws-ec2-instance

  1. Use the module wrapper for multiple instances

    master

    The wrappers sub-module implements a single module wrapper pattern. This allows you to manage multiple instances of the EC2 module within a single configuration block. This is particularly useful in environments like Terragrunt where native Terraform for_each might not be feasible for managing multiple resource copies without duplicating configuration files.

    Note that this wrapper does not add any new functionality; it simply iterates over a map of items using the arguments provided by the root module.

  2. Migrate root block device configuration to v6.x

    master

    In v6.x, the root_block_device configuration has changed from a list to a single object, as an instance can only have one root block device.

    Configuration Changes

    • Data Structure: Change from a list(object) to a single object.
    • Attribute Names:
      • volume_size is now size.
      • volume_type is now type.
    # v6.x Root Block Device Configuration
    root_block_device = {
      encrypted   = true
      size        = 50
      type        = "gp3"
      throughput  = 200
      tags = {
        Name = "my-root-block"
      }
    }
  3. Important usage constraints

    master

    When configuring the module, be aware of the following constraints:

    • Network Interface Conflict: You cannot specify network_interface at the same time as vpc_security_group_ids, associate_public_ip_address, or subnet_id.
    • Spot Instance KMS Permissions: As noted in the Spot EC2 section, ensure AWSServiceRoleForEC2Spot has access to custom KMS keys to avoid bad parameters errors.
  4. Migrate EBS volume configuration to v6.x

    master

    In v6.x, the module has moved from a list-based EBS configuration to a map-based configuration using ebs_volumes. This change allows for more flexible management of EBS volumes via aws_ebs_volume and aws_volume_attachment resources without causing unintended diffs.

    Configuration Changes

    • Variable Name: Rename ebs_block_device to ebs_volumes.
    • Data Structure: Change from a list(object) to a map(object).
    • Attribute Names:
      • volume_size is now size.
      • volume_type is now type.
    • Keys: The map key can be the device_name (e.g., "/dev/sdf"), or you can specify the device_name attribute within the object.
    # v6.x EBS Volume Configuration
    ebs_volumes = {
      "/dev/sdf" = {
        encrypted  = true
        size       = 5
        type       = "gp3"
        throughput = 200
        tags = {
          MountPoint = "/mnt/data"
        }
      }
    }
  5. Configure the wrapper with Terragrunt

    master

    To use the wrapper with Terragrunt, define the source in the terraform block and provide configuration via the inputs block. You must provide two main maps:

    1. defaults: A map of arguments that will be applied to every instance.
    2. items: A map where each key represents a unique instance and the value is a map of arguments specific to that instance. Any argument supported by the base EC2 instance module can be used here.
    terraform {
      source = "tfr:///terraform-aws-modules/ec2-instance/aws//wrappers"
    }
    
    inputs = {
      defaults = {
        create = true
        tags = {
          Terraform   = "true"
          Environment = "dev"
        }
      }
    
      items = {
        my-item = {
          # any argument supported by the module
        }
        my-second-item = {
          # any argument supported by the module
        }
      }
    }
  6. Upgrade from v5.x to v6.x

    master

    When upgrading the terraform-aws-modules/ec2-instance/aws module from version 5.x to 6.x, note the following breaking changes and requirements:

    Requirements

    • Terraform version: Minimum v1.10.0 required.
    • AWS provider version: Minimum v6.0.0 required.

    Breaking Changes

    • AMI Default: The ami_ssm_parameter default changed from Amazon Linux 2 (/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2) to Amazon Linux 2023 (/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64).
    • EBS Configuration: The ebs_block_device list has been removed and replaced by the ebs_volumes map.
    • Variable Types: Variable definitions now use detailed object types instead of any.
    • Removed Variables: cpu_core_count and cpu_threads_per_core are no longer supported.
  7. Generate an encrypted AMI for use with the module

    master

    The module does not support encrypted AMIs natively. To use an encrypted AMI, you must first create one by copying an existing unencrypted AMI and setting encrypted = true. You can then reference this new AMI in your module configuration.

    provider "aws" {
      region = "us-west-2"
    }
    
    data "aws_ami" "ubuntu" {
      most_recent = true
      owners      = ["679593333241"]
    
      filter {
        name   = "name"
        values = ["ubuntu-minimal/images/hvm-ssd/ubuntu-focal-20.04-*"]
      }
    
      filter {
        name   = "virtualization-type"
        values = ["hvm"]
      }
    }
    
    resource "aws_ami_copy" "ubuntu_encrypted_ami" {
      name              = "ubuntu-encrypted-ami"
      description       = "An encrypted root ami based off ${data.aws_ami.ubuntu.id}"
      source_ami_id     = data.aws_ami.ubuntu.id
      source_ami_region = "eu-west-2"
      encrypted         = true
    
      tags = { Name = "ubuntu-encrypted-ami" }
    }
    
    data "aws_ami" "encrypted-ami" {
      most_recent = true
    
      filter {
        name   = "name"
        values = [aws_ami_copy.ubuntu_encrypted_ami.id]
      }
    
      owners = ["self"]
    }
  8. Configure the wrapper with Terraform

    master

    To use the wrapper directly in Terraform, call it as a module and pass the defaults and items maps. The items map keys will define the unique identifiers for each instance created by the wrapper.

    module "wrapper" {
      source = "terraform-aws-modules/ec2-instance/aws//wrappers"
    
      defaults = {
        create = true
        tags = {
          Terraform   = "true"
          Environment = "dev"
        }
      }
    
      items = {
        my-item = {
          # any argument supported by the module
        }
        my-second-item = {
          # any argument supported by the module
        }
      }
    }
  9. Connect to the EC2 instance using AWS CLI Session Manager

    master

    Once the infrastructure is deployed, you can connect to the private EC2 instance using the AWS CLI.

    1. Install the Plugin: You must have the Session Manager plugin for the AWS CLI installed on your local machine.
    2. Retrieve the Command: The Terraform output ssm_connect_command provides the exact command needed for your specific instance and region.
    3. Execute: The command follows this format:
      aws ssm start-session --target <INSTANCE-ID> --region <REGION>
    aws ssm start-session --target <INSTANCE-ID> --region <REGION>
  10. Run the complete EC2 instance example

    master

    To deploy the complete EC2 instance configuration, which demonstrates various arguments such as Elastic IPs, network interfaces, and credit specifications, execute the standard Terraform workflow.

    Warning: This example creates real AWS resources that may incur costs. Ensure you run terraform destroy to clean up resources when finished.

    $ terraform init
    $ terraform plan
    $ terraform apply
  11. Perform State Migration for v2.x to v3.x Upgrade

    master

    If you are upgrading from v2.x (which used instance_count) to v3.x (which uses for_each), you must move your existing resources in the Terraform state to avoid recreation.

    If your v2.x module was configured with instance_count = 3, use the following commands to map the indexed resources to the new for_each map keys:

    terraform state mv 'module.ec2_upgrade.aws_instance.this[0]' 'module.ec2_upgrade["0"].aws_instance.this[0]'
    terraform state mv 'module.ec2_upgrade.aws_instance.this[1]' 'module.ec2_upgrade["1"].aws_instance.this[0]'
    terraform state mv 'module2_upgrade.aws_instance.this[2]' 'module.ec2_upgrade["2"].aws_instance.this[0]'
    terraform state mv 'module.ec2_upgrade.aws_instance.this[0]' 'module.ec2_upgrade["0"].aws_instance.this[0]'
    terraform state mv 'module.ec2_upgrade.aws_instance.this[1]' 'module.ec2_upgrade["1"].aws_instance.this[0]'
    terraform state mv 'module.ec2_upgrade.aws_instance.this[2]' 'module.ec2_upgrade["2"].aws_instance.this[0]'
  12. Deploy an EC2 instance with private network access via Session Manager

    master

    This configuration creates an EC2 instance that is not connected to the Internet. Instead, it provides private network access using AWS Systems Manager (SSM) Session Manager through VPC Endpoints. This setup allows for secure management of instances without requiring public IP addresses or internet gateways.

    Requirements

    • Terraform: >= 1.5.7
    • AWS Provider: >= 6.37

    Deployment Steps

    1. Initialize the working directory:
      terraform init
    2. Review the execution plan:
      terraform plan
    3. Apply the configuration:
      terraform apply
    WARNING

    This example creates resources that may incur costs. Run terraform destroy to clean up resources when they are no longer needed.

    $ terraform init
    $ terraform plan
    $ terraform apply