Terraform资源发现导入及AWS未清理实例自动清理方案咨询
Great questions! Let’s tackle them one by one to get you sorted out.
Absolutely, Terraform supports importing existing AWS resources into its state, though it doesn’t have a built-in "discover all resources" command—you’ll need to target specific resources manually. Here’s how it works:
Import a single resource: Use the
terraform importcommand, specifying the resource address from your config and the AWS resource ID. For an EC2 instance, that looks like:terraform import aws_instance.my_app_instance i-1234567890abcdef0Important: After importing, you must add a matching resource block to your Terraform configuration. Without this, Terraform will flag the imported resource as "unmanaged" and try to destroy it on your next
terraform plan.Check managed resources: To see which resources Terraform already tracks, use
terraform state listto get a list of resource addresses, orterraform state show <resource-address>to view details for a specific one. This helps you cross-reference which existing AWS resources aren’t yet in your Terraform state.
It’s frustrating when terraform destroy leaves instances hanging—here’s a workflow to automate cleanup using Terraform and cron, without relying on external tools beyond what you’re already using:
Core Idea
We’ll use Terraform data sources to fetch all running EC2 instances, compare that list against the ones Terraform manages (via its state), then terminate any unmanaged "stuck" instances. You can choose between two approaches: using AWS CLI for simplicity, or a pure Terraform flow (import + destroy) if you want to stick strictly to Terraform commands.
Step 1: Create a Cleanup Script
Here’s a bash script that handles the heavy lifting. Adjust the tag filters or AWS region as needed for your environment:
#!/bin/bash set -euo pipefail # -------------------------- # Configuration # -------------------------- # Optional: Filter instances by tag (e.g., only cleanup instances tagged Environment=dev) TAG_FILTER="Environment=dev" AWS_REGION="us-east-1" # -------------------------- # Get Terraform-managed instance IDs # -------------------------- MANAGED_INSTANCES=$(terraform state list | grep aws_instance | while read -r RESOURCE; do terraform state show "$RESOURCE" | grep '^id =' | awk '{print $3}' done | sort) # -------------------------- # Fetch all running EC2 instances using Terraform data source # -------------------------- cat > temp_instance_query.tf << EOF provider "aws" { region = "$AWS_REGION" } data "aws_instances" "running" { instance_tags = { $TAG_FILTER } filters { name = "instance-state-name" values = ["running"] } } output "running_ids" { value = data.aws_instances.running.ids } EOF # Initialize and fetch output terraform init > /dev/null RUNNING_INSTANCES=$(terraform output -json running_ids | jq -r '.[]' | sort) # Clean up temporary files rm -f temp_instance_query.tf terraform.tfstate* .terraform.lock.hcl rm -rf .terraform # -------------------------- # Find unmanaged instances # -------------------------- UNMANAGED_INSTANCES=$(comm -23 <(echo "$RUNNING_INSTANCES") <(echo "$MANAGED_INSTANCES")) # -------------------------- # Terminate unmanaged instances # -------------------------- if [ -n "$UNMANAGED_INSTANCES" ]; then echo "$(date): Found unmanaged instances to terminate: $UNMANAGED_INSTANCES" # Option 1: Use AWS CLI (simple, fast) aws ec2 terminate-instances --instance-ids $UNMANAGED_INSTANCES --region $AWS_REGION # Option 2: Pure Terraflow (import + destroy) # for INSTANCE_ID in $UNMANAGED_INSTANCES; do # cat > temp_destroy.tf << EOF # provider "aws" { # region = "$AWS_REGION" # } # resource "aws_instance" "temp_${INSTANCE_ID}" { # # Dummy values - Terraform will overwrite these on import # ami = "ami-0c55b159cbfafe1f0" # instance_type = "t2.micro" # } # EOF # terraform init > /dev/null # terraform import aws_instance.temp_${INSTANCE_ID} $INSTANCE_ID > /dev/null # terraform destroy -target aws_instance.temp_${INSTANCE_ID} -auto-approve > /dev/null # rm -f temp_destroy.tf terraform.tfstate* .terraform.lock.hcl # rm -rf .terraform # done else echo "$(date): No unmanaged running instances found." fi
Step 2: Set Up a Cron Job
To run this script automatically, add a cron entry. For example, to run it daily at 2 AM:
- Make the script executable:
chmod +x /path/to/terraform_cleanup.sh - Edit your crontab:
crontab -e - Add this line (adjust paths and log location as needed):
0 2 * * * /path/to/terraform_cleanup.sh >> /var/log/terraform_cleanup.log 2>&1
Key Notes
- Permissions: Ensure the user running the cron job has:
- Access to your Terraform state (if using remote state like S3, configure AWS credentials or IAM roles appropriately)
- AWS IAM permissions for
ec2:DescribeInstancesandec2:TerminateInstances
- Testing: Always run the script manually first (comment out the termination step) to verify it’s identifying the right instances before enabling auto-termination.
- Tag Filters: Adding tag filters (like
Environment=dev) prevents accidental cleanup of production instances—never skip this if you have multiple environments!
内容的提问来源于stack exchange,提问作者SuperTetelman

