1
votes

Let's take the following module as an example.

https://registry.terraform.io/modules/terraform-aws-modules/ec2-instance/aws/1.0.1

If my app stack requires a few web servers, an ELB and a mysql server, I plan on utilizing modules so that I'm not repeating my code. My question is, should I have simple modules such as the one listed above (then one for ELB and one for MySQL), and then combine all that by making a stack out of it within env-dev/app/apollo/main.tf?

Example structure:

├── env-dev
│   └── app
│       └── apollo
│           └── main.tf
├── env-test
├── global
├── mgmt
└── modules
    ├── ec2-elb
    └── ec2-instance
        ├── LICENSE
        ├── main.tf

Should my env-dev/app/apollo/main.tf source the two modules to build the app or should I be creating a module to build out the instances along with ELB?

1

1 Answers

3
votes

Generally-speaking, a module should be created only if it either imposes some restrictions on use (to apply organization-specific conventions, for example) or if it represents a number of resources that behave (from the perspective of your system) as an atomic unit that may be instantiated multiple times.

The registry module you linked to is not a good example of a reusable module because it is merely a wrapper around an existing resource, passing through input arguments exactly and adding no value beyond what could be expressed with the resource block directly. That module serves more as a "getting started" example to copy into your root module, rather than something you'd call directly, since it doesn't raise the level of abstraction any higher than the resource it wraps.

There are a few different ways to approach the structure of a Terraform configuration, but when modelling simple things I would suggest starting with a single root module with direct resource blocks inside of it. Over time, you may notice that certain resources are effectively being copy-pasted (with minor adjustments) either within the same configuration or across multiple configurations; at that point I would consider factoring out those resources into modules that can be instantiated multiple times.

There is no definitive answer to how many things should be packed together into a module. Just like with functions in a programming language, it's generally better to err on the side of small building blocks that you can compose together, rather than large and inflexible units. However, exactly where to draw the line is something that depends on the situation. To decide, think about the different permutations you expect to need to support, and which things seem to "naturally" belong together.

If you don't get it right the first time then it's not the end of the world because you can use the terraform state mv command to move resource state between modules as you refactor your configuration.