Taming Terraform with Modules

Some of us know what Terraform is. It’s an Open Source tool created and maintained by Hashicorp to help us specify and manage our Infrastructure as Code across multiple Infrastructure as a Service (IaaS) and Cloud providers.

When you start learning Terraform you make use of it’s primitive types: data sources and resource statements. If you’re trying it out and simply creating a Ghost publication in The Cloud these primitives do the job. It’s a great way to tie together your understandings of the building blocks to make something on whatever Cloud provider you’re using. Typically, a VPC, a few Subnets, A Routing table, a Nat Gateway, an ELB, a handful of Security Groups, an Instance and a Database will have you up and running with a shiny new Ghost publication. A bit of an expensive Ghost publication.

Unfortunately, most of us aren’t doing simple, one-off things in our day jobs. We’re building complex and often evolutionary infrastructures across multiple projects, products, teams, accounts, locations and cloud providers. Handcrafting all of that Terraform code from the primitives offered would be a nightmare from the beginning. Maintaining consistency across all the things would be pretty much impossible. I’ve been there and I ran away. Fast! This is where Terraform modules help us out.

Terraform has some good documenation on writing basic modules:

Modules allow us to create reusable collections of resources that are often used together to do something and expose them as a single module resource in Terraform.

As an example: EC2 instances will usually belong to an Autoscaling Group, have a Launch Configuration and be attached to some Security Groups. By bundling these into a module you can reuse the same code by passing different parameters into the module and you get a similar result each time. Before we break out the module shotgun it’s worth understanding that there are multiple types of module.

Component Modules

A component module has a focussed job and only interacts with a single cloud provider and only uses the low-level Terraform resources. It might group together an ASG, Launch Configuration and Security Group or a VPC, Subnets, Route Tables and Internet / NAT Gateways.

Component modules are typically the type of module you’ll find on the Terraform Registry. Some good examples are:

Infrastructure or Service Modules

So, you’ve started using upstream component modules and you start to realise that you’re doing the same things, adding the same tags, using autoscaling, security-group and alb together to create a service and inputting a lot of default boilerplate values.

This is where Infrastructure modules take over. You can use Terraform modules within other modules. You can create modules that enforce best practice or certain requirements and create things in a consistent way across your infrastructures. They sometimes make use of multiple providers. Some examples:

Data Modules

Modules that do nothing more than give static output for use in other modules. They might be used to enforce available instance types, provide some data like an instance price to use for spot prices or normalise instance sizes across cloud providers. An example of a data module might be something like:

Hopefully some of this makes sense and can help you evolve your Terraform code into something more beautiful than it was previously.

Something I haven’t touched on here is managing Terraform module versions and dependencies. I might braindump a post on this soon. Thanks for reading!

comments powered by Disqus
Taming Terraform with Modules
Share this