AWS Cloud Operations & Migrations Blog

Getting started with myApplications for Terraform-managed applications

Introduction

AWS customers often operate hundreds of applications and have to monitor and manage individual resources to make sure their applications are available, secure, cost-optimized, and performing optimally. AWS application operations is a set of capabilities that helps customers move faster at scale and operate their applications with less effort across AWS services, consoles, and Infrastructure as Code (IaC). The myApplications dashboard supports application operations by showing you an application-centric view of key application metrics such as the cost, health, security findings, and performance in one view in the AWS Management Console.

In a previous blog post, we walked through how to create an application through the AWS Console Home page. However, manual operations in the console can be complex to scale when you have a lot of environments, applications, and teams. For these reasons, many organizations look to Infrastructure as Code (IaC) tools like HashiCorp Terraform to automate resource deployments. Terraform allows you to collaborate effectively by configuring your resources declaratively in code, translating your configuration to the necessary API calls to create your resources.

In this blog post, we will walk through how to use Terraform to create an application for use with myApplications, add resources to new and existing applications, and strategies for scaling application management using Terraform.

Benefits of operating applications with myApplications

Application operations requires a consistent application model; AWS Service Catalog AppRegistry stores application metadata, AWS Resource Groups logically groups application resources, and resource tagging organizes the application’s resources into searchable resource groups.

When an AppRegistry application is created, AppRegistry associates the AWS resources as a resource group using a vended application tag. The tag key is awsApplication and the value is a unique identifier for the application. The tag key and value are both case sensitive. Any AWS resources tagged with this key-value pair become part of the application. This application tag allows AWS services to support application operations by referencing that application tag within their consoles and APIs.

The myApplications dashboard uses the application tag to provides a combined view of metrics for your chosen application, including cost and usage, security, and operations metrics and insights from multiple AWS services.

myApplications dashboard for example application called Banana. myApplications dashboard is shown with four widgets to show application summary, cost and usage, security findings and DevOps status such as patch compliance.

Customers are able to view widgets with metrics and data specific to that application and drill down to more specific information with the embedded console links. Within the different services, you can filter with the awsApplication tag to view the resources attached to the application. For example, the Cost and usage widget allows you to view the costs associated with the application and see the forecasted costs. If you wanted to see previous months costs or have a more granular view of the costs, you click on the link which would take you to AWS Cost Explorer with a filter already applied for the awsApplication tag value of your application.

Cost and Usage report showing chart of total cost per month, grouped by service name and filtered by the awsApplication tag for application called Banana.

Now that we understand the benefits and how the awsApplication tag work, let’s dive right in how we can implement the awsApplication tag with Terraform.

Prerequisites

Before starting, you will need the following prerequisites:

Creating a new application

To get started with application operations and defining our application with the appropriate resources, we first need to leverage AppRegistry to register the application using the aws_servicecatalogappregistry_application resource block. This allows myApplications to display the application based on the metadata store. For this example, we start by registering a new AppRegistry application named MarketingWebApp. In the latter section, we will add additional resources such as VPC or EC2 instances to the Terraform configuration.

To run this, we use the following steps:

  • Create a new working directory with a new file named tf
  • Copy the content below into the tf file
# Register new application
resource "aws_servicecatalogappregistry_application" "marketing_web_app" {
  name        = "MarketingWebApp"
  description = "New marketing web application"
}
  • Initialize our Terraform directory by running terraform init
  • Apply our configuration by running terraform apply
  • Review the Terraform plan output and confirm the operation

After performing the above operations, the MarketingWebApp visible in myApplications alongside other applications in the selected region.

myApplications summary page showing two applications within the us-west-2 region named InternalWiki and MarketingWebApp.

Adding resources to the application with tagging

Now that our application is created, we will extend our Terraform code to create resources and associate them to the application. We can use the vended application tag to associate resources with our application. This is visible on the myApplications dashboard under Application summary.

myApplications application summary widget showing the application tag and value for an application called MarketingWebApp.

With Terraform, this tag key-value is available on the application_tag attribute of the aws_servicecatalogappregistry_application resource. This attribute contains a map with a single key-value pair containing the tag. This allows us to easily add it to the tags of our application resources.

The updated Terraform code below will deploy a new Amazon Virtual Private Cloud (VPC), an Amazon EC2 instance in a private subnet, and an Amazon CloudWatch alarm which monitors the CPU utilization of the instance. The resources deployed here are covered by the AWS Free Tier with the exception of NAT Gateway. Refer to the Amazon VPC pricing page for NAT Gateway pricing.

# Register new application
resource "aws_servicecatalogappregistry_application" "marketing_web_app" {
  name        = "MarketingWebApp"
  description = "New marketing web application"
}

# Lookup latest Amazon Linux 2023 AMI with SSM
data "aws_ssm_parameter" "al_2023" {
  name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64"
}

# Create application VPC
module "vpc" {
  source     = "aws-ia/vpc/aws"
  version    = "~> 4.4"
  name       = "marketing-vpc"
  cidr_block = "10.0.0.0/16"
  az_count   = 2

  subnets = {
    public = {
      netmask                   = 24
      nat_gateway_configuration = "all_azs"
    }
    private = {
      netmask                 = 24
      connect_to_public_natgw = true
    }
  }
  tags = aws_servicecatalogappregistry_application.marketing_web_app.application_tag
}

# Create application instance
resource "aws_instance" "web_server" {
  instance_type = "t3.micro"
  ami           = data.aws_ssm_parameter.al_2023.value
  subnet_id     = module.vpc.private_subnet_attributes_by_az["private/${module.vpc.azs[0]}"].id
  tags          = aws_servicecatalogappregistry_application.marketing_web_app.application_tag
}

# Create CloudWatch Alarm
resource "aws_cloudwatch_metric_alarm" "web_server_cpu" {
  alarm_name          = "marketing-web-server-cpu-high"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = 2
  metric_name         = "CPUUtilization"
  namespace           = "AWS/EC2"
  dimensions = {
    InstanceId = aws_instance.web_server.id
  }
  period                    = 120
  statistic                 = "Average"
  threshold                 = 80
  alarm_description         = "This metric monitors EC2 CPU utilization"
  insufficient_data_actions = []
  tags                      = aws_servicecatalogappregistry_application.marketing_web_app.application_tag
}

Notice in the Terraform configuration above, each resource is tagged with aws_servicecatalogappregistry_application.marketing_web_app.application_tag.

To apply this configuration:

  1. Replace the contents of your main.tf file with the contents above
  2. Run the command terraform init again to install the Terraform module used
  3. Run the command terraform apply
  4. Review the Terraform plan and approve the operation

After doing so, we can find the newly created resources in myApplications under Manage resources.

myApplications “Manage resources” page showing a list of resources including Amazon EC2, VPC, and CloudWatch resources.

Tagging application resources at scale with default_tags

In the previous example, we set the tags on each individual resource and module by referencing the application_tag of our new application. This is a great way to get started, but can be hard to scale as our Terraform-managed application continues to grow with more resources.

One option to help you scale your application tagging is to use the default_tags configuration block of the AWS provider. By using this feature, all existing and future resources using the provider will be automatically tagged with the application tag we specify and associated to our application.

The default_tags is configured at AWS provider block level. We cannot directly reference our Terraform-managed application in the same provider configuration that provisioned the resource because it would create a circular dependency. Instead, we will need to configure separate AWS provider block: one to create our AppRegistry application and one to create the rest of our application resources.

Let’s try updating our Terraform code to use this method. First, we will create a new aliased AWS provider block and modify our aws_servicecatalogappregistry_application resource to use that provider:

# Create application using aliased 'application' provider
provider "aws" {
  alias = "application"
}

resource "aws_servicecatalogappregistry_application" "marketing_web_app" {
  provider    = aws.application
  name        = "MarketingWebApp"
  description = "New marketing web application"
}

Next, we will define another AWS provider block for deploying our application resources, assigning default_tags to tag all resources with the correct application tag.

# Configure default tags
provider "aws" {
  default_tags {
    tags = aws_servicecatalogappregistry_application.marketing_web_app.application_tag
  }
}

With the default tags in place, we no longer need to manually add tags for each individual resource configurations. The tags will apply to all existing and future resources using that provider.

Using an existing application

What if our application is created outside of our Terraform configuration? The AppRegistry application may be managed by different Terraform root module, a CloudFormation Stack, automation script, or manual process. In this case, we can use the AWS provider data source to lookup the application tag based of the application ID.

First, we locate the application id in the AWS Service Catalog AppRegistry console or through the AWS CLI. There is an InternalWiki application that was created outside of Terraform.

AWS Service Catalog AppRegistry console applications summary page showing the application name and application ID for applications named InternalWiki and MarketingWebApp.

For this example, we declare a Terraform input variable to hold the value of our application ID, which will be passed during Terraform plan or apply. The aws_servicecatalogappregistry_application data source block uses the application ID input variable to read the application tag from the existing AppRegistry application. Now we can set the default_tags value using output of the data source block as shown below.

# Look up application
provider "aws" {
  alias = "application"
}

variable "application_id" {}

data "aws_servicecatalogappregistry_application" "marketing_web_app" {
  provider = aws.application
  id       = var.application_id
}

# Configure default tags
provider "aws" {
  default_tags {
    tags = data.aws_servicecatalogappregistry_application.my_existing_application.application_tag
  }
}

The tag will apply to all existing and future resources using that provider without needing to explicitly set the tags attribute in each resource block. If we update our code and apply deploy the new configuration with Terraform, the resources are added to the InternalWiki application and will appear in the myApplications dashboard.

myApplications dashboard for the applications named InternalWiki. myApplications dashboard is shown with three widgets to show summary of compute resources, DevOps status such as patch compliance, and cost and usage.

Clean up

If you have been following along and no longer need the resources created from this blog, don’t forget to clean up the resources created in your account by running the CLI command terraform destroy. This is a sensitive operation that will delete resources, so be sure to review the output of the Terraform plan before confirming.

Conclusion

In this post, you learned how to use Terraform to manage resources in an application-centric view and use the myApplications dashboard in the AWS Management Console to visualize the costs, health, and performance of your resources. You also learned how to associate resources created in Terraform to AppRegistry applications by applying the application tag. Lastly, we discussed how to use multiple AWS provider blocks and default_tags to automatically tag all resources within your Terraform-based application. For more information on how to use AWS Service Catalog AppRegistry in Terraform, please check out the Terraform AWS Provider documentation.

Sean Nixon

As a Senior Technical Account Manager at AWS, Sean spends his time helping customers achieve their goals and operate successfully at scale on AWS. He is an experienced Terraform practitioner with over 7 years of experience in cloud operations, security, DevOps, and Infrastructure as Code. When he’s not at work, Sean enjoys spending time outdoors and hosting board game nights.

Welly Siauw

As a Principal Partner Solution Architect, Welly led the co-build and co-innovation strategy with AWS ISV partners. He is passionate about Terraform, Developer Experience and Cloud Governance. Welly joined AWS in 2018 and carried with him almost 2 decades of experience in IT operations, application development, cyber security, and oil exploration. In between work, he spent time tinkering with espresso machines and outdoor hiking.