terribly中文翻译(《Terraform 101 从入门到实践》 第三章 Modules模块化)
《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新 ,书中的示例代码也是放在GitHub上 ,方便大家参考查看 。
模块的概念
模块化是Terraform实现代码重用的方式 。模块可以理解为一个包含多个资源的容器模板 。封装好之后 ,可以给大家使用 。也可以理解为代码中的函数或方法 ,它接收入参 ,经过一些声明式的调用后 ,输出一些结果变量 。
从Terraform的代码层面来看 ,模块其实就是一个包含多个.tf或.tf.json文件的目录 。任何一个Terraform项目 ,都是一个目录 ,所以也都是一个模块 ,我们把它称为根模块(Root Module) 。而在它目录下的其它模块 ,都是子模块 。我们可以调用多个模块 ,也可以多次调用同一个子模块 。在子模块中,也可以调用其它模块 。这些特点 ,与函数无异 。
调用模块有两种方式 ,一种是在当前项目定义一个模块,另一种是引入外部的模块 。而外部模块的方式也很多种 ,如Git的仓库 、压缩文件等。
定义并使用模块
我们先来使用第一种方式 ,引用当前项目中的模块 。
子模块的功能很简单 ,创建一个文件 ,文件名有随机字符串 ,以避免冲突 。写入文件的内容可以通过参数指定。
子模块:
定义入参:创建一个文件叫variables.tf ,专门用来定义入参:
variable "prefix" { type = string default = "pkslow" description = "File name prefix" } variable "content" { type = string default = "www.pkslow.com" description = "File content" }这里输入有两个变量 ,都是字符串类型 ,分别是文件名前缀prefix和文件内容context 。
定义模块功能 ,主要配置这个模块用管理的资源 ,一般会放在main.tf文件中 ,内容如下:
resource "random_string" "random" { length = 6 lower = true special = false } resource "local_file" "file" { content = var.content filename = "${path.root}/${var.prefix}.${random_string.random.result}.txt" }这里定义了两个resource ,第一个是生成6位的随机字符串 。第二个是生成一个文件,第二个resource使用了输入参数 ,还使用了第一个资源生成的结果 。所以第二个resource是依赖于第一个的 。输入的变量引用方式为var.xxx 。
定义返回值:
可以不需要返回值 ,也可以定义一个或多个返回值 。创建一个outputs.tf文件,内容如下:
output "file_name" { value = local_file.file.filename }它返回的是前面第二个resource中的值 。
现在 ,模块random-file已经定义完成了 。现在我们在根模块调用这个子模块 。代码如下:
module "local-file" { source = "./random-file" prefix = "pkslow" content = "Hi guys, this is www.pkslow.com\nBest wishes!" }这个source是被调用模块的地址 。prefix和content都是入参 ,之前已经定义了 。
在根模块也可以定义输出变量:
output "fileName" { value = module.local-file.file_name }这里直接输出子模块的文件名 ,也就是子模块的返回变量file_name 。
apply后通过terraform output查看输出:
$ terraform output fileName = "./pkslow.B2UwmR.txt"多个block调用同一个module
我们说过模块是为了实现代码复用 ,Terraform允许一个模块被多次调用。我们修改根模块的调用代码:
module "pkslow-file" { source = "./random-file" prefix = "pkslow" content = "Hi guys, this is www.pkslow.com\nBest wishes!" } module "larry-file" { source = "./random-file" prefix = "larrydpk" content = "Hi guys, this is Larry Deng!" }这里两个调用的source都是一样的 ,都调用了random-file这个模块 ,只是入参不同 。
根模块的输出也修改一下:
output "pkslowPileName" { value = module.pkslow-file.file_name } output "larryFileName" { value = module.larry-file.file_name }执行apply后output输出结果为:
$ terraform output larryFileName = "./larrydpk.txoV34.txt" pkslowPileName = "./pkslow.WnJVMm.txt"循环调用一个module
count方式
多次调用一个模块还有另一种方式就是循环调用 ,通过count来实现 ,具体如下:
module "pkslow-file" { count = 6 source = "./random-file" prefix = "pkslow-${count.index}" content = "Hi guys, this is www.pkslow.com\nBest wishes!" }这里会调用6次子模块random-file ,下标索引为count.index ,它是从0开始的索引 。
因此 ,执行后 ,会生成以下6个文件:
pkslow-0.JBDuhH.txt pkslow-1.Z6QmPV.txt pkslow-2.PlCK5u.txt pkslow-3.a70sWN.txt pkslow-4.UnxYue.txt pkslow-5.8bSNxg.txt这里根模块的输出就需要修改了,它成了一个List ,通过*引用所有元素:
output "pkslowPileNameList" { value = module.pkslow-file.*.file_name }for each方式
通过for_each也可以实现循环调用:
Map的情况:
resource "azurerm_resource_group" "rg" { for_each = { a_group = "eastus" another_group = "westus2" } name = each.key location = each.value }Set的情况:
resource "aws_iam_user" "the-accounts" { for_each = toset( ["Todd", "James", "Alice", "Dottie"] ) name = each.key }引用外部模块
除了在本项目中定义并引用模块之外 ,还可以引用外部的模块。在官方的仓库中已经有非常多的可重用的模块了,可以到上面查找:https://registry.terraform.io/browse/modules
比如我引用了( https://registry.terraform.io/modules/matti/resource/shell/latest )这个模块:
module "echo-larry-result" { source = "matti/resource/shell" version = "1.5.0" command = "cat ${module.larry-file.file_name}" }执行terraform get会从仓库下载模块:
$ terraform get Downloading matti/resource/shell 1.5.0 for echo-larry-result... - echo-larry-result in .terraform/modules/echo-larry-result - larry-file in random-file - pkslow-file in random-file在.modules目录下可以查看模块内容 。
这个模块可以执行shell命令 ,并返回结果 。我这里执行的命令是读取之前生成文件的内容 。输出调用结果:
output "larryFileResult" { value = module.echo-larry-result.stdout }执行结果如下:
larryFileName = "./.result/larrydpk.GfgMyh.txt" larryFileResult = "Hi guys, this is Larry Deng!"模块来源
引入模块的来源很多:
本地目录 Terraform官方仓库 GitHub或其它Git仓库 Bitbucket HTTP URLs S3 Buckets GCS Bucket非常方便 。我们已经介绍过比较常用的前两种了 ,其它更多细节可以参考:https://www.terraform.io/docs/language/modules/sources.html
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!