Terraform AWS Launch Configuration Deep Dive and Migration Guidance

Launch configurations are the legacy mechanism for defining the template that Amazon EC2 Auto Scaling groups use to launch new instances. In Terraform, the aws_launch_configuration resource maps directly to the AWS API for launch configurations, and while AWS now actively discourages their use in favor of launch templates, many existing production stacks still rely on them. This article covers the resource in full depth from the reference documentation, including immutable behavior, lifecycle management with create_before_destroy, spot pricing, block device handling, import workflows, and the recommended migration path to aws_launch_template.

Introduction

Terraform providers expose AWS launch configurations as a declarative resource that couples an AMI, instance type, security settings, and optional launch parameters into a single named entity that an Auto Scaling group can reference. The resource is documented as providing a resource to create a new launch configuration, used for autoscaling groups. Because the underlying AWS API makes launch configurations immutable after creation, Terraform must destroy and recreate the resource on any change. That immutability drives the core operational pattern for Terraform users: use name_prefix instead of a static name, pair it with a lifecycle { create_before_destroy = true } block, and reference the configuration name in aws_autoscaling_group. The documentation explicitly warns that the use of launch configurations is discouraged in favor of launch templates, with a note in the AWS EC2 Documentation.

Resource Overview and Core Behavior

The AWS API treats a launch configuration as immutable. Launch Configurations cannot be updated after creation with the Amazon Web Service API. In order to update a Launch Configuration, Terraform will destroy the existing resource and create a replacement. In order to effectively use a Launch Configuration resource with an AutoScaling Group resource, it’s recommended to specify createbeforedestroy in a lifecycle block.

This behavior means any change to attributes such as image_id, instance_type, spot_price, or block device mappings triggers a destroy-create cycle. Without create_before_destroy, an Auto Scaling group would temporarily lose its launch configuration reference during the update window.

The recommended naming pattern avoids hard-coded names that would collide on replacement:

Either omit the Launch Configuration name attribute, or specify a partial name with name_prefix.

When using aws_launch_configuration with aws_autoscaling_group, it is recommended to use the name_prefix Optional instead of the name Optional attribute. This will allow Terraform lifecycles to detect changes to the launch configuration and update the autoscaling group correctly.

Required and Optional Arguments

The following arguments are required:

  • image_id - The EC2 image ID to launch.
  • instance_type - The size of instance to launch.

The following arguments are optional:

  • region - Optional Region where this resource will be managed. Defaults to the Region set in the provider configuration.
  • associate_public_ip_address - Optional Associate a public ip address with an instance in a VPC.
  • ebs_block_device - Optional Additional EBS block devices to attach to the instance. See Block Devices below for details.
  • ebs_optimized - Optional If true, the launched EC2 instance will be EBS-optimized.
  • enable_monitoring - Optional Enables/disables detailed monitoring.

Additional optional arguments documented in the provider include name, name_prefix, spot_price, key_name, security_groups, iam_instance_profile, user_data, ebs_optimized, and more. Spot pricing is a notable parameter for cost optimization.

Launch configurations can set the spot instance pricing to be used for the Auto Scaling Group to reserve instances. Simply specifying the spot_price parameter will set the price on the Launch Configuration which will attempt to reserve your instances at this price.

Example Usage Patterns

A minimal launch configuration using an AMI data source:

```hcl
data "awsami" "ubuntu" {
most
recent = true
filter {
name = "name"
values = ["ubuntu/images/ebs/ubuntu-trusty-14.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["paravirtual"]
}
owners = ["099720109477"] # Canonical
}

resource "awslaunchconfiguration" "asconf" {
name = "web
config"
imageid = data.awsami.ubuntu.id
instance_type = "t1.micro"
}
```

The same pattern with name_prefix and lifecycle for safe updates:

```hcl
data "awsami" "ubuntu" {
most
recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}

resource "awslaunchconfiguration" "asconf" {
name
prefix = "terraform-lc-example-"
imageid = data.awsami.ubuntu.id
instancetype = "t2.micro"
lifecycle {
create
before_destroy = true
}
}

resource "awsautoscalinggroup" "bar" {
name = "terraform-asg-example"
launchconfiguration = awslaunchconfiguration.asconf.name
minsize = 1
max
size = 2
lifecycle {
createbeforedestroy = true
}
}
```

With this setup Terraform generates a unique name for your Launch Configuration and can then update the AutoScaling Group without conflict before destroying the previous Launch Configuration.

Spot pricing example:

```hcl
data "awsami" "ubuntu" {
most
recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}

resource "awslaunchconfiguration" "asconf" {
image
id = data.awsami.ubuntu.id
instance
type = "m4.large"
spotprice = "0.001"
lifecycle {
create
before_destroy = true
}
}

resource "awsautoscalinggroup" "bar" {
name = "terraform-asg-example"
launchconfiguration = awslaunchconfiguration.asconf.name
}
```

Attributes Reference and Import

Attributes Reference exported by the resource:

  • id - The ID of the launch configuration.

Import support is name based:

Launch configurations can be imported using the name, e.g.

$ terraform import aws_launch_configuration.as_conf terraform-lg-123456

In Terraform v1.5.0 and later, use an import block to import launch configurations using the name. For example:

hcl import { to = aws_launch_configuration.example identity = { name = "example" } }

Using terraform import, import launch configurations using the name. For example:

% terraform import aws_launch_configuration.example example

Attribute metadata also includes:

  • name - String name of the launch configuration.
  • account_id - String AWS Account where this resource is managed.
  • region - String Region where this resource is managed.

Block Device Considerations

AWS publishes a list of which ephemeral devices are available on each type. The devices are always identified by the virtual_name in the format "ephemeral{0..N}".

Terraform provides a note on block device changes:

~> NOTE: Changes to *blockdevice configuration of existing resources cannot currently be detected by Terraform. After updating to block device configuration, resource recreation can be manually triggered by using the taint command.

This limitation is important when using ebs_block_device or ephemeral device mappings. Because Terraform cannot detect drift, manual recreation may be required.

Launch Configuration Spec Summary

Attribute Type Required Description
image_id string Yes The EC2 image ID to launch
instance_type string Yes The size of instance to launch
name string No name of the launch configuration
name_prefix string No Prefix for generated name
spot_price string No Max price for Spot instances
ebs_optimized bool No If true, launched EC2 instance will be EBS-optimized
enable_monitoring bool No Enables/disables detailed monitoring
associatepublicip_address bool No Associate a public IP in VPC
ebsblockdevice block No Additional EBS block devices

Launch Templates as the Preferred Alternative

AWS and Terraform now recommend launch templates over launch configurations. The provider documentation includes the warning:

!> WARNING: The use of launch configurations is discouraged in favor of launch templates. Read more in the AWS EC2 Documentation.

Launch templates offer versioning, support for more instance types, and richer metadata. A production-ready launch template in Terraform typically includes:

  • AMI lookup with most recent filter
  • Instance type
  • Security groups
  • IAM instance profile
  • Base64 encoded user data
  • Tag specifications for instances and volumes
  • Lifecycle create_before_destroy with name_prefix

Example from production guidance:

```hcl
data "awsami" "al2023" {
most
recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}

resource "awslaunchtemplate" "app" {
nameprefix = "app-"
description = "Launch template for application servers"
image
id = data.awsami.al2023.id
instance
type = "t3.medium"
lifecycle {
createbeforedestroy = true
}
vpcsecuritygroupids = [
aws
securitygroup.app.id,
aws
securitygroup.monitoring.id,
]
iam
instanceprofile {
name = aws
iaminstanceprofile.app.name
}
userdata = base64encode(templatefile("${path.module}/scripts/bootstrap.sh", {
environment = var.environment
app
version = var.appversion
}))
tag
specifications {
resourcetype = "instance"
tags = {
Name = "app-server"
Environment = var.environment
}
}
tag
specifications {
resource_type = "volume"
tags = {
Name = "app-server-volume"
Environment = var.environment
}
}
}
```

This pattern mirrors launch configuration essentials while adding template versioning and safer updates.

Comparison: Launch Configuration vs Launch Template

Feature Launch Configuration Launch Template
Immutability Immutable after creation Versioned, mutable
AWS Recommendation Discouraged Recommended
Spot support spot_price parameter Multiple pricing options
User data Supported Supported, base64 required
Tagging Limited tag_specifications for instance/volume
Name handling name / name_prefix name_prefix recommended

Best Practices for Existing Launch Configurations

When you must maintain launch configurations:

  • Always use name_prefix instead of a fixed name to allow Terraform to generate unique names on replacement.
  • Set lifecycle { create_before_destroy = true } on both the launch configuration and the autoscaling group.
  • Reference the launch configuration by aws_launch_configuration.as_conf.name in the ASG.
  • Pin AMI lookups with filters and most_recent = true for repeatable builds.
  • Avoid changes to ebs_block_device without planning a manual taint, as Terraform cannot detect drift.
  • Plan migration to aws_launch_template with aws_autoscaling_group using launch_template { id = ... version = "$Latest" }.

Conclusion

The aws_launch_configuration resource remains a functional bridge for teams with legacy Auto Scaling groups, but its immutable nature imposes operational constraints that require careful lifecycle management. The combination of name_prefix and create_before_destroy is essential to avoid service interruption during updates, and spot pricing can be injected via spot_price for cost-sensitive workloads. Attribute support covers the required image_id and instance_type, with optional controls for EBS optimization, monitoring, public IP association, and block devices, though block device drift remains undetectable by Terraform.

Import workflows are straightforward using the launch configuration name, with both legacy terraform import commands and v1.5+ import blocks supported. Given the explicit provider warning that the use of launch configurations is discouraged in favor of launch templates, new designs should adopt aws_launch_template for versioning, richer tagging, and future-proof compatibility, while existing launch configurations should be maintained with the safe naming and lifecycle patterns described here until migration is feasible.

Sources

  1. awslaunchconfiguration
  2. create-launch-templates-for-auto-scaling-in-terraform
  3. awslaunchconfiguration

Related Posts