乐趣区

关于云计算: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 是被调用模块的地址。prefixcontent 都是入参,之前曾经定义了。

在根模块也能够定义输入变量:

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…

比方我援用了(https://registry.terraform.io…)这个模块:

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…

退出移动版