首页IT科技terrible horrible(《Terraform 101 从入门到实践》 第五章 HCL语法)

terrible horrible(《Terraform 101 从入门到实践》 第五章 HCL语法)

时间2025-07-07 03:05:09分类IT科技浏览4124
导读:《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新,书中的示例代码也是放在GitHub上,方便大家参考查看。...

《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新             ,书中的示例代码也是放在GitHub上                   ,方便大家参考查看             。

介绍了Terraform一些比较基础的概念后      ,我们可以先了解一下Terraform的语法             ,也就是HCL的语法                   。

变量Variables

变量是实现代码复用的一种方式                   ,同样的代码不同的变量往往会有不同的效果      。而在Terraform里      ,有一个概念非常重要       ,就是变量都是从属于模块的       。变量无法跨模块引用                   。即在模块A定义的变量X                   ,无法在模块B中直接引用            。但父模块的变量             ,可以作为子模块的入参;而子模块的输出变量可以被父模块获取       。

变量类型

从语言角度

跟任何编程语言一样       ,变量都是有类型的                   ,Terraform的变量类型从语言的角度可分为两大类:基本类型和组合类型             ,具体如下:

基本类型:

字符串string,如"pkslow.com" 数字number                   ,如319或5.11 布尔值bool                   ,如true

组合类型:

列表list(),如["dev", "uat", "prod"] 集合set()             ,如set(...) 映射map()                   ,如{name="Larry", age="18"} 对象object({name1=T1, name2=T2}) 元组tuple([T1,T2,T3...])

如果不想指定某个类型      ,可以用any来表示任意类型;或者不指定             ,默认为任意类型                    。

从功能角度

从功能角度来看                   ,变量可以分为输入变量             、输出变量和本地变量            。

输入变量是模块接收外部变量的方式      ,它定义在variable块中       ,如下:

variable "image_id" { type = string } variable "availability_zone_names" { type = list(string) default = ["us-west-1a"] } variable "docker_ports" { type = list(object({ internal = number external = number protocol = string })) default = [ { internal = 8300 external = 8300 protocol = "tcp" } ] }

输出变量定义了一个模块对外返回的变量                   ,通过output块来定义             ,如下:

output "instance_ip_addr" { value = aws_instance.server.private_ip }

本地变量是模块内定义且可引用的临时变量       ,在locals块中定义                   ,如下:

locals { service_name = "forum" owner = "Community Team" }

输入变量Input Variable

输入变量是定义在variable块中的             ,它就像是函数的入参。

定义输入变量

定义variable有很多可选属性:

类型type:指定变量是什么类型;如果没有指定,则可以是任意类型; 默认值default:变量的默认值                   ,定义后可以不用提供变量的值                   ,注意它的值的类型要与type对应上; 说明description:说明这个变量的作用和用途; 校验validation:提供校验逻辑来判断输入的变量是否合法; 敏感性sensitive:定义变量是否敏感,如果是则不会显示;默认为false; 可空nullable:如果为true则可以为空             ,否则不能                    。默认为true                   。

所有属性都显性指定如下面例子所示:

variable "env" { type = string default = "dev" description = "environment name" sensitive = false nullable = false validation { condition = contains(["dev", "uat", "prod"], var.env) error_message = "The env must be one of dev/uat/prod." } }

这个变量名为env                   ,表示环境名      ,默认值为dev             ,这个值必须为dev                   、uat和prod中的其中一个。如果输出一个非法的值                   ,会报错:

$ terraform plan -var="env=sit" ╷ │ Error: Invalid value for variable │ │ on input.tf line 1: │ 1: variable "env" { │ │ The env must be one of dev/uat/prod.

使用输入变量

只有定义了变量才可以使用      ,使用的方式是var.name             。比如这里定义了两个变量env和random_string_length:

variable "env" { type = string default = "dev" } variable "random_string_length" { type = number default = 10 }

则使用如下:

resource "random_string" "random" { length = var.random_string_length lower = true special = false } locals { instance_name = "${var.env}-${random_string.random.result}" } output "instance_name" { value = local.instance_name }

传入变量到根模块

要从外部传入变量到根模块       ,有多种方式                   ,常见的有以下几种             ,按优先级从低到高:

环境变量export TF_VAR_image_id=ami-abc123

terraform.tfvars文件;

terraform.tfvars.json文件;

*.auto.tfvars或*.auto.tfvars.json文件;

命令行参数-var传入一个变量;命令行参数-var-file传入一个变量的集合文件;

在实践中       ,最常用的还是通过命令行来传入参数                   ,因为一般需要指定不同环境的特定变量             ,所以会把变量放到文件中,然后通过命令行指定特定环境的主文件:

$ terraform apply -var="env=uat" $ terraform apply -var-file="prod.tfvars"

而prod.tfvars的内容如下:

env = "prod" random_string_length = 12

我们可以定义dev.tfvars      、uat.tfvars和prod.tfvars等                   ,要使用不同环境的变量就直接改变文件名即可                   。

输出变量Output Variable

有输入就有输出                   ,输出变量就像是模块的返回值,比如我们调用一个模块去创建一台服务             ,那就要获取服务的IP                   ,这个IP事先是不知道      ,它是服务器创建完后的结果之一      。输出变量有以下作用:

子模块的输出变量可以暴露一些资源的属性; 根模块的输出变量可以在apply后输出到控制台; 根模块的输出变量可以通过remote state的方式共享给其它Terraform配置             ,作为数据源             。

定义输出变量

输出变量需要定义在output块中                   ,如下:

output "instance_ip_addr" { value = aws_instance.server.private_ip }

这个value可以是reource的属性      ,也可以是各种变量计算后的结果                   。只要在执行apply的时候才会去计算输出变量       ,像plan是不会执行计算的      。

还可以定义输出变量的一些属性:

description:输出变量的描述                   ,说明清楚这个变量是干嘛的; sensitive:如果是true             ,就不会在控制台打印出来; depends_on:显性地定义依赖关系       。

完整的定义如下:

output "instance_ip_addr" { value = aws_instance.server.private_ip description = "The private IP address of the main server instance." sensitive = false depends_on = [ # Security group rule must be created before this IP address could # actually be used, otherwise the services will be unreachable. aws_security_group_rule.local_access, ] }

引用输出变量

引用输出变量很容易       ,表达式为module.<module name>.<output name>                   ,如果前面的输出变量定义在模块pkslow_server中             ,则引用为:module.pkslow_server.instance_ip_addr                   。

本地变量Local Variable

本地变量有点类似于其它语言代码中的局部变量,在Terraform模块中                   ,它的一个重要作用是避免重复计算一个值            。

locals { instance_name = "${var.env}-${random_string.random.result}-${var.suffix}" }

这里定义了一个本地变量instance_name                   ,它的值是一个复杂的表达式       。这时我们可以通过local.xxx的形式引用,而不用再写复杂的表达式了                    。如下:

output "instance_name" { value = local.instance_name }

这里要特别注意:定义本地变量的关键字是locals块             ,里面可以有多个变量;而引用的关键字是local                   ,并没有s            。

一般我们是建议需要重复引用的复杂的表达式才使用本地变量      ,不然太多本地变量就会影响可读性。

对变量的引用

定义了变量就需要对其进行引用             ,前面的讲解其实已经讲过了部分变量的引用                   ,这些把所有列出来                    。

类型 引用方式 资源Resources . 输入变量Input Variables var. 本地变量Local Values local. 子模块的输出 module.. 数据源Data Sources data.. 路径和Terraform相关 path.module:模块所在路径

path.root:根模块的路径

path.cwd:一般与根模块相同      ,其它高级用法除外

terraform.workspace:工作区名字 块中的本地变量 count.index:count循环的下标;

each.key/each.value:for each循环的键值;

self:在provisioner的引用;

上面都是单值的引用       ,如果是List或Map这种复杂类型                   ,就要使用中括号[]来引用                   。

aws_instance.example[0].id:引用其中一个元素;

aws_instance.example[*].id:引用列表的所有id值;

aws_instance.example["a"].id:引用key为a的元素;

[for value in aws_instance.example: value.id]:返回所有id为列表;

运算符

与其它语言一样             ,Terraform也有运算符可以用       ,主要是用于数值计算和逻辑计算。以下运算符按优先级从高到低如下:

!取反                   ,-取负 *乘号             ,/除号,%取余 +加号                   ,-减号 >                   ,>=,<             ,<=:比较符号 ==等于                   ,!=不等于 &&与门 ||或门

当然      ,用小括号可以改变这些优秀级             ,如(1 + 2) * 3             。

注意:对于结构化的数据比较需要注意类型是否一致                   。比如var.list == []按理说应该返回true                   ,而list为空时      。当[]实际表示是元组tuple([])      ,所以它们不匹配             。可以使用length(var.list) == 0的方式                   。

条件表达式

条件表达式的作用是在两个值之间选一个       ,条件为真则选第一个                   ,条件为假则选第二个      。形式如下:

condition ? true_value : false_value

示例如下:

env = var.env !="" ? var.env : "dev"

意思是给env赋值             ,如果var.env不为空就把输入变量var.env的值赋给它       ,如果为空则赋默认值dev       。

for表达式

使用for表达式可以创建一些复杂的值                   ,而且可以使用一些转换和计算对值计算再返回                   。如将字符串列表转化成大写:

> [for s in ["larry", "Nanhua", "Deng"] : upper(s)] [ "LARRY", "NANHUA", "DENG", ]

可以获取下标和值:

> [for i,v in ["larry", "Nanhua", "Deng"] : "${i}.${v}"] [ "0.larry", "1.Nanhua", "2.Deng", ]

对于Map的for表达式:

> [for k,v in {name: "Larry Deng", age: 18, webSite: "www.pkslow.com"} : "${k}: ${v}"] [ "age: 18", "name: Larry Deng", "webSite: www.pkslow.com", ]

通过条件过滤数据:

> [for i in range(1, 10) : i*3 if i%2==0] [ 6, 12, 18, 24, ]

动态块Dynamic Block

动态块的作用是根据变量重复某一块配置            。这在Terraform是会遇见的       。

resource "aws_elastic_beanstalk_environment" "tfenvtest" { name = "tf-test-name" application = "${aws_elastic_beanstalk_application.tftest.name}" solution_stack_name = "64bit Amazon Linux 2018.03 v2.11.4 running Go 1.12.6" dynamic "setting" { for_each = var.settings content { namespace = setting.value["namespace"] name = setting.value["name"] value = setting.value["value"] } } }

比如这里的例子             ,就会重复setting块                    。重复的次数取决于for_each后面跟的变量            。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
seo如何进行优化(seo排名优化工具推荐) pythonwith语句终止条件(python使用语句的常见陷阱)