Skip to content

Terraform Modules

← Back to all decks

38 cards — 🟢 6 easy | 🟔 16 medium | šŸ”“ 6 hard

🟢 Easy (6)

1. What is the difference between Terraform modules and resources?

Show answer In Terraform, resources represent individual infrastructure components (e.g., virtual machines, networks), while modules are a way to encapsulate and reuse groups of resources. Modules allow you to organize and abstract portions of your Terraform configuration for better maintainability and reusability. Resources are the building blocks, and modules are the higher-level constructs that promote modularization and shareability of infrastructure code.

2. What is a recommended layout for a reusable module?

Show answer ```text\nmodules/vpc/\n main.tf\n variables.tf\n outputs.tf\n versions.tf\n README.md\n examples/\n basic/\n main.tf\n```

- `main.tf` defines resources, data sources, and locals.
- `variables.tf` contains typed inputs with descriptions and validations.
- `outputs.tf` exposes the minimal set of outputs downstream stacks need.
- `versions.tf` pins compatible Terraform and provider versions.
- `examples/` hosts runnable samples for documentation and testing, usually referenced by CI.

3. How to access module output variables?

Show answer The general syntax is `module..`

Remember: "Publishing to the Terraform Registry requires: GitHub repo, semantic version tags, and standard module structure."

4. What are Terraform modules and how do you use them?

Show answer Modules are reusable, self-contained packages of Terraform configurations.
They're the primary way to organize and reuse infrastructure code.

Structure:
```\nmodule/\nā”œā”€ā”€ main.tf # Resources\nā”œā”€ā”€ variables.tf # Input variables\nā”œā”€ā”€ outputs.tf # Output values\n└── README.md # Documentation\n```

Using a module:
```hcl
module "vpc" {
source = "./modules/vpc" # Local path
# Or: source = "terraform-aws-modules/vpc/aws" # Registry

vpc_cidr = "10.0.0.0/16"
environment = "production"
}

5. You would like to load and render a file from module directory. How to do that?

Show answer `templatefile("${path.module}/user-data.sh", { name = var.name })` loads and renders a template from the module directory. `${path.module}` resolves to the filesystem path of the module where the expression is defined, not the calling module. This ensures the template path works regardless of where the module is called from. Variables are passed as the second argument map.

6. True or False? Module source can be only local path

Show answer False. It can be a Git URL, HTTP URL, ... for example:

```\nmodule "some_module" {\n\n source = "github.com/foo/modules/bar?ref=v0.1"\n}\n```

Remember: "Module versioning: always pin versions in production." Without version pinning, terraform init may pull breaking changes.

🟔 Medium (16)

1. Aside from .tfvars files or CLI arguments, how can you inject dependencies from other modules?

Show answer The built-in terraform way would be to use `remote-state` to lookup the outputs from other modules.
It is also common in the community to use a tool called `terragrunt` to explicitly inject variables between modules.

Remember: "Module = reusable Terraform package." It has inputs (variables), outputs, and resources.

2. How do you use a Terraform module in your configuration?

Show answer The general syntax is:

```hcl\nmodule "" {\n source = ""\n version = ">= 1.2.0, < 2.0.0"\n\n # module inputs\n}\n```

The critical part is the source which you use to tell Terraform where the module can be found. When the module comes from the registry, you can pin the `version`; for local paths omit that attribute.

3. You are trying to use templatefile as part of a module and you use a relative path to load a file but sometimes it fails, especially when others try to reuse the module. How can you deal with that?

Show answer Switch relative paths with what is known as path references. These are fixes: paths like module root path, module expression file path, etc.

Remember: "Module sources: local (./), registry, GitHub, S3, GCS." Pin versions for registry modules.

4. How to use a module with for_each to create networks per availability zone?

Show answer ```hcl\nmodule "subnet" {\n source = "../modules/subnet"\n for_each = toset(var.azs)\n\n name = "subnet-${each.key}"\n az = each.value\n}\n```

`for_each` keeps addresses stable and lets you add or remove AZs without re-creating the entire module.

5. What should be done every time you modify the source parameter of a module?

Show answer Run `terraform init -upgrade` (or `terraform get -update` on older versions) so Terraform downloads the new version of the module and updates the `.terraform/modules` directory.

Remember: "Module outputs expose inner values to the caller." Access with module.NAME.OUTPUT.

6. Discuss the importance of "Terraform Modules" in promoting code reuse and maintainability.

Show answer Terraform Modules are crucial for:
* Code Reusability: Encapsulating and reusing configurations for different components.
* Maintainability: Simplifying maintenance by isolating functionality within modules.
* Abstraction: Providing an abstraction layer for hiding implementation details.
* Consistency: Ensuring consistency in resource configurations across environments.
* Collaboration: Facilitating collaboration by sharing and versioning modular code.

7. How do you consume a versioned module from a VCS or the Terraform Registry?

Show answer ```hcl\nmodule "vpc" {\n source = "git::https://github.com/org/infra-modules.git//vpc?ref=v1.2.3"\n cidr = "10.0.0.0/16"\n azs = ["us-east-1a", "us-east-1b"]\n}\n```

- For registry modules, use `version` constraints (for example `version = ">= 1.2.0, < 2.0.0"`).
- Always pin module versions to keep plans reproducible and review upstream releases before upgrading.
- Prefer tags or immutable SHAs for VCS sources to guarantee repeatable builds.

8. How do modules handle inputs, outputs, locals and validation effectively?

Show answer - Define typed variables with defaults and `validation` blocks to guard against invalid CIDRs, AZ counts, or empty strings.
- Use `locals` to transform data or derive names, and combine with `for_each`/`count` for deterministic resource creation.
- Document outputs in `outputs.tf`, mark sensitive ones, and keep outputs minimal to reduce coupling.
- Surface module metadata (like version or tags) through outputs for downstream modules or automation.

9. There is a module to create a compute instance. How would you use the module to create three separate instances?

Show answer starting with Terraform 0.13, the `count` meta-argument can be used with modules. So you could use something like this:

```\nmodule "instances" {\n source = "/some/module/path"\n\n count = 3\n}\n```

You can also use it in outputs vars: `value = module.instances[*]`

Remember: "Keep modules small and focused." One module per concern: networking, compute, database.

10. How do you manage and version control Terraform modules?

Show answer Managing and version controlling Terraform modules involves organizing them as separate directories or repositories. Best practices include:
* Repository per Module: Create a Git repository for each module.
* Semantic Versioning: Follow semantic versioning for module releases.
* Use Version Tags: Tag module releases for version control.
* Module Registry: Utilize Terraform Registry or private module registries for discoverability.
* Module Documentation: Include documentation with examples and usage guidelines.
* Dependencies: Declare module dependencies clearly in the module documentation.

11. How do you use a module in Terraform?

Show answer By calling it in your configuration with a module block, specifying the source (path, registry, or git URL) and passing input variables. For example:

```hcl\nmodule "vpc" {\n source = "terraform-aws-modules/vpc/aws"\n version = "3.5.0"\n cidr = "10.0.0.0/16"\n # ... other inputs\n}\n```

12. When should you use a module instead of inline resources?

Show answer - You need to reuse infrastructure patterns across environments, teams, or regions without copy-paste.
- You want to codify best practices (naming, tagging, security controls) behind a stable interface.
- You need to version and promote infrastructure changes using semantic releases and CI pipelines.
- You want to limit blast radius by updating one module and rolling it out gradually.

13. What are Terraform modules and how do they promote reuse?

Show answer [Terraform.io](https://www.terraform.io/language/modules/develop): "A module is a container for multiple resources that are used together. Modules can be used to create lightweight abstractions, so that you can describe your infrastructure in terms of its architecture, rather than directly in terms of physical objects."

In addition, modules are great for creating reusable Terraform code that can be shared and used not only between different repositories but even within the same repo, between different environments (like staging and production). Well-designed modules also expose a small, opinionated surface and hide implementation details.

14. Assuming you have multiple regions configured and you would like to use a module in one of them. How to achieve that?

Show answer ```\nmodule "some_module" {\n source = "..."\n\n providers = {\n aws = aws.some_region\n }\n\n ...\n}\n```

Gotcha: Nested module calls create deep dependency chains. Keep nesting to 2 levels max for readability.

15. When creating a module, do you prefer to use inline blocks, separate resources or both? why?

Show answer No right or wrong here.
Personally, I prefer to use only separate resources in modules as it makes modules more flexible. So if a resource includes inline blocks, that may limit you at some point.

16. Where can you obtain Terraform modules?

Show answer Terraform modules can be found at the [Terraform registry](https://registry.terraform.io/browse/modules)

Remember: "Modules don't inherit provider configuration." Pass providers explicitly or let them use the default.

šŸ”“ Hard (6)

1. Discuss the use of Terraform modules for code reusability and composability.

Show answer Terraform modules are reusable and composable components that encapsulate infrastructure configurations. They allow users to define and version a set of resources, making it easy to share, reuse, and maintain infrastructure code. Modules can represent higher-level abstractions or specific functionalities, enhancing code organization. For example, a "VPC module" could encapsulate networking configurations. Modules can be composed to create complex infrastructure by referencing them in other Terraform configurations, promoting modularity, maintainability, and consistency across projects.

2. You noticed there are relative paths in some of your modules and you would like to change that. What can you do and why is that a problem in the first place?

Show answer Relative paths usually work fine in your own environment as you are familiar with the layout and paths used, but when sharing a module and making it reusable, you may bump into issues as it runs on different environments where the relative paths may no longer be relevant.

A better approach would be to use `path reference` like one of the following:

- `path.module`: the path of the module where the expression is used
- `path.cwd`: the path of the current working directory
- `path.root`: the path of the root module

3. Which module anti-patterns should you avoid?

Show answer - Embedding provider blocks inside the module which makes reuse across accounts harder.
- Accepting overly generic `map(any)` inputs that hide required structure instead of typed objects.
- Outputting secrets or credentials without `sensitive = true` or secret stores.
- Creating "god" root modules that mix networking, compute, and application concerns instead of composing smaller modules.
- Copying and pasting modules without versioning, documentation, or automated tests.

4. What are the considerations for versioning Terraform modules, and how do you approach it?

Show answer Considerations for versioning Terraform modules include:
* Semantic Versioning: Follow SemVer for clear versioning conventions.
* Module Stability: Version modules based on stability and backward compatibility.
* Release Notes: Provide release notes to communicate changes between versions.
* Dependency Management: Clearly define dependencies and version constraints.
* Module Tagging: Tag Git or other VCS repositories with version information.
* Changelog Maintenance: Keep a well-maintained changelog for transparency.

5. Discuss the use of "Terraform Modules" for managing complex infrastructure deployments.

Show answer Terraform modules are reusable and shareable components that encapsulate infrastructure configurations. They are beneficial for managing complex deployments by:
* Abstraction: Providing a level of abstraction for infrastructure components.
* Reusability: Enabling reuse across different projects and environments.
* Consistency: Ensuring consistent configurations across deployments.
* Maintainability: Simplifying updates and changes to infrastructure.
* Scalability: Facilitating the scaling of deployments in a modular fashion.

6. How can you manage dependencies between Terraform modules in a complex infrastructure setup?

Show answer Managing module dependencies involves:
* Input Variables: Passing output variables of one module as input variables to another.
* Explicit Dependency Declaration: Clearly defining dependencies using Terraform syntax.
* Module Composition: Composing modules hierarchically to reflect dependencies.
* Terraform Remote State: Using remote state files to share outputs between modules.
* Versioned Modules: Ensuring that module versions are specified to maintain stability.