Terraform
Deploy a Stack with HCP Terraform
HCP Terraform Stacks help you manage complex infrastructure deployments across multiple environments by providing a different model of infrastructure management from Terraform workspaces. Instead of loosely coupled workspaces, a Stack consists of a set of components that are organized into one or more deployments, each of which HCP Terraform will provision as a unit. Each of the deployments in your Stack will provision the same Terraform configuration, defined by your Stack’s components, defined as a Terraform module. Stacks allow you to manage the lifecycle of each of your deployments independently, since changes to one deployment in your Stack do not affect the others. Each deployment in a Stack represents a set of infrastructure that works together, such as a dev, test, or production environment. HCP Terraform will roll out changes to each deployment at a time, and allows you to track changes across your environments.
In this tutorial, you will provision an HCP Terraform Stack consisting of two deployments of virtual machines and related resources, organized into logical components. You will use HCP Terraform to deploy this infrastructure to both environments, and then add and deploy a third environment. You will review the status of each deployment in HCP Terraform, learn how Stacks manages changes between deployments, and then remove all three deployments.
Terraform Stacks include:
- A Stack, defining a set of components that Terraform will manage across one or more deployments.
- One or more deployments, which represent an instance of the components in a stack configured for a specific purpose or environment.
- Each deployment is made up of components, which are Terraform modules that define part of the infrastructure that makes up a deployment.
Prerequisites
This tutorial assumes that you are familiar with the Terraform and HCP Terraform workflows. If you are new to Terraform, complete the Get Started collection first. If you are new to HCP Terraform, complete the HCP Terraform Get Started tutorials first.
In order to complete this tutorial, you will need the following:
- An AWS account and credentials to use to authenticate.
- An HCP Terraform account.
- An HCP Terraform variable set configured with your cloud provider credentials.
Create example repository
Navigate to the template
repository
for this tutorial. Click the Use this template button and select Create a
new repository. Choose a GitHub account to create the repository in and name
the new repository learn-terraform-stacks-deploy-aws
. Leave the rest of the
settings at their default values.
In your terminal, clone your example repository, replacing USER
with your own
GitHub username.
$ git clone https://github.com/USER/learn-terraform-stacks-deploy-aws
Change to the repository directory.
$ cd learn-terraform-stacks-deploy-aws
Review components and deployment
A Terraform Stack is made up of one or more components, each sourced from a
Terraform module and configured with inputs and the module’s specified
providers. HCP Terraform will provision all of these components for each of the
deployments in your Stack. Each deployment block defined in tfdeploy.hcl
files
represents an independent deployment of this Stack’s infrastructure.
As with Terraform configuration files, HCP Terraform processes all of the blocks
in all of the tfcomponent.hcl
and tfdeploy.hcl
files in your Stack's root
directory in dependency order, so you can organize your component configuration
into multiple files just like Terraform configuration.
Explore the example configuration to review how this Terraform Stack's configuration is organized.
.
├── components.tfcomponent.hcl
├── deployments.tfdeploy.hcl
├── instance
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── key_pair
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── LICENSE
├── outputs.tfcomponent.hcl
├── providers.tfcomponent.hcl
├── README.md
├── variables.tfcomponent.hcl
└── vpc
├── main.tf
├── outputs.tf
└── variables.tf
In addition to the licensing-related files and README, the example repository
has three directories containing Terraform modules that define the
infrastructure components of your stack. The repository
also includes the files required to configure your Stacks: a deployments file
named deployments.tfdeploy.hcl
, and Stack configuration files with the
extension .tfcomponent.hcl
. These configuration files replace a Terraform
workspace's root module and serve as the blueprint for the infrastructure your
Stack will manage.
Review Stack components
Open the providers.tfcomponent.hcl
file. This file contains the provider
configuration for your Stack.
providers.tfcomponent.hcl
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.14.1"
}
tls = {
source = "hashicorp/tls"
version = "~> 4.1.0"
}
}
provider "aws" "this" {
for_each = var.regions
config {
region = each.value
assume_role_with_web_identity {
role_arn = var.role_arn
web_identity_token = var.identity_token
}
default_tags {
tags = var.default_tags
}
}
}
provider "tls" "this" {}
The required_providers
block defines the providers used in this configuration,
and uses a syntax similar to the required_providers
block nested inside the
terraform
block in Terraform configuration.
This configuration includes provider
blocks that configure each provider.
Unlike standard Terraform configuration, Stacks provider blocks include a label,
allowing you to configure multiple providers of each type if needed. For
example, this configuration includes a for_each
meta argument so that Stacks
will use a separate provider configuration for each region defined in the
regions
variable.
For example, in configuration you would refer to the AWS provider for the
us-east-1
region as provider.aws.configurations["us-east-1"]
.
The assume_role_with_web_identity
block configures provider authentication to
use a JWT identity token managed by trust relationship that you will provision
later in this tutorial. Each of your deployments will pass the ARN of your trust
relationship’s IAM role and a corresponding JWT identity token generated by your
cloud provider each time you plan or apply your Stack. This allows each of your
deployments to use their own role, which you can configure with the specific
permissions required by your project.
Next, review the components.tfcomponent.hcl
file. This file includes
configuration for three components: vpc
, key_pair
, and instance
.
Review the configuration for the vpc
component.
components.tfcomponent.hcl
component "vpc" {
source = "./vpc"
for_each = var.regions
inputs = {
vpc_name = "stacks-${each.value}-${var.default_tags.Environment}"
}
providers = {
aws = provider.aws.this[each.value]
}
}
A Stack component
block sets a Terraform module as a source, sets any variable values for
the module, and specifies the providers that Terraform will use to provision your
infrastructure. Each component can also include output values. Components
can refer to the output values from other components.
The components in the example configuration use the for_each
meta-argument to
deploy their Terraform module in each of the regions you configure for the
current deployment. Notice that in the provider
block, your provider is
configured to use the correct provider for the given region with
provider.NAME.configurations[each.value]
.
The instance
component is configured to use output values from the
corresponding vpc
component for each region it is deployed in. The
configuration for each component is found in the subdirectory referenced by the
source
argument. You can also use modules from external sources such as the
Terraform Registry with the same syntax as for Terraform module
blocks. Since
your Stack will configure the appropriate providers for each of your
deployments, you cannot include provider
blocks in modules you intend to use
with Stacks.
Review deployments
Each deployment represents an instance of all of the components in your Stack,
which you will customize with the inputs
argument. You can use multiple
deployments to manage self-contained instances of your Stack’s infrastructure,
such as development, test, and production environments, or multiple instances of
the same infrastructure distributed across multiple cloud regions.
Open the deployments.tfdeploy.hcl
file and review the two deployments for this
example.
deployments.tfdeploy.hcl
identity_token "aws" {
audience = ["aws.workload.identity"]
}
deployment "development" {
inputs = {
regions = ["us-east-1"]
role_arn = "<YOUR_ROLE_ARN>"
identity_token = identity_token.aws.jwt
default_tags = {
Stack = "learn-stacks-deploy-aws",
Environment = "dev"
}
}
}
deployment "production" {
inputs = {
regions = ["us-east-1", "us-west-1"]
role_arn = "<YOUR_ROLE_ARN>"
identity_token = identity_token.aws.jwt
default_tags = {
Stack = "learn-stacks-deploy-aws",
Environment = "prod"
}
}
}
This file includes two deployments, one for development, and a second for
production. Each deployment block represents an instance of the configuration
defined in the Stack, configured with the given inputs. Your development
deployment is configured for a single region, while your production deployment
is configured in two regions.
Fork identity token repository
Your Stack will use a JWT identity token to authenticate your cloud provider provider in each region. To do so, you must first establish an OIDC trust relationship between your cloud provider and HCP Terraform, and configure the appropriate permissions to create and manage your Stack.
Navigate to the template
repository
for creating an identity token. Click the Use this template button and
select Create a new repository. Choose a GitHub account to create the
repository in and name the new repository
learn-terraform-stacks-identity-tokens
. Leave the rest of the settings at
their default values.
Create a project
Create an HCP Terraform project for this tutorial.
To do so, first log in to HCP Terraform, and select the organization you wish to use for this tutorial.
Next, ensure that Stacks is enabled for your organization by navigating to
Settings > General. Ensure that the box next to Stacks
is checked, and
click the Update organization button.
Then navigate to Projects, click the + New Project button, name your
project Stacks
, and click the Create button to
create it.
Provision and set identity token
Next, ensure that your cloud provider credentials variable set is configured for
your project. Navigate back to < Projects, then to your organization’s
Settings > Variable sets page, and select your credentials variable
set. Under
Variable set scope, select Apply to specific projects and workspaces,
and add your Stacks
project to the list under
Apply to projects. Scroll to the bottom of the page and click the Save
variable set button to apply it to your new project.
Next, provision the identity token and role that HCP Terraform uses to authenticate with your cloud provider when it deploys your Stack.
Navigate to Projects and select your Stacks
project. Create a workspace to provision your project's identity tokens:
- On the project overview page, select New > Workspace.
- On the next screen, select Version Control Workflow and select your GitHub account.
- On the Choose a repository page, select the
learn-terraform-stacks-identity-tokens
repository you created in the previous step. - On the Configure settings step, name your workspace
learn-terraform-stacks-identity-tokens-aws
. - Expand the Advanced options interface, and set the Terraform Directory to
aws/
. - Scroll to the bottom of the page and click the Create button to create your identity token workspace.
Once you create the workspace, HCP Terraform loads the configuration for your
identity token. This process may take a few seconds to complete. Once it does,
HCP Terraform prompts you to enter values for your organization and project.
Enter your organization name and the project name for this tutorial, Learn
Stacks
and click the Save variables button.
Next, click the Start new plan button, and then Start, to plan your changes. HCP Terraform plans your changes, and prompts you to apply them. Once the plan is complete, click the Confirm and apply button and then Confirm plan to create your OpenID provider, policy, and role.
Make a copy of the role_arn
output value. You will use it in the next step.
Configure identity token
Open the deployments.tfdeploy.hcl
file in the
learn-terraform-stacks-deploy-aws
repository on your local machine and replace
the <YOUR_ROLE_ARN>
for both deployments with the role_arn
output value from
your identity token workspace.
deployments.tfdeploy.hcl
deployment "development" {
inputs = {
regions = ["us-east-1"]
role_arn = "<YOUR_ROLE_ARN>"
identity_token = identity_token.aws.jwt
default_tags = {
Stack = "learn-stacks-deploy-aws",
Environment = "dev"
}
}
}
deployment "production" {
inputs = {
regions = ["us-east-1", "us-west-1"]
role_arn = "<YOUR_ROLE_ARN>"
identity_token = identity_token.aws.jwt
default_tags = {
Stack = "learn-stacks-deploy-aws",
Environment = "prod"
}
}
}
Commit the changes to your git repository.
$ git add deployments.tfdeploy.hcl && git commit -m "Configure identity token"
Push the change to Github
$ git push
Note
For this tutorial, you configured the same identity token for each deployment. In your own environment, use a different configuration for each deployment, with appropriately scoped permissions for your project.
Create and deploy Stack in HCP Terraform
Now that you have configured your Stack with your identity token, create and deploy your Stack.
In HCP Terraform, navigate to your Stacks
project, and select New >
and click Stack.
On the Connect to a version control provider page, select your GitHub
account. Then, choose the repository containing the example Stack for this
tutorial, learn-terraform-stacks-deploy-aws
. On the next page, leave your
Stack name the same as your repository name, and click Create Stack to
create it.
HCP Terraform will load your Stack configuration from your VCS repository. This process may take a few moments to complete.
Provision infrastructure
Once HCP Terraform loads your configuration, it plans your changes. HCP Terraform plans each deployment separately, and you can choose when to apply each plan. Under Deployments rollout, HCP Terraform lists your development and production deployments, as well as their current status.
Select your development
deployment to review your deployments status. HCP
Terraform created a plan for your deployment. Select it to review the changes to
be applied. Click the Approve plan button to apply it now, which may take a
few minutes. Once the plan is complete, you can review the resources that HCP
Terraform will create, and apply the plan.
After a few minutes, HCP Terraform finishes applying your development deployment. Review the results of the deployment.
Navigate to your production
deployment and apply it as well. Once HCP
Terraform has finished deploying your infrastructure, your Stack's status will
change to Rolled out. You can manage each deployment in a Stack separately,
update your Stack's configuration, and roll those changes out one environment at
a time.
Add a new deployment
Now, you will provision a new test deployment of your Stack.
Open the deployments.tfdeploy.hcl
file in your editor, and add a new
deployment block to represent a test environment. This deployment uses the same
configuration as your other deployments.
Replace <YOUR_ROLE_ARN>
with the same output value you used for your other
deployments.
deployments.tfdeploy.hcl
deployment "test" {
inputs = {
regions = ["us-east-1", "us-west-1"]
role_arn = "<YOUR_ROLE_ARN>"
identity_token = identity_token.aws.jwt
default_tags = {
Stack = "learn-stacks-deploy-aws",
Environment = "test"
}
}
}
Commit and push this change to your GitHub repository.
First, add the change.
$ git add deployments.tfdeploy.hcl
Next, commit it.
$ git commit -m "Add test deployment"
Finally, push the change to GitHub.
$ git push
Return to your Stack in HCP Terraform, navigate to your Stack's Deployments page. Once HCP Terraform loads your configuration change, it will add your new deployment. Review the plan and apply it as you did the others.
Destroy infrastructure
Now you have used a Terraform Stack to deploy three independent environments. You can manage each environment separately, and roll out changes to your stack one environment at a time.
Before finishing this tutorial, destroy your infrastructure.
Destroy deployments
To destroy a deployment, you must set the destroy
argument on that
deployment's block and commit your configuration to your VCS. Destroy all three
of the deployments you created in this tutorial.
deployments.tfdeploy.hcl
deployment "development" {
inputs = {
## ...
}
destroy = true
}
deployment "production" {
inputs = {
## ...
}
destroy = true
}
deployment "test" {
inputs = {
## ...
}
destroy = true
}
Commit and push this change to your GitHub repository.
First, add the change.
$ git add deployments.tfdeploy.hcl
Next, commit it.
$ git commit -m "Destroy all deployments."
Finally, push the change to GitHub.
$ git push
Return to your Stack in HCP Terraform, navigate to your Stack's Deployments page. Once HCP Terraform loads your configuration change, it will plan to destroy all three of your deployments. Navigate to each deployment and click the Approve plan button to destroy the resources for that deployment.
Destroy stack
Once you have destroyed all three of your deployments, navigate to your Stack's Settings > Destruction and Deletion page, and click the Delete Stack learn-terraform-stacks-deploy button. Confirm the action, and click the Delete button.
Finally, navigate to your learn-terraform-stacks-identity-token
workspace’s
Settings > Destruction and Deletion page, and follow the prompts to destroy
your identity token infrastructure and delete the workspace. You can also remove
your project by navigating to its settings page and following the steps to
delete it.
Next steps
In this tutorial, you learned how to deploy a Stack with HCP Terraform across multiple environments. You also learned how Stacks support deploying the same configuration across multiple regions, and deployed a third instance of your Stack as a test environment. In addition to allowing you to define any number of environments in a single configuration, Terraform Stacks include powerful orchestration and workflow features.
- Read the Terraform Stacks documentation for more details on Stacks features and workflow.
- Read the Terraform Stacks, explained blog post.
- Learn how to use Stacks deferred actions to manage Kubernetes workloads by following the Manage Kubernetes workloads with Stacks tutorial.