As cloud budgets continue to grow as the #2 line item behind salaries for many companies, cloud practitioners are becoming more attuned to the FinOps imperative — the need to optimize cloud costs, budgets, and cost allocation. In addition, most major organizations employ multiple cloud service providers, oftentimes having to manually manage and configure numerous cost reports and dashboards.
Enter FinOps as Code, offering a solution to streamline manual cloud cost management efforts. Like its close cousin, Infrastructure as Code (IaC), FinOps as Code empowers FinOps practitioners to automate practices, maintain consistency, and promote collaboration among teams.
The FinOps as Code Toolkit: Terraform
Terraform is an open-source IaC tool, developed by HashiCorp, that automates provisioning and managing your resources in a version-controlled manner. With Terraform, infrastructure definitions are written as code, typically using HashiCorp Configuration Language, or HCL. The benefit of using an IaC tool, like Terraform, is that it enables version control, code reuse, and collaboration — just like traditional software development. When applied to FinOps, you can use Terraform for practices like cost allocation via automated resource tagging as well as creating numerous reports and dashboards.
This blog walks through several FinOps use cases, showcasing how Terraform and other FinOps as Code tools can automate and optimize cloud financial operations. We’ll provide code samples and recommendations for how to get up and running with your FinOps as Code practice.
Adopt FinOps Principles for Better Cloud Cost Management
The FinOps Foundation maintains a set of FinOps Principles that “guide the activities of [the] FinOps practice.” Integrating the FinOps as Code approach along with these principles not only helps your organization develop a culture of cloud cost mindfulness — it also drives greater efficiency and removes the mundane and manual burden of pointing and clicking through the setup of numerous reports and filters. Considering a few of these principles, we’ll dive deeper and discover the power of automation combined with FinOps as Code.
Principle 1: Personal Ownership of Cloud Usage
The Personal ownership of cloud usage FinOps Principle seeks to empower teams to manage their individual cloud cost usage against a designated budget. You can include a Terraform resource within your infrastructure to create a budget, as well as a notification of any budget anomalies that helps the team to immediately recognize when they are nearing budget thresholds.
In the following example, a hypothetical Marketing team uses Amazon Simple Storage Service (S3) to store website media and promotional graphics. They also use EC2 as the compute solution for some marketing analytics systems. They want to set up a monthly budget of $1000 that also alerts the team when they reach a 90% threshold of that budget. Using the aws_budgets_budget
Terraform resource, the team can easily configure this budget and ensure they are immediately made aware of approaching that limit.
First, define the aws_budgets_budget
resource. Define the limit_amount
and time_unit
arguments to fit the determined needs.
resource "aws_budgets_budget" "marketing_s3_ec2" {
name = "budget-s3-ec2-monthly-marketing"
budget_type = "COST"
limit_amount = "1000"
limit_unit = "USD"
time_period_end = "2023-12-31_00:00"
time_period_start = "2023-01-01_00:00"
time_unit = "MONTHLY"
# ...
Add the S3 and EC2 cost_filter
argument.
resource "aws_budgets_budget" "marketing_s3_ec2" {
# ...
cost_filter {
name = "Service"
values = [
"Amazon Simple Storage Service",
"Amazon Elastic Compute Cloud - Compute",
]
}
# ...
The FinOps Principles also stress that organizations need to “[c]reate, monitor, and improve real-time financial forecasting and planning.” In the spirit of timely reporting, you can add the notification
argument to send alerts via Amazon Simple Notification Service (SNS).
resource "aws_budgets_budget" "marketing_s3_ec2" {
# ...
notification {
comparison_operator = "GREATER_THAN"
threshold = 90
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_sns_topic_arns = ["arn:aws:sns:us-east-1:123456789012:BudgetAlert"]
}
}
In the above example, we pass the Amazon Resource Name (ARN) for an already created SNS topic; however, to automate things further, you can use the power of Terraform data sources to dynamically access an ARN that you can then use as a variable within the above configuration.
Principle 2: Accessible and Timely Reports
The Accessible and timely reports FinOps Principle stresses the importance of processing and sharing cost data as soon as it is available. These examples support how convenient and streamlined it is to integrate automation into your FinOps workflow while addressing some FinOps Principles. However, in reality, many organizations are multi-cloud consumers and also work with a number of other cloud service providers. As a result, setting up cost reporting to cover all cloud spend is daunting.
Automate Reporting with Terraform and Vantage
In the following example, we’ll use the Vantage Terraform provider (which uses our Write API and VQL) to demo a simplified workflow and architecture for a Marketing department that uses AWS and Snowflake. We’ll use Terraform to create a cloud cost management infrastructure that monitors costs for the Marketing team.
All demo files are also included in the FinOps as Code demo repo.
Step 1: Set Up Terraform Directory Structure
For this tutorial, we will use the below directory structure. /vantage_modules
will contain all the Terraform resources that we’ll call from each module. The root main.tf
will contain the modules we create — one for our Snowflake reporting infrastructure and one for our AWS reporting infrastructure.
terraform-marketing-costs/
├── main.tf
├── variables.tf
├── vantage_modules/
│ ├── main.tf
│ ├── variables.tf
│ ├── outputs.tf
The goal of this walkthrough will be to create a final dashboard that shows the Marketing team’s Snowflake and AWS costs from the past six months, grouped by month.
Step 2: Create Terraform Variable for Workspace ID
Note: Before you use the Vantage Terraform provider, you will need a Vantage API token. You can store your API credentials as an environment variable with
export VANTAGE_API_TOKEN=an-api-token
.
First, we’ll obtain the Marketing workspace token from the /workspaces
Vantage API endpoint. We’ll store this token as a variable within the variables.tf
file, in the root of our directory.
# variables.tf
variable "marketing_workspace_token" {
description = "Value of Marketing workspace token"
type = string
default = "wrkspc_12345"
}
Step 3: Define Terraform Resources, Variables, and Outputs
Next, we’ll create a set of Vantage resources in /vantage_modules/main.tf
.
We’ll use this file as the source
when we create our modules. We can then reuse this set of resources across both the AWS and Snowflake modules.
These resources will create a folder, a saved filter, and a Cost Report that uses the saved filter within the Vantage console.
The filter
argument of the vantage_saved_filter
resource uses Vantage Query Language — or VQL — which is a SQL-like language for creating filters. Once created, the Snowflake filter will look like the below image. The AWS filter will look similar, specifying the AWS provider.
In this scenario, the value for costs.provider
is stored as a variable (var.service
), which will be referenced when constructing the modules. These values will be set to aws
and snowflake
in their respective modules.
# /vantage_modules/main.tf
terraform {
required_providers {
vantage = {
source = "vantage-sh/vantage"
}
}
}
resource "vantage_folder" "folder" {
title = var.folder_title
workspace_token = var.workspace_token
}
resource "vantage_saved_filter" "filter" {
title = "${var.folder_title} Filter"
filter = <<FILTER
(costs.provider = '${var.service}'
AND tags.name = '${var.tag_name}'
AND tags.value = '${var.tag_value}')
FILTER
workspace_token = var.workspace_token
}
resource "vantage_cost_report" "report" {
title = "${var.folder_title} Report"
folder_token = vantage_folder.folder.token
saved_filter_tokens = [vantage_saved_filter.filter.token]
workspace_token = var.workspace_token
}
Observe the use of variables throughout this configuration (for example, var.tag_value
). These variables should be stored in the /vantage_modules/variables.tf
file, depicted below.
# /vantage_modules/variables.tf
variable "folder_title" {
description = "The title of the folder"
type = string
}
variable "workspace_token" {
description = "The workspace token"
type = string
}
variable "service" {
description = "The cloud service provider"
type = string
}
variable "tag_name" {
description = "The tag name"
type = string
}
variable "tag_value" {
description = "The tag value"
type = string
}
In addition, the report ID, or token
, that is output from the vantage_saved_filter
resource needs to be saved to /vantage_modules/outputs.tf
. We’ll use this token
when creating a Cost Report in the vantage_cost_report
resource. To create a dashboard that displays a Snowflake and an AWS report, we’ll also need to create outputs to obtain the generated token
for both Costs Reports.
# /vantage_modules/outputs.tf
output "created_saved_filter" {
value = vantage_saved_filter.filter.token
}
output "marketing_aws_cost_report_token" {
value = vantage_cost_report.report.token
}
output "marketing_snowflake_cost_report_token" {
value = vantage_cost_report.report.token
}
Once created, the Cost Report will look like the below image. One report will be created for Snowflake costs, and one report will be created for AWS costs.
Step 4: Configure the Root main.tf
and Dashboard Terraform Resource
Finally, we’ll configure the root main.tf
file, which includes both the marketing_aws
and marketing_snowflake
modules as well as their associated configurations.
Here we will define the arguments specific to each module. For example, the values for the tag_name
and tag_value
are used in the vantage_saved_filter
resource we defined earlier. A best-practice cloud cost strategy includes resource tagging. In this scenario, the Marketing team’s cost allocation strategy includes adding cost_center
AWS tags and Snowflake metadata to the resources they use.
# main.tf
terraform {
required_providers {
vantage = {
source = "vantage-sh/vantage"
}
}
}
module "marketing_aws" {
source = "./vantage_modules"
folder_title = "Marketing AWS Costs"
workspace_token = var.marketing_workspace_token
service = "aws"
tag_name = "cost_center"
tag_value = "marketing"
}
module "marketing_snowflake" {
source = "./vantage_modules"
folder_title = "Marketing Snowflake Costs"
workspace_token = var.marketing_workspace_token
service = "snowflake"
tag_name = "cost_center"
tag_value = "marketing"
}
To bring everything together, we’ll create a single dashboard that contains the AWS and Marketing Cost Reports. This dashboard shows costs over the past six months, grouped by month.
# main.tf
# ...
resource "vantage_dashboard" "dashboard" {
widget_tokens = [
module.marketing_aws.marketing_aws_cost_report_token,
module.marketing_snowflake.marketing_snowflake_cost_report_token
]
title = "Marketing Dashboard"
date_interval = "last_6_months"
date_bin = "month"
workspace_token = var.marketing_workspace_token
}
After running terraform plan
and terraform apply
, we now have a fully functioning dashboard that shows both AWS and Snowflake costs attributed to the Marketing team. Per our initial goal, the dashboard shows monthly data for the past six months. We’ve packaged a set of resources and variables we can use across multiple cloud service providers.
Adopting FinOps as Code in Your Organization
FinOps as Code offers a new, more streamlined approach to cloud cost management. It not only addresses the increasing complexity of cloud budgets and resource management but also aligns with traditional software practices, like infrastructure automation and collaboration. As cloud practitioners grapple with multi-cloud deployments and numerous cloud service providers, FinOps as Code can promote financial efficiency.
The tutorial demonstrated a practical application of FinOps Principles using Terraform. Cloud practitioners can easily implement this cost-efficient and collaborative approach. The FinOps as Code mindset will empower teams to take ownership of their cloud usage and ensure accessible and timely financial insights.
Lower your AWS costs.