Reputation: 3256
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
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
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:
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