Constantly monitoring AWS costs
Tags: cloud, aws, cloudformation, costmanagement
Published: 2022-09-28 05:46:13

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.

```yaml
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:

```bash
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
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2eduzkeul7wjefo4e44q.png)

I hope this help you to keep track of your AWS costs and avoid surprises.