天天看點

Module 讓 Terraform 使用更簡單

衆所周知,Terraform 是一個開源的自動化的資源編排工具,支援多家雲服務提供商。阿裡雲作為第三大雲服務提供商, terraform-alicloud-provider

已經支援了超過 140 個 Resource 和 100 個 Data Source,覆寫30多個服務和産品,吸引了越來越多的開發者加入到阿裡雲Terraform生态的建設中。

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

本文将通過一個典型的負載均衡架構,向大家介紹如何使用 Module 簡化 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-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"
  ...
}           

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

歡迎加入 Terraform AliCloud Modules

目前我們已經在在 Terraform Module 上釋出了一些

常用的 Module

,但這些 Module 遠遠無法滿足大家多種多樣的技術架構和複雜的應用場景,非常歡迎大家可以将自己的模闆Module注冊到官方 Module 上,借助社群的力量,不斷完善自己模闆,豐富我們的社群。

繼續閱讀