Guide: Managing EC2 and Compute
Relevant source files
The following files were used as context for generating this wiki page:
This guide provides a comprehensive overview of how to provision and manage AWS EC2 and related compute resources using the Terraform AWS provider. The provider allows for full lifecycle management of AWS resources, enabling declarative infrastructure-as-code practices. The information and examples herein are derived from a reference implementation that deploys an ECS cluster on an EC2-backed Auto Scaling Group.
The core components covered include networking (VPC, Subnets), security (Security Groups), and the compute layer itself, which consists of Auto Scaling Groups, Launch Configurations, and EC2 instances. This guide also details the necessary IAM roles and profiles required for the instances to function correctly within the AWS ecosystem.
Sources: README.md, examples/ecs-alb/main.tf
Core Architecture
The fundamental architecture involves creating a set of scalable EC2 instances within a custom VPC to host a containerized application. An Application Load Balancer (ALB) distributes traffic to the instances, which are managed by an Auto Scaling Group (ASG).
The following diagram illustrates the high-level relationship between the key resources defined.
This diagram shows how user traffic flows through an ALB to EC2 instances within public subnets. The instances are managed by an Auto Scaling Group and have outbound internet access via an Internet Gateway.
Sources: examples/ecs-alb/main.tf:16-29, 57-64, 185-191, 201-209
Compute Layer Management
The compute layer is managed through a combination of an Auto Scaling Group and a Launch Configuration. This pairing ensures that a specified number of instances are always running and that new instances are configured correctly when launched.
Sources: internal/service/ec2/README.md
Auto Scaling Group (aws_autoscaling_group)
The aws_autoscaling_group resource manages the collection of EC2 instances. It defines the desired, minimum, and maximum number of instances, and across which subnets they should be launched.
| Parameter | Description | Example Value |
|---|---|---|
name | A unique name for the ASG. | "tf-test-asg" |
vpc_zone_identifier | A list of subnet IDs to launch instances into. | aws_subnet.main.*.id |
min_size | The minimum number of instances in the group. | var.asg_min |
max_size | The maximum number of instances in the group. | var.asg_max |
desired_capacity | The desired number of instances. | var.asg_desired |
launch_configuration | The name of the launch configuration to use. | aws_launch_configuration.app.name |
Sources: examples/ecs-alb/main.tf:57-64
Launch Configuration (aws_launch_configuration)
The aws_launch_configuration resource acts as a template for creating new EC2 instances. It specifies the AMI, instance type, key pair, security groups, and IAM instance profile. It also supports a user_data script for bootstrap actions.
The relationship between these components is as follows:
This flow shows that an Auto Scaling Group uses a Launch Configuration to define the properties of the EC2 instances it creates.
Sources: examples/ecs-alb/main.tf:95-110
A key feature is the user_data attribute, which allows for instance initialization at launch time. In the reference example, it uses a template_file to pass dynamic configuration, such as the ECS cluster name, to a cloud-config.yml script.
# examples/ecs-alb/main.tf:66-76
data "template_file" "cloud_config" {
template = file("${path.module}/cloud-config.yml")
vars = {
aws_region = var.aws_region
ecs_cluster_name = aws_ecs_cluster.main.name
ecs_log_level = "info"
ecs_agent_version = "latest"
ecs_log_group_name = aws_cloudwatch_log_group.ecs.name
}
}
# examples/ecs-alb/main.tf:105-106
resource "aws_launch_configuration" "app" {
// ...
user_data = data.template_file.cloud_config.rendered
// ...
}
Sources: examples/ecs-alb/main.tf:66-76, 106
Security and Networking
Properly configured networking and security are critical for a secure and functional compute environment. This involves defining VPC-level security groups to control traffic to and from the instances.
Security Groups (aws_security_group)
Two primary security groups are defined: one for the load balancer (lb_sg) and one for the instances (instance_sg).
| Resource Name | Description |
|---|---|
aws_security_group.lb_sg | Controls access to the application load balancer. |
aws_security_group.instance_sg | Controls direct access to the application instances. |
Sources: examples/ecs-alb/main.tf:115-136, 138-171
The following diagram illustrates the traffic flow rules between the internet, the load balancer, and the EC2 instances.
This diagram shows that the Load Balancer Security Group allows inbound HTTP traffic from anywhere. The Instance Security Group allows SSH from a specific admin CIDR and ephemeral TCP traffic from the Load Balancer Security Group. Both allow all outbound traffic.
Sources: examples/ecs-alb/main.tf:121-125, 146-152, 154-162
Instance Security Group Rules (instance_sg)
| Type | Protocol | Port Range | Source | Description |
|---|---|---|---|---|
| Ingress | tcp | 22 | var.admin_cidr_ingress | Allows SSH access from a specified admin IP block. |
| Ingress | tcp | 32768-61000 | aws_security_group.lb_sg.id | Allows traffic from the ALB on the ephemeral port range. |
| Egress | -1 (All) | 0-0 | 0.0.0.0/0 | Allows all outbound traffic. |
Sources: examples/ecs-alb/main.tf:146-170
IAM for Compute Instances
EC2 instances often require permissions to interact with other AWS services. This is managed via an aws_iam_instance_profile, which attaches an aws_iam_role to the instance.
Sources: internal/service/iam/README.md
The relationship is defined as follows:
- An
aws_iam_roleis created with a trust policy allowing theec2.amazonaws.comservice to assume it. - An
aws_iam_role_policyis attached to the role, granting specific permissions (e.g., to register with ECS, write logs to CloudWatch). - An
aws_iam_instance_profileis created and linked to the role. - The instance profile is assigned to instances via the
iam_instance_profileattribute in theaws_launch_configuration.
This flow demonstrates how a Launch Configuration assigns an Instance Profile to an EC2 instance, which in turn contains a Role with specific permissions and a trust relationship with the EC2 service.
Sources: examples/ecs-alb/main.tf:104, 193-228
The following code snippet shows the definition of the instance profile and its link to the role.
# examples/ecs-alb/main.tf:193-196
resource "aws_iam_instance_profile" "app" {
name = "tf-ecs-instprofile"
role = aws_iam_role.app_instance.name
}
# examples/ecs-alb/main.tf:198-213
resource "aws_iam_role" "app_instance" {
name = "tf-ecs-example-instance-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
Sources: examples/ecs-alb/main.tf:193-213
Conclusion
The Terraform AWS provider offers a powerful and declarative way to manage the entire lifecycle of EC2 compute resources. By combining aws_autoscaling_group, aws_launch_configuration, aws_security_group, and aws_iam_instance_profile, developers can define scalable, secure, and automated compute infrastructure. The example architecture demonstrates how these components integrate to support a containerized application service with ECS, showcasing a realistic, production-like pattern.
Sources: examples/ecs-alb/main.tf, internal/service/ec2/README.md