Capstone: estimate, build, tag and trace the cost of a small project

capstone · 75 min · Task statement 4.2

Task

Run the whole cost life cycle of a small project the way a careful team would. You estimate it in the AWS Pricing Calculator before anything exists, build it from a CloudFormation template so that one command makes it and one command removes it, tag every resource with a project, a cost centre and an environment, and then follow those tags into the billing tools to see exactly where they show up and where they do not yet. The project is three pieces that cost nothing while they sit idle: a private S3 bucket for files, a DynamoDB table for orders, and an SNS topic for alerts. At the end you can explain why a tag on a resource is not yet a cost allocation tag, how CloudFormation spreads one set of tags across a stack, and which tool answers which cost question, and you will leave the account as you found it.

Steps

  1. Open AWS CloudShell. Confirm your identity and the Region, and count the budgets before you start:
aws sts get-caller-identity --query Arn --output text
echo $AWS_REGION
aws budgets describe-budgets --account-id 111122223333 --query 'length(Budgets)'

The ARN should contain assumed-role/AWSReservedSSO_ or :user/. If it ends in :root, sign out now: this lab must not run as the root user. Write down the number of budgets. It must be the same at the end. 2. Estimate first. Open the AWS Pricing Calculator at calculator.aws and start a new estimate named clf-lab24. Add Amazon S3 with 1 GB of S3 Standard storage and a few thousand requests, Amazon DynamoDB in on-demand mode with 1 GB of storage and a few thousand reads and writes, and Amazon SNS with a few thousand notifications, all in the Region CloudShell printed. Write down the monthly total and which service makes up most of it. Leave the estimate unsaved and unshared: a shared estimate link can be opened by anyone who has it. 3. Write the template. It describes the three resources and nothing else. The bucket name ends in your account ID, which CloudFormation fills in, so it is globally unique, and Block Public Access is on for all four settings. Paste this into CloudShell as one block:

cat > clf-lab24.yaml <<'EOF'
AWSTemplateFormatVersion: "2010-09-09"
Description: Lesson 24 capstone, a small tagged project
Resources:
  ProjectBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub "clf-lab24-data-${AWS::AccountId}"
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
  ProjectTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: clf-lab24-orders
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: orderId
          AttributeType: S
      KeySchema:
        - AttributeName: orderId
          KeyType: HASH
  ProjectTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: clf-lab24-alerts
EOF

Check the file with cat clf-lab24.yaml and read it through before you build anything from it. 4. Build the stack, tagging it with three user-defined tags. CloudFormation passes stack tags on to every resource in the stack that supports tags:

aws cloudformation deploy --stack-name clf-lab24-capstone --template-file clf-lab24.yaml --tags Project=clf-lab24 CostCentre=training Environment=lab
aws cloudformation describe-stack-resources --stack-name clf-lab24-capstone --query 'StackResources[].[LogicalResourceId,ResourceStatus]' --output table

The deploy waits until the stack is built, usually a minute or two. The table should list three resources, each CREATE_COMPLETE. 5. Give the project a little invented data. Write a sample order to the table and a small text file to the bucket:

aws dynamodb put-item --table-name clf-lab24-orders --item '{"orderId": {"S": "sample-001"}, "note": {"S": "invented test order"}}'
echo "invented sample export for lesson 24" > sample.txt
aws s3 cp sample.txt s3://clf-lab24-data-111122223333/sample.txt
  1. Read the tags back from each resource:
aws s3api get-bucket-tagging --bucket clf-lab24-data-111122223333 --output table
aws dynamodb list-tags-of-resource --resource-arn arn:aws:dynamodb:$AWS_REGION:111122223333:table/clf-lab24-orders --output table
aws sns list-tags-for-resource --resource-arn arn:aws:sns:$AWS_REGION:111122223333:clf-lab24-alerts --output table

Each resource carries Project, CostCentre and Environment, from the one --tags option. The bucket also carries tags whose keys begin aws:cloudformation:. You did not write those: AWS applied them, and like every key beginning aws: they cannot be edited. That is the difference between the tags you define and the tags AWS applies, which this lesson describes. 7. Follow the tags into billing. In Billing and Cost Management, open Cost allocation tags and search the User-defined cost allocation tags tab for Project. AWS says a new tag key can take up to 24 hours to appear here, so it will probably be missing. Then open Cost Explorer, open the Group by list and pick Tag: Project is not offered, because only activated tags are. This is the lesson's key point. Your resources are tagged, but no cost can be split by Project until the tag is activated, and costs from before that point carry it only if you request a backfill. Leave the tag inactive; the Notes explain why. Finally open Data Exports and read where a Cost and Usage Report would be delivered to an S3 bucket, with activated tags as columns. 8. Compare the estimate with reality. In Cost Explorer, group by Service for this month. Your three resources have existed for minutes and Cost Explorer refreshes about once a day, so they add nothing visible yet; the Pricing Calculator figure was for a whole month of the usage you typed in. If your account is a management account, group by Linked account to see how consolidated billing still shows each account's share. Then open Budgets and read lesson 1's budget: this is the alert that would catch the project if it started to cost money. Change nothing in it.

Verify

Run these while the stack still exists.

aws cloudformation describe-stacks --stack-name clf-lab24-capstone --query 'Stacks[0].StackStatus' --output text

Expected output: CREATE_COMPLETE.

aws s3api get-bucket-tagging --bucket clf-lab24-data-111122223333 --query "TagSet[?Key=='Project'].Value" --output text

Expected output: clf-lab24.

aws dynamodb list-tags-of-resource --resource-arn arn:aws:dynamodb:$AWS_REGION:111122223333:table/clf-lab24-orders --query "Tags[?Key=='CostCentre'].Value" --output text

Expected output: training.

aws s3api get-public-access-block --bucket clf-lab24-data-111122223333 --query 'PublicAccessBlockConfiguration.BlockPublicPolicy'

Expected output: true.

aws budgets describe-budgets --account-id 111122223333 --query 'length(Budgets)'

Expected output: the same number you wrote down in step 1.

Cost and clean-up

An empty S3 bucket, an on-demand DynamoDB table with one item and an SNS topic that sends nothing cost nothing, or very close to it, for the hour this lab takes. Charges are possible if they stay in place for weeks or if you store far more than the lab asks. The Pricing Calculator, Cost Explorer in the console and the cost allocation tags page carry no charge to view. Check each service's pricing page for the current terms.

Created by this lab: the CloudFormation stack clf-lab24-capstone; the S3 bucket clf-lab24-data-111122223333, made by the stack; the object sample.txt in that bucket; the DynamoDB table clf-lab24-orders, made by the stack, with one sample item; the SNS topic clf-lab24-alerts, made by the stack; the files clf-lab24.yaml and sample.txt in your CloudShell home directory; an unsaved estimate in the public AWS Pricing Calculator, which lives only in your browser tab.

  1. Empty the bucket first. CloudFormation cannot delete a bucket that still holds objects:
aws s3 rm s3://clf-lab24-data-111122223333/sample.txt
  1. Delete the stack, and wait until it is gone. Deleting clf-lab24-capstone deletes the bucket clf-lab24-data-111122223333, the table clf-lab24-orders with its sample item, and the topic clf-lab24-alerts, which is the clean removal lesson 12 describes:
aws cloudformation delete-stack --stack-name clf-lab24-capstone
aws cloudformation wait stack-delete-complete --stack-name clf-lab24-capstone

If the wait reports that the stack reached DELETE_FAILED, the bucket still holds an object: repeat step 1 of the clean-up, then run both commands again. 3. Delete the local files clf-lab24.yaml and sample.txt from CloudShell, whose home directory keeps them between sessions:

rm clf-lab24.yaml sample.txt
  1. Close the Pricing Calculator tab. The estimate was never saved or shared, so it is gone with the tab. If you exported it, delete the downloaded file.
  2. Keep lesson 1's budget: every later lab relies on it, and this capstone never changed it. The Project tag was never activated, so there is no billing setting to undo.

Check it is gone

aws cloudformation list-stacks --stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE ROLLBACK_COMPLETE DELETE_FAILED --query "length(StackSummaries[?StackName=='clf-lab24-capstone'])"

Expected output: 0.

aws s3api list-buckets --query "length(Buckets[?Name=='clf-lab24-data-111122223333'])"

Expected output: 0.

aws dynamodb list-tables --query "length(TableNames[?@=='clf-lab24-orders'])"

Expected output: 0.

aws sns list-topics --query "length(Topics[?ends_with(TopicArn, ':clf-lab24-alerts')])"

Expected output: 0.

aws budgets describe-budgets --account-id 111122223333 --query 'length(Budgets)'

Expected output: the same number you wrote down in step 1.

Notes

Why the tag stays inactive. Activating a cost allocation tag is free and can be undone, but it is an account-wide billing setting, a new tag key can take up to a day to become available to activate, and activation applies to costs from that point on unless you request a backfill. In a lab that lasts an hour the result would not show up before the resources were deleted. In a real project you would activate Project once, in the management account, and leave it on. Why there is no project budget. A real project would usually get its own cost budget, filtered to the tag Project = clf-lab24. This course keeps exactly one budget, lesson 1's, so that nobody confuses two near-identical budgets and removes the one every lab relies on. Why there is no Cost and Usage Report. A CUR keeps writing files to an S3 bucket every day until it is turned off, which does not suit a lab. Reading the Data Exports page shows where it would be set up.

This is an independent study companion for the AWS Certified Cloud Practitioner (CLF-C02) exam and is not produced by or endorsed by Amazon Web Services. AWS, Amazon Web Services and AWS Certified Cloud Practitioner are trademarks of Amazon.com, Inc. or its affiliates.

This is an independent study companion for AWS Certified Cloud Practitioner CLF-C02 and is not produced by or endorsed by CompTIA.