Advanced Terraform Module Usage: Versioning, Nesting, and Reuse Across Environments
🎯 This article, will explain in detail how to advanced concepts of working with modules, including how to manage versioning, use nested modules, and reuse modules🎯
🌈Synopsis:
🌞Understanding of Terraform modules and learn how to manage modules across different versions and environments.
🌈Module Versioning:
🌞If both your staging and production environment are pointing to the same module folder, as soon as you make a change in that folder, it will affect both environments on the very next deployment. This sort of coupling makes it more difficult to test a change in staging without any chance of affecting production. A better approach is to create versioned modules so that you can use one version in staging (e.g., v0.0.2) and a different version in production (e.g., v0.0.1)
🌞The easiest way to create a versioned module is to put the code for the module in a separate Git repository and to set the source parameter to that repository’s URL.
🌞To set up this folder structure, you’ll first need to move the stage, prod, and global folders into a folder called live. Next, configure the live and modules folders as separate Git repositories
Example of how to do that for the modules folder
$ cd modules
$ git init
$ git add .
$ git commit -m "Initial commit of modules repo"
$ git remote add origin "(URL OF REMOTE GIT REPOSITORY)"
$ git push origin main
🌞You can also add a tag to the modules repo to use as a version number. If you’re using GitHub
$ git tag -a "v0.0.1" -m "First release of webserver-cluster module"
$ git push --follow-tags
🌞Now you can use this versioned module in both staging and production by specifying a Git URL in the source parameter. Here is what that would look like in live/stage/services/webserver-cluster/main.tf
module "webserver_cluster" {
source = "github.com/foo/modules//services/webserver-cluster?ref=v0.0.1"
cluster_name = "webservers-stage"
db_remote_state_bucket = "(YOUR_BUCKET_NAME)"
db_remote_state_key= "stage/data-stores/mysql/terraform.tfstate"
instance_type = "t2.micro"
min_size= 2
max_size= 2
}
🌞Let’s say you made some changes to the webserver-cluster module, and you want to test them out in staging. First, you’d commit those changes to the modules repo:
$ cd modules
$ git add .
$ git commit -m "Made some changes to webserver-cluster"
$ git push origin main
Next, you would create a new tag in the modules repo:
$ git tag -a "v0.0.2" -m "Second release of webserver-cluster"
$ git push --follow-tags
🌞And now you can update just the source URL used in the staging environment (live/ stage/services/webserver-cluster/main.tf) to use this new version
module "webserver_cluster" {
source = "github.com/foo/modules//services/webserver-cluster?ref=v0.0.2"
cluster_name = "webservers-stage"
db_remote_state_bucket = "(YOUR_BUCKET_NAME)"
db_remote_state_key = "stage/data-stores/mysql/terraform.tfstate"
instance_type = "t2.micro"
min_size = 2
max_size = 2
}
🌞In production (live/prod/services/webserver-cluster/main.tf), you can happily continue to run v0.0.1 unchanged
module "webserver_cluster" {
source = "github.com/foo/modules//services/webserver-cluster?ref=v0.0.1"
cluster_name= "webservers-prod"
db_remote_state_bucket = "(YOUR_BUCKET_NAME)"
db_remote_state_key = "prod/data-stores/mysql/terraform.tfstate"
instance_type = "m4.large"
min_size = 2
max_size = 2
}
🌞 After v0.0.2 has been thoroughly tested and proven in staging, you can then update production, too. But if there turns out to be a bug in v0.0.2, no big deal, because it has no effect on the real users of your production environment. Fix the bug, release a new version, and repeat the entire process again until you have something stable enough for production.
🌈Module Scope:
🌞Modules are simply terraform configuration files that have optional/required inputs and will return specified number of outputs. The configuration within the module can be akin to a black box, as the module is abstracting away the configuration blocks that it contains.
🌞Variables can be declared in a module. In order to calla module with variables, you will need to declare those variables in the root module as well. If done correctly, there will be a set of variables declared in a child module and a corresponding set declared in the root module
🌈Terraform module - Public registry:
🌞Hashicorp maintains a public registry that helps you to consume Terraform modules from others. The Terraform Public Registry is an index of modules shared publicly and is the easiest way to get started with Terraform and find modules created by others in the community. It includes support for module versioning and a searchable and filterable list of available modules for quickly deploying common infrastructure configurations.
Publishing to the Terraform Public Module Registry:
The module must be on GitHub and must be a public repo. This is only a requirement for the public registry.
Module repositories must use a naming format: terraform--where reflects the type of infrastructure the module manages and is the main provider where it creates that infrastructure.
The module repository must have a description which is used to populate the short description of the module.
The module must adhere to the standard module structure, main. tf, variables.tf, outputs.tf. This allows the registry to inspect your module and generate documentation
x.y.z tags for releases. The registry uses tags to identify module versions. Release tag names must be a semantic version, which can optionally be prefixed with a v. For example,v1.0.4 and 0.9.2.
🕵🏻I also want to express that your feedback is always welcome. As I strive to provide accurate information and insights, I acknowledge that there’s always room for improvement. If you notice any mistakes or have suggestions for enhancement, I sincerely invite you to share them with me.
🤩 Thanks for being patient and following me. Keep supporting 🙏
Clap👏 if you liked the blog.
For more exercises — please follow me below ✅!
https://vjraghavanv.hashnode.dev/
#aws #terraform #cloudcomputing #IaC #DevOps #tools #operations #30daytfchallenge #HUG #hashicorp #HUGYDE #IaC #developers #awsugmdu #awsugncr #automatewithraghavan
Subscribe to my newsletter
Read articles from vijayaraghavan vashudevan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
vijayaraghavan vashudevan
vijayaraghavan vashudevan
I'm Vijay, a seasoned professional with over 13 years of expertise. Currently, I work as a Quality Automation Specialist at NatWest Group. In addition to my employment, I am an "AWS Community Builder" in the Serverless Category and have served as a volunteer in AWS UG NCR Delhi and AWS UG MDU, a Pynt Ambassador (Pynt is an API Security Testing tool), and a Browserstack Champion. Actively share my knowledge and thoughts on a variety of topics, including AWS, DevOps, and testing, via blog posts on platforms such as dev.to and Medium. I always like participating in intriguing discussions and actively contributing to the community as a speaker at various events. This amazing experience provides me joy and fulfillment! 🙂