Cost Explorer and Analysis
Cost Explorer and Cost Analysis
Cost Explorer
# Get current month costs
aws ce get-cost-and-usage \
--time-period Start=2024-01-01,End=2024-01-31 \
--granularity MONTHLY \
--metrics UnblendedCost
# Group by service
aws ce get-cost-and-usage \
--time-period Start=2024-01-01,End=2024-01-31 \
--granularity MONTHLY \
--metrics UnblendedCost \
--group-by Type=DIMENSION,Key=SERVICE
# Filter by specific service
aws ce get-cost-and-usage \
--time-period Start=2024-01-01,End=2024-01-31 \
--granularity MONTHLY \
--metrics UnblendedCost \
--filter '{"Dimensions":{"Key":"SERVICE","Values":["Amazon Elastic Compute Cloud - Compute"]}}'
# Group by tag
aws ce get-cost-and-usage \
--time-period Start=2024-01-01,End=2024-01-31 \
--granularity MONTHLY \
--metrics UnblendedCost \
--group-by Type=TAG,Key=Environment
Cost and Usage Report
# Create Cost and Usage Report
aws cur put-report-definition \
--report-definition '{
"ReportName": "my-cost-report",
"TimeUnit": "DAILY",
"Format": "textORcsv",
"Compression": "ZIP",
"S3BucketName": "my-cost-reports",
"S3Prefix": "reports",
"S3Region": "us-east-1",
"AdditionalArtifacts": ["REDSHIFT", "QUICKSIGHT"],
"AdditionalSchemaElements": ["RESOURCES"]
}'
Resource Tagging Strategy
Resource Tagging Strategy
Tagging Best Practices
# Tag all resources
aws ec2 create-tags \
--resources i-xxx \
--tags \
Key=Environment,Value=Production \
Key=Project,Value=MyApp \
Key=Team,Value=Engineering \
Key=CostCenter,Value=12345
# List resources by tag
aws ec2 describe-instances \
--filters "Name=tag:Environment,Values=Production" \
--query 'Reservations[*].Instances[*].[InstanceId,Tags[?Key==`Name`].Value|[0]]'
Required Tags
| Tag | Purpose | Example |
|---|---|---|
| Environment | Identify environment | prod, staging, dev |
| Project | Project name | my-app |
| Team | Owning team | engineering |
| CostCenter | Cost allocation | 12345 |
| Owner | Contact person | john@example.com |
Tag Policies (Organizations)
# Create tag policy
aws organizations create-policy \
--content '{
"Version": "2012-10-17",
"Statement": [{
"Sid": "RequireEnvironmentTag",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:RequestTag/Environment": ["prod", "staging", "dev"]
}
}
}]
}' \
--type TAG_POLICY \
--name "Require Environment Tag"
Rightsizing and Optimization
Rightsizing and Optimization
AWS Compute Optimizer
# Enable Compute Optimizer
aws compute-optimizer update-enrollment-status --status Active
# Get EC2 recommendations
aws compute-optimizer get-ec2-instance-recommendations
# Get Lambda recommendations
aws compute-optimizer get-lambda-function-recommendations
# Get EBS volume recommendations
aws compute-optimizer get-ebs-volume-recommendations
EC2 Rightsizing
# Find underutilized instances
aws ce get-cost-and-usage \
--time-period Start=2024-01-01,End=2024-01-31 \
--granularity MONTHLY \
--metrics UnblendedCost \
--filter '{"Dimensions":{"Key":"SERVICE","Values":["Amazon Elastic Compute Cloud - Compute"]}}' \
--group-by Type=TAG,Key=InstanceType
# Stop unused instances
aws ec2 describe-instances \
--filters "Name=instance-state-name,Values=running" \
--query 'Reservations[*].Instances[*].[InstanceId,InstanceType,CpuOptions,MemoryGiBOfMemory]'
Savings Plans
# Get Savings Plans recommendations
aws ce get-savings-plans-recommendations \
--account-id 123456789012 \
--term-in-years ONE_YEAR \
--lookback-period-in-days SIXTY_DAYS
# Purchase Savings Plan
aws savingsplans purchase-savings-plan \
--savings-plan-offering-id xxx \
--purchase-commitment-amount 10.0 \
--client-token $(uuidgen)
# Describe your Savings Plans
aws savingsplans describe-savings-plans
Budgets and Alerts
Budgets and Alerts
Create Budget
# Create a cost budget
aws budgets create-budget \
--account-id 123456789012 \
--budget '{
"BudgetName": "Monthly-100",
"BudgetLimit": {
"Amount": "100",
"Unit": "USD"
},
"TimeUnit": "MONTHLY",
"BudgetType": "COST",
"CostFilters": {
"TagKeyValue": ["user:Environment$Production"]
}
}' \
--notifications-with-subscribers '[{
"Notification": {
"NotificationType": "ACTUAL",
"ComparisonOperator": "GREATER_THAN",
"Threshold": 80,
"ThresholdType": "PERCENTAGE"
},
"Subscribers": [{
"SubscriptionType": "EMAIL",
"Address": "admin@example.com"
}]
}]
Budget Types
| Type | Description |
|---|---|
| Cost | Track total costs |
| Usage | Track resource usage |
| Reservation | Track RI utilization |
| Savings Plans | Track SP utilization |
Budget Notifications
# Add SNS notification
aws budgets create-budget \
--account-id 123456789012 \
--budget '{...}' \
--notifications-with-subscribers '[{
"Notification": {
"NotificationType": "FORECASTED",
"ComparisonOperator": "GREATER_THAN",
"Threshold": 90
},
"Subscribers": [{
"SubscriptionType": "SNS",
"Address": "arn:aws:sns:us-east-1:xxx:cost-alerts"
}]
}'
Cost Optimization Checklist
Cost Optimization Checklist
Quick Wins
- Terminate unused resources (old EBS volumes, unused ENIs)
- Right-size instances based on CloudWatch metrics
- Use Spot Instances for fault-tolerant workloads
- Purchase Reserved Instances for steady-state workloads
- Enable S3 Intelligent-Tiering for unpredictable access
- Delete unattached Elastic IPs
- Use gp3 instead of gp2 EBS volumes
Long-Term Strategy
┌─────────────────────────────────────────────────────────────┐
│ Cost Optimization Framework │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. Measure: Cost Explorer, CUR, Tagging │
│ 2. Analyze: Identify waste, rightsizing opportunities │
│ 3. Optimize: RI, Savings Plans, Spot, Right-sizing │
│ 4. Monitor: Budgets, Alarms, Dashboards │
│ 5. Automate: Lambda cleanup, Auto Scaling │
│ │
└─────────────────────────────────────────────────────────────┘
Cost by Service
# Get cost breakdown by service
aws ce get-cost-and-usage \
--time-period Start=2024-01-01,End=2024-01-31 \
--granularity MONTHLY \
--metrics UnblendedCost \
--group-by Type=DIMENSION,Key=SERVICE \
--sort-by Key=UnblendedCost,SortOrder=DESCENDING
Cost Optimization Automation
import boto3
import datetime
# Stop non-production instances outside business hours
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
hour = datetime.datetime.now().hour
if hour < 8 or hour > 20: # Before 8am or after 8pm
instances = ec2.describe_instances(
Filters=[{'Name': 'tag:Environment', 'Values': ['dev']}]
)
instance_ids = []
for r in instances['Reservations']:
for i in r['Instances']:
if i['State']['Name'] == 'running':
instance_ids.append(i['InstanceId'])
if instance_ids:
ec2.stop_instances(InstanceIds=instance_ids)
print(f'Stopped {len(instance_ids)} instances')