pkslow.com 南瓜慢说

  • AllArticles
  • Container
  • Spring
  • Life
  • Cloud
  • Collections
  • About
  • GitHub

  • Search
App Terraform101 English Terraform Middleware config Go Private Kubernetes pkslow Test HTTPS Redis Docker Mac Plan Stream MongoDB Spring DevOps JVM String Map Set List Performance Email Springboot JavaCollections ArrayList Java

《Terraform 101 从入门到实践》 第三章 Modules模块化

Created on: 2022-01-13 | Category: Cloud | 0 | View: 385

《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来实现,具体如下:

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
}

引用外部模块

除了在本项目中定义并引用模块之外,还可以引用外部的模块。在官方的仓库中已经有非常多的可重用的模块了,可以到上面查找: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


参考:

https://www.terraform.io/docs/language/meta-arguments/count.html

https://stackoverflow.com/questions/64989080/terraform-modules-output-from-for-each


Code for all: GitHub

欢迎关注微信公众号<南瓜慢说>,将持续为你更新...

file

Recommendations:
Cloud Native
Terraform
Container: Docker/Kubernetes
Spring Boot / Spring Cloud
Https
如何制定切实可行的计划并好好执行

  • Author 作者: LarryDpk 南瓜慢说
  • Link 链接: https://www.pkslow.com/archives/terraform-101-modules
  • 版权声明: 本博客所有文章除特别声明外,不可转载!
# App # Terraform101 # English # Terraform # Middleware # config # Go # Private # Kubernetes # pkslow # Test # HTTPS # Redis # Docker # Mac # Plan # Stream # MongoDB # Spring # DevOps # JVM # String # Map # Set # List # Performance # Email # Springboot # JavaCollections # ArrayList # Java
App Terraform101 English Terraform Middleware config Go Private Kubernetes pkslow Test HTTPS Redis Docker Mac Plan Stream MongoDB Spring DevOps JVM String Map Set List Performance Email Springboot JavaCollections ArrayList Java
在GCP上创建GCE的三种方式(Console,gcloud,Terraform)
《Terraform 101 从入门到实践》 第二章 Providers插件管理
  • Contents
  • Site Overview
南瓜慢说

南瓜慢说

多年Java开发,主要专注后端技术:Java/Spring/Springboot/微服务/大数据等。

多读书,多分享;多写作,多整理。

243 Posts
9 Categories
31 Tags
RSS
0%
© 2020 — 2022 南瓜慢说 pkslow The WebSite keeping alive:   粤ICP备20036375号