Terraspace Extra Layering
Concept
Terraspace has a concept of extra stacks. The extra concept allows you to reuse the same stack and deploy multiple instances of it. It’s as simple as setting the TS_EXTRA env variable.
The stacks should be designed to allow for multiple instances of it to be deployed. Typically, this means making sure the resources created will have unique names.
Backend Adjustment
You also want adjust the backend to include it so stacks will have separate state files.
Example:
config/terraform/backend.tf:
Note, if TS_EXTRA
is not set. The //
will be “squished”. For example, so instead expanding out to:
us-west-2/dev/dev-2//stacks/demo/terraform.tfstate
The //
is replaced by a /
like so:
us-west-2/dev/dev-2/stacks/demo/terraform.tfstate
Example
Let’s say, we with have a stack that creates a server. Something like this:
app
└── stacks
└── server
├── main.tf
├── outputs.tf
└── variables.tf
app/stacks/server/main.tf
module "server" {
source = "../../modules/server"
instance_type = var.instance_type
tags = { "Name": var.name }
}
We can launch multiple “instances” of the stack to create servers using different tfvar files.
terraspace up server # uses dev.tfvars only
TS_EXTRA=2 terraspace up server # uses dev.tfvars and dev-2.tfvars (layered)
TS_EXTRA=3 terraspace up server # uses dev.tfvars and dev-3.tfvars (layered)
The tfvar structure files looks like this:
app
└── stacks
└── server
├── main.tf
├── outputs.tf
├── tfvars
│ ├── dev.tfvars
│ ├── dev-2.tfvars
│ └── dev-3.tfvars
└── variables.tf
The tfvars file for dev-2 and dev-3 servers could have different TS_EXTRA:
config/stacks/server/tfvars/dev-2.tfvars
name = "dev-2"
instance_type = "t3.small"
config/stacks/server/tfvars/dev-3.tfvars
name = "dev-3"
instance_type = "t3.medium"
Layering
The TS_EXTRA var adds another layer to be processed. Here’s the typical layering structure for review:
app/stacks/server
└── tfvars
├── base.tfvars
├── dev.tfvars
└── prod.tfvars
Terraspace adds the TS_EXTRA value as an additional layer.
app/stacks/server
└── tfvars
├── base.tfvars
├── dev.tfvars
├── dev-2.tfvars
└── prod.tfvars
So:
TS_ENV=dev TS_EXTRA=2 terraspace up server # uses base.tfvars, dev.tfvars and dev-2.tfvars (layered)
TS_ENV=prod TS_EXTRA=2 terraspace up server # uses base.tfvars, prod.tfvars and prod-2.tfvars (layered)
You can also organize the files in corresponding TS_ENV
based folders. Here’s an example of a different organization and how the extra layer also not include the env.
config/stacks/server/tfvars
├── base.tfvars
├── dev
│ ├── base.tfvars
│ └── 2.tfvars
└── prod
├── base.tfvars
└── 2.tfvars
State File
A different statefile key path is used different TS_EXTRA values. Example:
$ TS_EXTRA=2 terraspace up server -y
Building .terraspace-cache/us-west-2/dev/stacks/server.2 <= DIFFERENT
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
$
The instance value is appended after a period (.
). This allows multiple instances of the infrastructure to be deployed without colliding.
Extra Tfvars Example
Here’s an example with the TS_EXTRA
env var in a tfvars file.
config/stacks/server/tfvars/base.tfvars:
name = "<%= Terraspace.extra %>-server"
So:
TS_EXTRA=bob terraspace up server
Results in:
name = "bob-server"
So:
TS_EXTRA=kevin terraspace up server
Results in:
name = "kevin-server"
Code Instead of TfVars
Using the TS_EXTRA
with different tfvars is only one way to re-use the same infrastructure code. Depending on what you’re trying to achieve, you may want reuse the module code by calling it multiple times in the stack code itself. Something like this:
module "dev-2" {
source = "../../modules/server"
instance_type = "t3.small"
tags = { "Name": "dev-2" }
}
module "dev-3" {
source = "../../modules/server"
instance_type = "t3.medium"
tags = { "Name": "dev-3" }
}
It really depends on the problem being solved. Either way, Terraspace allows you to use either option.