更新时间:2022-02-10 GMT+08:00

Modules

一个Terraform配置文件中通常包含多个Resource,Data Source以及变量,为了简化配置和降低维护复杂度,Terraform提供了Modules功能。Module相当于一个Terraform模块,是对多个资源的封装及抽象。

调用模块

在配置文件中声明 module块从可以调用module,其语法如下:

module "child_module" {
  source = "./child"
  ...
}

一个 module块包含关键字、module名称和块主体三个部分,块主体中需要指定source以及module中定义的输入变量等参数。在添加 module块之后,需要通过 "terraform init" 命令将模块代码的副本保存至工作目录下。在修改或删除 module块后,也必须重新运行 "terraform init" 命令以更新相应的配置。

source 是 module 中的必选参数,用于指向包含模块配置文件的源路径。Terraform 支持使用以下源路径:

  • 本地路径

    本地路径必须以 "./" 或 "../" 开头,如 "./child","../parent"等。

  • GitHub

    Terraform将以下路径解析为GitHub仓库:

    # 使用Https协议克隆
    module "myvpc" {
      source = "github.com/terraform-huaweicloud-modules/terraform-huaweicloud-vpc.git"
      ...
    }
    
    # 使用SSH协议克隆
    module "myvpc" {
      source = "git@github.com:terraform-huaweicloud-modules/terraform-huaweicloud-vpc.git"
      ...
    }

    默认情况下,Terraform将克隆仓库的master分支。如选择其他分支或版本,需要在路径中指定ref参数,例如:

    module "myvpc" {
      source = "github.com/terraform-huaweicloud-modules/terraform-huaweicloud-vpc.git?ref=v1.0.0"
      ...
    }
  • 通用Git仓库
    Terraform将以 "git::" 开头的路径解析为通用Git仓库,支持Https和SSH协议克隆仓库,支持指定分支或版本。
    module "myvpc" {
      source = "git::https://example.com/vpc.git"
    }
    
    module "mystorage" {
      source = "git::ssh://username@example.com/storage.git"
    }
    
    module "myvpc" {
      source = "git::https://example.com/vpc.git?ref=v1.2.0"
    }
  • OBS/S3桶

    Terraform将以 "s3::" 开头的路径解析为OBS/S3存储桶,例如:

    module "myvpc" {
      source = "s3::https://mybucket.obs.cn-north-1.myhuaweicloud.com/myproject/vpc-example.zip
    }
    示例中,使用了mybucket桶中的myproject/vpc-example.zip对象作为module的源路径。使用OBS/S3桶之前,需要进行认证,将AK/SK导出为环境变量:
    $ export AWS_ACCESS_KEY_ID="******"
    $ export AWS_SECRET_ACCESS_KEY="******"
  • HTTP URL

    当源路径为HTTP或HTTPs的URL时,Terraform将向给定的URL发送GET请求并下载对应的文件。我们也可以通过HTTP URL的形式来访问OBS桶中的对象,将对象的访问策略设置为公共读,然后使用对应的endpoint链接即可:

    module "myvpc" {
      source = "https://mybucket.obs.cn-north-1.myhuaweicloud.com/myproject/vpc-example.zip"
    }

访问模块的输出变量

由于模块是对资源的封装和抽象,我们不能直接访问模块中定义的资源属性,只能访问模块中定义的输出变量,格式为 "module.<MODULE NAME>.<OUTPUT NAME>"。我们采用本地路径源的方式进行说明,首先在工作目录的 "./modules/network" 路径下定义模块,创建一个VPC,并输出VPC ID,内容如下:

variable "mycidr" {
  type    = string
  default = "192.168.0.0/16"
}

resource "huaweicloud_vpc" "vpc" {
  name = "vpc_demo"
  cidr = var.mycidr
}

output "vpc_id" {
  value = huaweicloud_vpc.vpc.id
}

在工作目录中调用该模块,并在VPC下新增一个子网,此时 vpc_id 的值需要用 "module.network.vpc_id”来表示。

module "network" {
  source = "./modules/network"
}

resource "huaweicloud_vpc_subnet" "subnet" {
  name       = "subnet_new"
  cidr       = "192.168.12.0/24"
  gateway_ip = "192.168.12.1"
  vpc_id     = module.network.vpc_id
  dns_list   = ["100.125.1.250","100.125.129.250"]
}

通过Module对输出值的使用隐藏了资源实现的细节,父模块无需关心子模块的具体实现,也不会改变子模块的模块和结构。此方式不仅避免了外部错误对资源的影响,同时也降低了模块之间的耦合度。