Cost Optimization Strategies with Terraform on AWS
Learn how to implement cost optimization strategies for your AWS infrastructure using Terraform, including resource management, tagging, and budgeting
Cost Optimization Strategies with Terraform on AWS
Cost optimization is crucial for maintaining efficient cloud infrastructure. This guide demonstrates how to implement cost optimization strategies using Terraform on AWS.
Video Tutorial
Learn more about Cost Optimization with Terraform in AWS in this comprehensive video tutorial:
Prerequisites
- AWS CLI configured with appropriate permissions
- Terraform installed (version 1.0.0 or later)
- Basic understanding of AWS pricing
- Access to AWS Cost Explorer
Project Structure
terraform-cost/
├── main.tf
├── variables.tf
├── outputs.tf
├── modules/
│ └── cost/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── policies/
└── budget.json
Cost Management Configuration
Create modules/cost/main.tf:
# AWS Budgets
resource "aws_budgets_budget" "monthly" {
name = "${var.project_name}-monthly-budget"
budget_type = "COST"
limit_amount = var.monthly_budget_amount
limit_unit = "USD"
time_period_start = "2025-01-01_00:00"
time_unit = "MONTHLY"
notification {
comparison_operator = "GREATER_THAN"
threshold = 80
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_email_addresses = var.notification_emails
}
notification {
comparison_operator = "GREATER_THAN"
threshold = 100
threshold_type = "PERCENTAGE"
notification_type = "FORECASTED"
subscriber_email_addresses = var.notification_emails
}
cost_filters = {
TagKeyValue = "user:Environment$${var.environment}"
}
}
# Cost and Usage Report
resource "aws_cur_report_definition" "main" {
report_name = "${var.project_name}-cost-report"
time_unit = "HOURLY"
format = "Parquet"
compression = "Parquet"
additional_schema_elements = ["RESOURCES"]
s3_bucket = aws_s3_bucket.cost_reports.id
s3_region = data.aws_region.current.name
additional_artifacts = ["ATHENA"]
report_versioning = "OVERWRITE_REPORT"
}
# S3 Bucket for Cost Reports
resource "aws_s3_bucket" "cost_reports" {
bucket = "${var.project_name}-cost-reports-${data.aws_caller_identity.current.account_id}"
tags = merge(
var.tags,
{
Name = "${var.project_name}-cost-reports"
}
)
}
# S3 Lifecycle Rules
resource "aws_s3_bucket_lifecycle_configuration" "cost_reports" {
bucket = aws_s3_bucket.cost_reports.id
rule {
id = "archive-old-reports"
status = "Enabled"
transition {
days = 90
storage_class = "GLACIER"
}
expiration {
days = 365
}
}
}
# Cost Allocation Tags
resource "aws_ce_tags" "main" {
tags = [
"Environment",
"Project",
"Owner",
"CostCenter"
]
}
# Cost Category
resource "aws_ce_cost_category" "environment" {
name = "Environment"
rule_version = "CostCategoryExpression.v1"
rules {
value = "Production"
rule {
tags {
key = "Environment"
values = ["prod"]
}
}
}
rules {
value = "Development"
rule {
tags {
key = "Environment"
values = ["dev"]
}
}
}
}
# Cost Anomaly Detection
resource "aws_ce_anomaly_monitor" "main" {
name = "${var.project_name}-anomaly-monitor"
monitor_type = "DIMENSIONAL"
monitor_dimension = "SERVICE"
}
resource "aws_ce_anomaly_subscription" "main" {
name = "${var.project_name}-anomaly-subscription"
threshold = 100
frequency = "DAILY"
monitor_arn_list = [
aws_ce_anomaly_monitor.main.arn
]
subscriber {
type = "EMAIL"
address = var.cost_admin_email
}
}
Cost Optimization Strategies
- Resource Rightsizing
resource "aws_instance" "optimized" {
instance_type = var.environment == "prod" ? "t3.medium" : "t3.micro"
credit_specification {
cpu_credits = "unlimited"
}
metadata_options {
http_endpoint = "enabled"
http_tokens = "required"
}
root_block_device {
volume_size = var.environment == "prod" ? 100 : 30
volume_type = "gp3"
}
}
- Auto Scaling
resource "aws_autoscaling_group" "cost_optimized" {
mixed_instances_policy {
instances_distribution {
on_demand_base_capacity = 1
on_demand_percentage_above_base_capacity = 25
spot_allocation_strategy = "capacity-optimized"
}
launch_template {
launch_template_specification {
launch_template_id = aws_launch_template.main.id
version = "$Latest"
}
override {
instance_type = "t3.micro"
weighted_capacity = "1"
}
override {
instance_type = "t3.small"
weighted_capacity = "2"
}
}
}
}
- Storage Optimization
resource "aws_s3_bucket_lifecycle_configuration" "main" {
bucket = aws_s3_bucket.main.id
rule {
id = "transition-to-ia"
status = "Enabled"
transition {
days = 30
storage_class = "STANDARD_IA"
}
transition {
days = 90
storage_class = "GLACIER"
}
expiration {
days = 365
}
}
}
Cost Monitoring
- Budget Alerts
resource "aws_budgets_budget" "service" {
name = "${var.project_name}-service-budget"
budget_type = "COST"
limit_amount = var.service_budget_amount
limit_unit = "USD"
time_unit = "MONTHLY"
cost_filter {
name = "Service"
values = [
"Amazon Elastic Compute Cloud - Compute",
"Amazon Simple Storage Service"
]
}
notification {
comparison_operator = "GREATER_THAN"
threshold = 90
threshold_type = "PERCENTAGE"
notification_type = "FORECASTED"
subscriber_email_addresses = var.notification_emails
}
}
- Cost Explorer
resource "aws_ce_cost_category" "team" {
name = "Team"
rule_version = "CostCategoryExpression.v1"
rules {
value = "Frontend"
rule {
tags {
key = "Team"
values = ["frontend"]
}
}
}
rules {
value = "Backend"
rule {
tags {
key = "Team"
values = ["backend"]
}
}
}
}
Resource Scheduling
- EC2 Scheduling
resource "aws_autoscaling_schedule" "scale_down" {
scheduled_action_name = "scale-down"
min_size = 0
max_size = 0
desired_capacity = 0
recurrence = "0 20 * * 1-5"
autoscaling_group_name = aws_autoscaling_group.main.name
}
resource "aws_autoscaling_schedule" "scale_up" {
scheduled_action_name = "scale-up"
min_size = 1
max_size = 4
desired_capacity = 2
recurrence = "0 8 * * 1-5"
autoscaling_group_name = aws_autoscaling_group.main.name
}
- RDS Scheduling
resource "aws_rds_cluster" "dev" {
cluster_identifier = "${var.project_name}-dev"
engine = "aurora-postgresql"
engine_mode = "serverless"
scaling_configuration {
auto_pause = true
max_capacity = 4
min_capacity = 2
seconds_until_auto_pause = 300
}
}
Reserved Instances and Savings Plans
- Reserved Instance Planning
resource "aws_ec2_capacity_reservation" "main" {
instance_type = "t3.medium"
instance_platform = "Linux/UNIX"
availability_zone = "us-west-2a"
instance_count = 5
end_date_type = "unlimited"
end_date = "2026-01-19T00:00:00Z"
instance_match_criteria = "targeted"
}
- Savings Plans Utilization
resource "aws_cloudwatch_metric_alarm" "savings_plan" {
alarm_name = "${var.project_name}-savings-plan-coverage"
comparison_operator = "LessThanThreshold"
evaluation_periods = "1"
metric_name = "SavingsPlanCoverage"
namespace = "AWS/SavingsPlans"
period = "86400"
statistic = "Average"
threshold = 80
alarm_description = "Alert when Savings Plan coverage drops below 80%"
alarm_actions = [aws_sns_topic.cost_alerts.arn]
}
Cost Analysis and Reporting
- Athena Integration
resource "aws_athena_workgroup" "cost_analysis" {
name = "${var.project_name}-cost-analysis"
configuration {
enforce_workgroup_configuration = true
publish_cloudwatch_metrics_enabled = true
result_configuration {
output_location = "s3://${aws_s3_bucket.cost_reports.id}/athena-results/"
}
}
}
- QuickSight Dashboard
resource "aws_quicksight_data_source" "cost" {
name = "${var.project_name}-cost-analysis"
aws_account_id = data.aws_caller_identity.current.account_id
type = "ATHENA"
data_source_id = "${var.project_name}-cost-analysis"
parameters {
athena {
work_group = aws_athena_workgroup.cost_analysis.id
}
}
}
Best Practices
-
Tagging Strategy
- Implement mandatory tags
- Use cost allocation tags
- Track resources by project
- Monitor tag compliance
-
Resource Management
- Right-size resources
- Use auto scaling
- Implement scheduling
- Clean up unused resources
-
Storage Optimization
- Use lifecycle policies
- Implement tiered storage
- Delete unnecessary data
- Compress data when possible
-
Cost Monitoring
- Set up budgets
- Configure alerts
- Track anomalies
- Regular cost reviews
Conclusion
You’ve learned how to implement cost optimization strategies using Terraform in AWS. This setup provides:
- Cost monitoring and alerting
- Resource optimization
- Budget management
- Cost analysis capabilities
Remember to:
- Monitor costs regularly
- Review resource utilization
- Optimize resource sizing
- Implement cost controls