It's always crucial to monitor AWS costs to avoid surprising charges at the end of the month.
There are few great articles on how to use AWS Budgets out there, but I thought to create this post to share how we can automate the creation of budgets alerts via CloudFormation and deploy across multiple AWS accounts.
With the template below, we can not only budget the monthly cost, but also the daily cost.
Description: AWS Budget - daily and monthly alerts
Parameters:
AccountAlias:
Description: AWS account alias
Type: String
Mappings:
awsAccount:
"000000000": # nonprod
BudgetDailyAmount: 22
BudgetMonthlyAmount: 700
Unit: USD
DevTeamEmail: dev@company.com
PlatformTeamEmail: platform@company.com
"111111111": # prod
BudgetDailyAmount: 32
BudgetMonthlyAmount: 1000
Unit: USD
DevTeamEmail: dev@company.com
PlatformTeamEmail: platform@company.com
Resources:
BudgetDaily:
Type: AWS::Budgets::Budget
Properties:
Budget:
BudgetName: !Sub ${AWS::AccountId}-${AccountAlias}-daily
BudgetLimit:
Amount: !FindInMap [awsAccount, !Ref 'AWS::AccountId', BudgetDailyAmount]
Unit: !FindInMap [awsAccount, !Ref 'AWS::AccountId', Unit]
TimeUnit: DAILY
BudgetType: COST
NotificationsWithSubscribers:
- Notification:
NotificationType: ACTUAL
ComparisonOperator: GREATER_THAN
Threshold: 99
Subscribers:
- SubscriptionType: EMAIL
Address: !FindInMap [awsAccount, !Ref 'AWS::AccountId', DevTeamEmail]
- SubscriptionType: EMAIL
Address: !FindInMap [awsAccount, !Ref 'AWS::AccountId', PlatformTeamEmail]
- Notification:
NotificationType: ACTUAL
ComparisonOperator: GREATER_THAN
Threshold: 80
Subscribers:
- SubscriptionType: EMAIL
Address: !FindInMap [awsAccount, !Ref 'AWS::AccountId', DevTeamEmail]
- SubscriptionType: EMAIL
Address: !FindInMap [awsAccount, !Ref 'AWS::AccountId', PlatformTeamEmail]
BudgetMonthly:
Type: AWS::Budgets::Budget
Properties:
Budget:
BudgetName: !Sub ${AWS::AccountId}-${AccountAlias}-monthly
BudgetLimit:
Amount: !FindInMap [awsAccount, !Ref 'AWS::AccountId', BudgetMonthlyAmount]
Unit: !FindInMap [awsAccount, !Ref 'AWS::AccountId', Unit]
TimeUnit: MONTHLY
BudgetType: COST
NotificationsWithSubscribers:
- Notification:
NotificationType: ACTUAL
ComparisonOperator: GREATER_THAN
Threshold: 99
Subscribers:
- SubscriptionType: EMAIL
Address: !FindInMap [awsAccount, !Ref 'AWS::AccountId', DevTeamEmail]
- SubscriptionType: EMAIL
Address: !FindInMap [awsAccount, !Ref 'AWS::AccountId', PlatformTeamEmail]
- Notification:
NotificationType: ACTUAL
ComparisonOperator: GREATER_THAN
Threshold: 80
Subscribers:
- SubscriptionType: EMAIL
Address: !FindInMap [awsAccount, !Ref 'AWS::AccountId', DevTeamEmail]
- SubscriptionType: EMAIL
Address: !FindInMap [awsAccount, !Ref 'AWS::AccountId', PlatformTeamEmail]
This template creates two alerts: one for daily cost and another for monthly cost. Before deploying the template, we need to replace account IDs and email addresses in the "Mappings".
I used the script below to deploy the stack:
export AWS_REGION="us-east-1"
export AWS_ACCOUNT_ALIAS=$(aws iam list-account-aliases --query 'AccountAliases' --output text)
aws cloudformation deploy --stack-name budgets-alerts \
--parameter-overrides AccountAlias=$AWS_ACCOUNT_ALIAS \
--template-file budgets.yaml --region $AWS_REGION --capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
I hope this help you to keep track of your AWS costs and avoid surprises.
Top comments (1)
Nice