×
Community Blog Modules That Make Terraform Easier to Use

Modules That Make Terraform Easier to Use

Learn how you can use modules to simplify Terraform templates through a typical load balancing architecture.

By He Guimin, nicknamed Xiaozhu at Alibaba.

Terraform is an open-source automated resource orchestration tool that supports multiple cloud service providers. Alibaba Cloud is the third largest cloud service provider in the world. Terraform Alibaba Cloud Modules already support more than 140 resources and 100 data sources across more than 30 products and services, drawing more developers to join the Alibaba Cloud Terraform ecosystem.

With the continuous increase and further improvements in resources and data sources, as well as the continuous development of business architecture, the cost and complexity of Terraform template creation is also increasing. In this article, we're going to show you how you can use modules to simplify Terraform templates through a typical load balancing architecture.

1

As shown in the figure, this architecture includes Alibaba Cloud resources and services such as Elastic Compute Service (ECS) instances, Server Load Balancer (SLB) instances, ApsaraDB for RDS (RDS) instances, and Object Storage Service (OSS). All ECS instances, RDS instances, and some SLB instances are in the same Virtual Private Cloud (VPC) network.

Writing All Resources into One Template for Unified Management

For such an architecture, a template can be written in multiple ways. The common way is to write all the resources involved in the architecture into a template and to associate these resources through parameters and relational resources, as follows:

// Images data source for image_id
data "alicloud_images" "default" {
  ...
}
// Instance_types data source for instance_type
data "alicloud_instance_types" "default" {
  ...
}
// Zones data source for availability_zone
data "alicloud_zones" "default" {
  ...
}
// A new VPC
resource "alicloud_vpc" "vpc" {
    name = "default"
    ...
}
// Two new VSwitches
resource "alicloud_vswitch" "vswitches" {
  count             = 2
  vpc_id            = "${alicloud_vpc.vpc.id}"
  ...
}
// A new Security Group
resource "alicloud_security_group" "default" {
  vpc_id = "alicloud_vpc.vpc.id}"
  ...
}
// Two Web Tier instances
resource "alicloud_instance" "web" {
  count           = 2
  image_id        = "data.alicloud_images.default.images.0.id"
  instance_type   = "data.alicloud_instance_types.default.instance_types.0.id"
  security_groups = ["${ alicloud_security_group.default.id }"]
  vswitch_id = "${element(alicloud_vswitch.vswitches.*.id, count.index)}"
  ...
}
// Two Application Tier instances
resource "alicloud_instance" "app" {
  count           = 2
  image_id        = "${data.alicloud_images.default.images.0.id}"
  instance_type   = "${data.alicloud_instance_types.default.instance_types.0.id}"
  security_groups = ["${alicloud_security_group.default.id}"]
  vswitch_id = "${element(alicloud_vswitch.vswitches.*.id, count.index)}"
  ...
}
// A SLB Instance for intranet
resource "alicloud_slb" "intranet" {
  internet = false
  vswitch_id = "${alicloud_vswitch.vswitches.0.id}"
  ...
}
// Attach Ecs instances
resource "alicloud_slb_attachment" "intranet" {
  load_balancer_id = "${alicloud_slb.intranet.id}"
  instance_ids     = ["${alicloud_instance.web.*.id}", "${alicloud_instance.app.*.id}"]
}
// SLB Instance Resource for internet
resource "alicloud_slb" "internet" {
  internet  = true
  ...
}
// Attach Ecs instances
resource "alicloud_slb_attachment" "internet" {
  load_balancer_id = "${alicloud_slb.internet.id}"
  instance_ids     = ["${alicloud_instance.web.*.id}"]
}
// Two RDS Instance
resource "alicloud_db_instance" "default" {
  count            = 2
  vswitch_id = "${element(alicloud_vswitch.vswitches.*.id, count.index)}"
  ...
}
// Add a account for each RDS instance
resource "alicloud_db_account" "default" {
  count       = 2
  instance_id = "${element(alicloud_db_instance.default.*.id, count.index)}"
  ...
}
// Add a database for each RDS instance
resource "alicloud_db_database" "default" {
  count       = 2
  instance_id = "${element(alicloud_db_instance.default.*.id, count.index)}"
  ...
}
// A OSS Bucket
resource "alicloud_oss_bucket" "default" {
  ...
}

By doing so, you can manage your all resources in one template so that you can clearly understand the reference relationships among these resources. However, as the number of your resources continue to increase, the scaling of such an architecture can be difficult. The more complex the relationships among resources are, the more difficult it is to maintain templates.

Category-Based Management, with Directories Used as Unit Resources

From the diagram and template of this preceding architecture diagram, we can see that not all resources have direct associations. For example, the VPC is only related to the VSwitch and security group, and is not directly associated with the creation of other resources. Therefore, to clearly display the logic of the entire architecture in the template, you can consider classifying resources and managing each type of resource by using a separate directory. Finally, you can use a template to manage all directories and then connect all resources and resource relationships, as shown in the following example:

├── main.tf
├── variables.tf
├── outputs.tf
├── modules/
│   ├── vpc/
│   │   ├── variables.tf
│   │   ├── main.tf
│   │   ├── outputs.tf
│   ├── slb/
│   │   ├── variables.tf
│   │   ├── main.tf
│   │   ├── outputs.tf
│   ├── ecs/
│   ├── rds/
│   ├── oss/

The resources in this architecture are divided into the following categories: network (VPC), load balancing (SLB), computing (ECS), database (RDS), and storage (OSS). Then, the resources in the preceding template are implemented in their corresponding directories.

Next, you can use the main.tf template to associate these directories as follows:

// VPC module
module "vpc" {
  source = "./modules/vpc"
  name = "new-netwtok"
  ...
}
// Web Tier module
module "web" {
  source = "./modules/ecs"
  instance_count = 2
  vswitch_ids = "${module.vpc.this_vswitch_ids}"
  ...
}
// Web App module
module "app" {
  source = "./modules/ecs"
  instance_count = 2
  vswitch_ids = "${module.vpc.this_vswitch_ids}"
  ...
}
// SLB module(intranet)
module "slb" {
  source = "./modules/slb"
  name = "slb-internal"
  vswitch_id = "${module.vpc.this_vswitch_ids.0.id}"
  instances = "${concat(module.web.instance_ids, module.app.instance_ids,)}"
  ...
}
// SLB module(internet)
module "slb" {
  source = "./modules/slb"
  name = "slb-external"
  internet = true
  instances = "${module.web.instance_ids}"
  ...
}
// RDS module
module "oss" {
  source = "./modules/rds"
  name = "new-rds"
  ...
}
// OSS module
module "oss" {
  source = "./modules/oss"
  name = "new-bucket"
  ...
}

As you can see, the resource structure in main.tf is clearer and closer to that shown in the architecture diagram we introduced at the beginning of this post. At the same time, you probably also noticed that main.tf introduced a module that connects the resource directories.

What is a Module?

Modules are designed to manage unitized resources in Terraform. Modules are small, reusable Terraform configurations that let you manage a group of related resources as if they were a single resource. As mentioned in the architecture section of this article, various issues exist in the actual complex technical architecture, such as various types of resources, complex resource relationships, and writing, expansion, and maintenance of resource templates. These issues lead to continuous increases in costs. Multiple reusable resources can be defined as a module. Modules can be used to simplify the template architecture and reduce the complexity of template management.

In addition, developers and users only need to care about the input parameters of modules, and do not need to care about details such as the resource definitions, parameters, and syntax in modules. In this way, they can allocate more time and energy to architecture design and resource relationship integration.

Open-Source Modules: Improved, Shareable, and Convenient

In the above section, although the module has been implemented, this module can be implemented only on its corresponding local machine, but cannot be shared with others in real time or within the team in a timely manner.

Terraform provides the Terraform Registry for module registration. After uploading your module to GitHub and registering it as a Terraform module, you can apply this remote module to your own template.

By using an open-source module, we can improve the preceding template:

// VPC module
module "vpc" {
  source = "alibaba/vpc/alicloud"
  ...
}
// Web Tier module
module "web" {
  source = "alibaba/ecs-instance/alicloud"
  ...
}
// Web App module
module "app" {
  source = "alibaba/ecs-instance/alicloud"
  ...
}
// SLB module(intranet)
module "slb-intranet" {
  source = "alibaba/slb/alicloud"
  ...
}
// SLB module(internet)
module "slb-internet" {
  source = "alibaba/slb/alicloud"
  ...
}
// OSS module
module "rds" {
  source = "terraform-alicloud-modules/rds/alicloud"
  ...
}
// OSS module
module "oss" {
  source = "terraform-alicloud-modules/oss/alicloud"
  ...
}

Modules make the resource template architecture clearer and template management easier. And, open-source modules makes resource templates more convenient and shareable. Moreover, they can also implement version control of templates, and control and improve continuous upgrades of different architectures based on different versions.

Join Terraform Alibaba Cloud Modules

We have already published some common Modules on the Terraform Registry. However, these modules are far from meeting the needs of various technical architectures and complex application scenarios. You are welcome to register your modules and templates on the Terraform Registry. With the help of the Terraform community, we are able to constantly improve our own templates and enrich our community.

The views expressed herein are for reference only and don't necessarily represent the official views of Alibaba Cloud.

0 0 0
Share on

Alibaba Clouder

2,605 posts | 747 followers

You may also like

Comments