NoviceMe
NoviceMe

Reputation: 3256

Terraform structure for two aws accounts

I have two AWS accounts, one for dev and other for prod. I am trying to create the same resources in both accounts as VPC, subnet, etc. From reading on google I came up with the following structure:

|---- README.md
|---- dev_account
    |---- main.tf
    |---- terraform.tfvars
    |---- variables.tf
|---- prod_account
    |---- main.tf
    |---- terraform.tfvars
    |---- variables.tf
|---- modules
    |---- provider.tf
    |---- vpc.tf
    |---- variables.tf

Here is some code I am using:

modules/provider.tf

provider "aws" {
  region = "${var.aws_region}"
}

module/vpc.tf

 resource "aws_vpc" "vpc" {
      cidr_block       = "${var.vpc_cidr_block}"
      instance_tenancy = "default"
 }

dev_account/main.tf:

module "create_infra" {
  source = "../modules"

  aws_region = "${var.aws_region}"
  vpc_cidr_block = "${var.vpc_cidr_block}"
}

Same as above I will create more modules like subnet and call from main.tf file.

dev_account/variables.tf

variable "aws_region" {}

variable "vpc_cidr_block" {}

dev_account/terraform.tfvars

aws_region = "us-west-1"
vpc_cidr_block = "10.10.10.0/8"

Is this the right approach? Is there a better way of doing this? main.tf file under dev_account does not seem correct, as it will get difficult to manage if I will have let's say 10 or more resources.

Upvotes: 1

Views: 639

Answers (2)

Mahattam
Mahattam

Reputation: 5763

I would suggest using the below folder structure, this will help to use the same main.tf terraform code for all environments that will give avoid replicating the same code in all env folders.

I'm using this in my current implementation and it's really helpful, to use this pattern you need to add the toggle on/off feature for each module so that based on a variable terraform can skip specific module as per environment needs.

|---- README.md
|---- deployment
    |---- main.tf
    |---- variables.tf
|---- environments
    |---- dev
        |---- backend.tfvar
        |---- variables.tfvar
    |---- prod
        |---- backend.tfvar
        |---- variables.tfvar
|---- modules
    |---- provider.tf
    |---- vpc.tf
    |---- variables.tf

To initialize and apply terraform use below command (cd to specific environment folder)

terraform init -var-file=variables.tfvar -backend-config=backend.tfvar ../../deployment/
terraform apply -var-file=variables.tfvar ../../deployment

Upvotes: 1

Blokje5
Blokje5

Reputation: 5003

This is indeed according to Terraform Best Practices. I would like to add a couple of remarks:

There might be differences between resources in Dev/Prod. For example in Dev you might use a MySQL instance deployed on a EC2 machine to save costs while in Prod you use a managed RDS instance.

So one module for all your infrastructure might be a bit hard to maintain, as it would start to get a lot of flags for the different options (e.g. MySQL vs RDS). Instead you can use the following setup:

modules
  rds
  ec2-mysql

and in your dev main.tf you would call the ec2-mysql module while in the prod main.tf you call the rds module.

There also might be a point where your infrastructure is becoming so large where splitting it only based on environment is hard. E.g. in Prod you might maintain several microservices, databases a data lake and who knows what. And you might want to be able to deploy changes in the data lake without running the risk that you update something in the microservices. At that point you have two approaches:

  1. Split the code up over multiple repositories. You can source terraform modules by git reference.
  2. Move to a folder structure like this:
environment
  dev
    microservices
    data lake

you could potentially use a tool like Terragrunt to make that last setup easier

Hopefully this has given you some useful input.

Upvotes: 1

Related Questions