Terraform - 语法
Terraform语法
官方文档:https://developer.hashicorp.com/terraform/language
Terraform配置文件
- 配置文件支持两种格式HCL(HashiCorp Configuration Language)、JSON
- HCL格式后缀名以
.tf
结尾,JSON格式后缀名以.tf.json
结尾 - HCL格式更加人性化,支持“//”注释,并且是大多数Terraform文件通常推荐的格式
- JSON格式适用于机器创建,修改和更新,也可以由Terraform操作员完成
- Terraform配置是声明式的,对其他资源和变量的引用不依赖于它们定义的顺序
Provider 插件
- Terraform通过provider管理基础设施,使用provider与云供应商API 进行交互
- 每个Provider都包含相关的资源和数据源
- providers : https://registry.terraform.io/providers
- provider分类:官方版、认证版、社区版、留档版(不维护)
声明Provider
- 每个 Terraform 模块必须声明需要哪些Provider,以便 Terraform可以安装和使用
- 要求在 required_providers 语句块中声明对应Provider的源地址、版本
配置Provider
- 关键字 provider 自定义Provider名称
- 配置对应参数,例如 access_key、secret_key、region等
同一个Provider定义多个配置
- 在配置provider通过alias可以为同一个Provider定义多个配置
- 在资源中通过 provider关键字 引用
. - 可以支持一个云厂商的多个区域
- 需要有一个默认的provider存在
Resource 资源
在Terraform中,一个具体的资源或者服务称之为一个resource,
每个特定的resource包含了若干可用于描述对应资源或者服务的属性字段,通过这些字段来定义一个完整的资源或者服务。
- 通过 resource 关键字来定义一个资源块
- 每个资源块描述一个或多个基础对象、计算实例或更高级别的组件,例如网络、DNS 记录
- 资源名称必须以字母或下划线开头,并且只能包含字母、数字、下划线和破折号
- 资源参数引用:
. .
定义一台ECS实例,需要的参数:可用区、安全组、实例规格、系统盘类型、名称描述、镜像、实例名称、带宽、交换机、付费类型、账户密码等等
定义一条DNS记录,需要的参数:域名、主机记录、类型、值(IP)等
DataSource 数据源
在Terraform中,Data Source 提供的就是一个查询资源的功能,每个data source实现对一个资源的动态查询,Data Souce的结果可以认为是动态变量,只有在运行时才能知道变量的值。
- 提供资源的数据,可以通过参数过滤数据并供其他模块引用
- 使用data块声明
- 在data块中定义需要的属性
- 如果数据源信息较多,建议单独放置在一个tf文件中
定义一个系统镜像数据源,需要的参数:名称、架构、类型、状态等
表达式
- https://developer.hashicorp.com/terraform/language/expressions
- 在项目根目录下执行 terraform console 命令可以进行条件表达式语句的调试
条件表达式
condition ? true_val : false_val
- condition 条件 (返回值true/false)
- true_val 条件为true的值
- false_val 条件为false的值
for表达式
[ for VAR in OBJECT : VAR]
[ for INDEX, VAR in OBJECT: “${INDEX}=${VAR}”]
- 借助for表达式可以对数据进行处理,生成新的数据对象;
- 多用于list、map等数据类型
splat表达式
比用for表达式更简洁的循环方式
示例
variables.tf
variable "region" {
type = string
description = "define region name"
}
variable "owner" {
type = string
description = "define owner name"
}
variable "environment" {
type = list(string)
description = "define env name"
}
variable "dns_record" {
type = map(string)
description = "define dns name"
}
variable "ecs_spec" {
type = list(map(string))
}
terraform.tfvars
region = "beijing"
owner = ""
environment = ["dev", "test", "pre", "prod"]
dns_record = {
"dev" = "dev.sample.site",
"test" = "test.sample.site",
"pre" = "pre.sample.site",
"prod" = "prod.sample.site"
}
ecs_spec = [{
"name" = "ecs01",
"system" = "linux"
}, {
"name" = "ecs02",
"system" = "windows"
}]
output.tf
output "my_region" {
value = var.region != "" ? var.region : "shanghai"
}
output "my_owner" {
value = var.owner != "" ? var.owner : "anliven"
}
output "my_env1" {
value = var.environment
}
//for循环list对象,输出新的数据对象
output "my_env2" {
value = [for value in var.environment : "${value}"]
}
//for循环list对象,输出新的数据对象
output "my_env3" {
value = [for index, value in var.environment : "${index}-${value}"]
}
output "my_dns1" {
value = var.dns_record
}
//for循环map对象,输出新的数据对象
output "my_dns2" {
value = [for key, value in var.dns_record : "${key} : ${value}"]
}
output "my_ecs1" {
value = var.ecs_spec
}
//splat循环,输出新的数据对象
output "my_ecs2" {
value = var.ecs_spec[*].name
}
输出结果
liven@livenan MINGW64 /d/Testing/tf-files/tf-learn-expressions
$ terraform plan
Changes to Outputs:
+ my_dns1 = {
+ dev = "dev.sample.site"
+ pre = "pre.sample.site"
+ prod = "prod.sample.site"
+ test = "test.sample.site"
}
+ my_dns2 = [
+ "dev : dev.sample.site",
+ "pre : pre.sample.site",
+ "prod : prod.sample.site",
+ "test : test.sample.site",
]
+ my_ecs1 = [
+ {
+ name = "ecs01"
+ system = "linux"
},
+ {
+ name = "ecs02"
+ system = "windows"
},
]
+ my_ecs2 = [
+ "ecs01",
+ "ecs02",
]
+ my_env1 = [
+ "dev",
+ "test",
+ "pre",
+ "prod",
]
+ my_env2 = [
+ "dev",
+ "test",
+ "pre",
+ "prod",
]
+ my_env3 = [
+ "0-dev",
+ "1-test",
+ "2-pre",
+ "3-prod",
]
+ my_owner = "anliven"
+ my_region = "beijing"
You can apply this plan to save these new output values to the Terraform state, without changing any real infrastructure.
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
liven@livenan MINGW64 /d/Testing/tf-files/tf-learn-expressions
$
Module模块
- https://developer.hashicorp.com/terraform/language/modules
- 通过module可以复用配置代码,简化管理和编写次数,减少开发量和维护量。使资源标准化的同时,提高了代码整洁性,减少了人为错误发生频率。
- Terraform 模块是一个或多个.tf 文件集合,可以理解为一个目录下的tf文件是一个模块
- 一般嵌套不超过2层,维护可读性和可维护性
Module语法
- name: 模块的名称,在terraform中可以使用模块名称进行引用
- source:模块代码的路径,本地或者远程的仓库
- version: 版本信息
分类
- 远程模块:存储到根模块下的.terraform目录中(修改后,必须get/init)
- 本地模块:将通过软连接的方式引用本地的源目录(修改后,无需操作)
命令
- 使用terraform get 下载模块
- 使用terraform graph 查看模块;-module-depth 汇总对象
引用
- 模块的输出值,便于其他模块引用
- 引用方式: module.MODULE_NAME.OUTPUT_NAME
实例化
- 一个模块可以被多次实例化
- 每个实例定义唯一的名称,指定相同的 source 来源
行动是绝望的解药!
欢迎转载和引用,但请在明显处保留原文链接和原作者信息!
本博客内容多为个人工作与学习的记录,少数内容来自于网络并略有修改,已尽力标明原文链接和转载说明。如有冒犯,即刻删除!
以所舍,求所得,有所获,方所成。