1. 程式人生 > >Module 讓 Terraform 使用更簡單

Module 讓 Terraform 使用更簡單

眾所周知,Terraform 是一個開源的自動化的資源編排工具,支援多家雲服務提供商。阿里雲作為第三大雲服務提供商,terraform-alicloud-provider 已經支援了超過 90 多個 Resource 和 Data Source,覆蓋20多個服務和產品,吸引了越來越多的開發者加入到阿里雲Terraform生態的建設中。

隨著 Resource 和 DataSource 的不斷增加和完善,業務架構的不斷髮展,Terraform 模板編寫的成本和複雜度也在不斷的增加。如何讓Terraform 模板更加簡單和重用,就是本文所要解決的問題。

本文將通過一個典型的負載均衡架構,向大家介紹如何使用 Module 簡化 Terraform 的模板。

如圖所示,這個架構中,包含 ECS 例項,SLB 例項,RDS 例項,OSS 等資源和服務,同時所有的 ECS,RDS 和部分 SLB 在一個 VPC 網路環境中。

將所有Resource放在一個模板中進行統一管理

面對這樣的一個架構,模板可以有多種寫法。通常的寫法是將架構中涉及到的所有資源寫到一個模板中,並通過引數和關係型 resource 將這些資源關聯起來,如下所示:

// 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" {
  ...
}

這樣寫的好處是,所有資源都在一個模板中管理,編寫時可以很清楚瞭解資源之間的引用關係;但是,當資源不斷增加時,擴充套件非常不靈活,資源間關係越複雜,模板越難以維護。

分類管理,目錄作為單元化資源

從架構圖和上文模板中不難看出,並不是所有的Resource都有直接關聯關係,比如VPC只和VSwitch和SecurityGroup有關,與其他資源的建立無直接關聯關係。因此,為了使整個架構的邏輯可以更加清楚的展示在模板中,我們可以考慮,對資源進行分類,將每一類資源用一個單獨的目錄進行管理,最後用一個模板來管理所有的目錄,進而完成對所有資源及資源關係的串聯,如下所示:

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

將該架構中的資源分為網路(VPC),負載均衡(SLB),計算(ECS),資料庫(RDS)和儲存(OSS)這幾類,然後將上文模板中的資源分別在對應的目錄中予以實現。

接下來,用統一的模版main.tf將這些目錄關聯起來,如下所示:

// 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"
  ...
}

可以看出,main.tf中資源的結構更加清楚,更加接近於架構圖。

同時,大家已經注意到了,main.tf引入了一個 module,通過module將資源目錄串聯起來。

什麼是Module

Module 是 Terraform 為了管理單元化資源而設計的,是子節點,子資源,子架構模板的整合和抽象。正如本文架構中提到的,在實際複雜的技術架構中,涉及到的資源多種多樣,資源與資源之間的關係錯綜複雜,資源模版的編寫,擴充套件,維護等多個問題的成本都會不斷增加。將多種可以複用的資源定義為一個module,通過對 module 的管理簡化模板的架構,降低模板管理的複雜度,這就是module的作用。

除此之外,對開發者和使用者而言,只需關心 module 的 input 引數即可,無需關心module中資源的定義,引數,語法等細節問題,抽出更多的時間和精力投入到架構設計和資源關係整合上。

開源Module,使其更完善,更分享,更便捷

上文中,雖然已經實現了module,但是這個module只能在自己本地機器上實現,無法實現與他人的實時分享,無法實現團隊內部的及時共享。

Terraform 提供了 Module 的註冊地址,將自己的module上傳到Github,並註冊為一個Terraform Module後,即可將遠端的Module應用到我們自己的模板中。

利用開源 module,我們可對上文中的模板進行完善:

// 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" {
  source = "alibaba/slb/alicloud"
  ...
}
// SLB module(internet)
module "slb" {
  source = "alibaba/slb/alicloud"
  ...
}
// OSS module
module "rds" {
  source = "terraform-alicloud-modules/rds/alicloud"
  ...
}
// OSS module
module "oss" {
  source = "terraform-alicloud-modules/oss/alicloud"
  ...
}

Module 讓資源模板架構更清楚,模板管理更簡單;開源 Module 讓資源模板更便捷,更分享。除此之外,開源 Module 可實現對模板的版本控制,基於不同的版本,實現不同架構不斷升級的控制和完善。

歡迎加入 Terraform AliCloud Modules

目前我們已經在在 Terraform Module 上釋出了一些常用的 Module,但這些 Module 遠遠無法滿足大家多種多樣的技術架構和複雜的應用場景,非常歡迎大家可以將自己的模板Module註冊到官方 Module 上,藉助社群的力量,不斷完善自己模板,豐富我們的社群。

原文連結 本文為雲棲社群原創內容,未經允許不得轉載。