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