info
This post explains some customizations I did to save AWS Control Tower costs. I followed the next article to set it up: Manage AWS Accounts Using Control Tower Account Factory for Terraform. I recommend you read it before continuing. Basic knowledge about AWS and Terraform is required.
Context
Whenever I want to start a new project, I create an AWS account for each environment, I do it to separate domains and costs. So far, I have been doing this manually, but then I discover the Account Factory for Terraform (AFT) as part of the AWS Control Tower services.
AFT defines a GitOps process to automate the account creation and update. It is based on two main elements:
- Git repositories where the account creation request and customizations are defined.
- AWS resources used in the account creation/update process. All of them are based on the repository code. Some of them are CodePipeline, Dynamo tables, Lambdas, and Step Functions.
I don't want to go into details, but I think it is worth mentioning that this automatization simplifies the whole process, not only because we avoid manual operations (that is always nice, right?), but because it allows us to align different AWS accounts.
A customization example could be to define a Budget after creating the account. We can add a notification when we are close to a maximum amount (in fact, this was my main goal at first, to avoid any unexpected cost ๐). Next are other examples:
- Create default resources like S3 buckets
- Add SSM parameters to describe the account
- Add custom policies
info
I'm not going to go into the customization details in this article. I just want to point out a few examples. I will explain it in a separate post in the future.
Problem: Costs
AFT does not have a cost itself, the cost depends on the resources deployed and used. Next are the main costs per resource after a few days of using it:
- VPC Endpoints: billed hourly.
- NatGateway.
I found it in the Cost Explorer of my root account, grouping by API Operation:
Solution
Delete the VPC Endpoints when not used
The AFT repository (terraform-aws-control_tower_account_factory) offers the flag aft_vpc_endpoints
to enable/disable the VPC Endpoints. As those are billed hourly, it doesn't make sense to have them on if you are not using them. So, to save costs, only turn them on before requesting a new account, and once it is finished, turn them off. The idea is simple, let's see that in practice:
The basic TF code that creates the AFT infrastructure is:
module "aft" {
source = "github.com/aws-ia/terraform-aws-control_tower_account_factory"
ct_management_account_id = var.ct_management_account_id
log_archive_account_id = var.log_archive_account_id
audit_account_id = var.audit_account_id
aft_management_account_id = var.aft_management_account_id
ct_home_region = var.ct_home_region
tf_backend_secondary_region = "us-west-2"
vcs_provider = "github"
account_request_repo_name = "${var.github_username}/learn-terraform-aft-account-request"
global_customizations_repo_name = "${var.github_username}/learn-terraform-aft-global-customizations"
account_customizations_repo_name = "${var.github_username}/learn-terraform-aft-account-customizations"
account_provisioning_customizations_repo_name = "${var.github_username}/learn-terraform-aft-account-provisioning-customizations"
}
Once we have created the infrastructure by executing a terraform apply
, the VPC endpoints are enabled by default, we process to send the account creation request (explained in the tutorial). Once it is finished, we set the aft_vpc_endpoints
flag to false:
module "aft" {
source = "github.com/aws-ia/terraform-aws-control_tower_account_factory"
...
aft_vpc_endpoints = false
}
We reexecute terraform apply
and done! VPC endpoints deleted and costs reduced!
Delete the NAT related resources when not used
Maybe, the first approach we think is to manually delete the NAT resources. Then, before queuing any account creation request, we use Terraform to recreate them. That might work, but it involves manual intervention on in the AWS Console for every request, we don't want that.
So, taking into account that the AFT code is in a GitHub repository, I thought it was better to fork it and add a new flag to conditionally create the NAT resources. So, I did the next steps:
- I forked the AWS GH repo aws-ia/terraform-aws-control_tower_account_factory in cangulo-aws-aft/terraform-aws-control_tower_account_factory.
- I created a new flag called
aft_vpc_nat_gateway
following theaft_vpc_endpoints
model. - I modify the NAT resources to depend on the new flag.
Everything is done in this commit.
Then, I simply update the "aft" module source to my fork and provide the new flag. Next is the result:
module "aft" {
# source = "github.com/cangulo-aws-aft/terraform-aws-control_tower_account_factory" # repo in the cloud
# source = "github.com/cangulo-aws-aft/terraform-aws-control_tower_account_factory"
source = "../terraform-aws-control_tower_account_factory" # repo in the same local path
ct_management_account_id = var.ct_management_account_id
log_archive_account_id = var.log_archive_account_id
audit_account_id = var.audit_account_id
aft_management_account_id = var.aft_management_account_id
ct_home_region = var.ct_home_region
tf_backend_secondary_region = var.tf_backend_secondary_region
vcs_provider = "github"
account_request_repo_name = "${var.github_username}/account-request"
account_provisioning_customizations_repo_name = "${var.github_username}/account-provisioning-customizations"
global_customizations_repo_name = "${var.github_username}/global-customizations"
account_customizations_repo_name = "${var.github_username}/account-customizations"
aft_feature_delete_default_vpcs_enabled = false
aft_vpc_aws_nat_gateway = false
aft_vpc_endpoints = false
}
Reduced Costs
I deactivated the VPC Endpoints since the day 11, NAT costs disappeared next days.
References:
- Youtube Tutorial for setting up AWS Control Tower: Enable AWS Control Tower for Existing Organizations
- Manage AWS Accounts Using Control Tower Account Factory for Terraform
- Account Factory for Terraform
Git Repositories
learn-terraform-aft-account-provisioning-customizations
learn-terraform-aft-account-customizations
learn-terraform-aft-global-customizations
learn-terraform-aft-account-request
About me
I'm a Software Engineer with experience as Developer and DevOps. The technologies I have worked with are DotNet, Terraform and AWS. For the last one, I have the Developer Associate certification. I define myself as a challenge-seeker person and team player. I simply give it all to deliver high-quality solutions. On the other hand, I like to analyze and improve processes, promote productivity and document implementations (yes, I'm a developer that likes to document ๐งโ๐ป).
You can check my experience here.
Personal Blog - cangulo.github.io
GitHub - Carlos Angulo Mascarell - cangulo
LinkedIn - Carlos Angulo Mascarell
Twitter - @AnguloMascarell