REusable Modules
Let us say you need to repeat a resource creation task (a set of resources) more than once. You may need to create those resources in two separate environments – dev and prod.
Or you may need to spin up an instance each in two separate regions (regional managed instance groups would only work across two zones in the SAME region).
Or, as another example, say you want to use code (modules) that already exists in github or on terraform’s public registry.
Creating a Module for local use
In my f5module folder, I have all of the terraform (main.tf and variables.tf) to spin up F5 instances in a particular environment. What that module (basically, any folder in terraform is a module), requires is a parent vpc, a region and gui_port, a couple of zones, a couple of static IPs and a NAT_IP. All these can be passed in as variables to the f5module, as shown below.
module "f5multiregional" { source ="./f5module" parent_vpc = var.parent_vpc region = var.region management_gui_port = var.management_gui_port zone1 = var.zone1 zone2 = var.zone2 staticIP_instance1 = google_compute_address.static1.address staticIP_instance2 = google_compute_address.static2.address subnet_id = google_compute_subnetwork.network-for-f5.id static_ip_nat = google_compute_address.staticnat.address }
The actual module code (the f5module folder containing main.tf and variables.tf)
resource "google_compute_instance_template" "f5-template" { name = "${var.environment}-f5-template" machine_type = "${var.instance_type}" network_interface { subnetwork = var.subnet_id access_config { nat_ip = var.static_ip_nat } } disk { source_image = "${var.image_name}" auto_delete = false disk_size_gb = 100 boot = true } # Shows up as network tags # Must be a match of regex '(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?) tags = [ "name-${var.environment}-shared-proxy", "environment-${var.environment}", "owner-${var.owner}", "group-${var.group}", "costcenter-${var.costcenter}", "application-${var.application}" ] metadata = { Name = "${var.environment}_proxy" environment = "${var.environment}" owner = "${var.owner}" group = "${var.group}" costcenter = "${var.costcenter}" application = "${var.application}" ssh-keys = "${var.admin_username}:${var.ssh_key_public}" } can_ip_forward = true } locals { instance1_bootstrap = templatefile("${path.module}/f5config1.sh", { admin_username = var.admin_username admin_password = var.admin_password }) instance2_bootstrap = templatefile("${path.module}/f5config2.sh", { admin_username = var.admin_username admin_password = var.admin_password }) } resource "google_compute_instance_from_template" "f5-instance-1" { name = "${var.environment}-${var.instance1_name}" zone = var.zone1 source_instance_template = google_compute_instance_template.f5-template.id scratch_disk { interface = "SCSI" } network_interface { subnetwork = var.subnet_id access_config { nat_ip = var.staticIP_instance1 } } metadata = { startup-script = local.instance1_bootstrap != "" ? local.instance1_bootstrap : local.instance1_bootstrap } service_account { scopes = ["userinfo-email", "compute-ro", "storage-ro"] } can_ip_forward = true } resource "google_compute_instance_from_template" "f5-instance-2" { name = "${var.environment}-${var.instance2_name}" zone = var.zone2 source_instance_template = google_compute_instance_template.f5-template.id scratch_disk { interface = "SCSI" } network_interface { subnetwork = var.subnet_id access_config { nat_ip = var.staticIP_instance2 } } metadata = { startup-script = local.instance2_bootstrap != "" ? local.instance2_bootstrap : local.instance2_bootstrap } service_account { scopes = ["userinfo-email", "compute-ro", "storage-ro"] } can_ip_forward = true } locals { api_url = "https://compute.googleapis.com/compute/v1/" instance1url = "${local.api_url}${google_compute_instance_from_template.f5-instance-1.id}" instance2url = "${local.api_url}${google_compute_instance_from_template.f5-instance-2.id}" } resource "google_compute_http_health_check" "default" { name = "f5healthcheck" request_path = "/" check_interval_sec = 1 timeout_sec = 1 } resource "google_compute_target_pool" "f5targetpool" { name = "instance-pool" instances = [ local.instance1url,local.instance2url ] health_checks = [ google_compute_http_health_check.default.name, ] } resource "google_compute_region_instance_group_manager" "f5-regional-group" { name = "f5-regional-instance-group" base_instance_name = "f5" region = var.region distribution_policy_zones = [var.zone1, var.zone2] version { instance_template = google_compute_instance_template.f5-template.id } target_pools = [google_compute_target_pool.f5targetpool.id] target_size = 2 named_port { name = "custom" port = 8888 } auto_healing_policies { health_check = google_compute_http_health_check.default.id initial_delay_sec = 300 } } output "instance1_url" { value = local.instance1url }
How else can Terraform Modules be leveraged?
There’s more to using terraform modules, but the use case above (using terraform modules locally), is a good way to get a basic understanding of terraform modules. Some other ways that modules can be leveraged include:
- Using terraform modules from the public registry
- Using Terraform module using GitHub
- Using a custom module
- Using Terraform’s module generator
Need an experienced Cloud Networking or a Cloud Data Protection Expert? Anuj has successfully delivered over a dozen deployments on each of the public clouds (AWS/GCP/Azure) including several DevSecOps engagements.
Next Steps?
Need help with your Terraform or PowerShell or other automation effort? Set up a free consultation – Start the conversation today.
Leave a Reply