配置语法
- Terraform的配置文件都是以- .tf为后缀
- Terraform支持两种模式- HCL、JSON
Provider 插件
 
providers地址:Terraform Registry
Terraform 通过 provider 管理基础设施,使用 provider 与云供应商 API 进行交互,每个 Provider 都包含相关的资源和数据源。
 
声明 Provider
 
每个 Terraform 模块必须声明它需要哪些 Provider ,以便 Terraform 可以安装和使用它们。
提供者要求在一个 required_providers 块中声明。
## versions.tfterraform {required_providers {alicloud = {// Provider 源地址source = "aliyun/alicloud"// Provider 版本version = "1.208.0"}}
}配置 Provider
 
- 关键字 provider
- Provider名称
# Configure the Alicloud Provider
provider "PROVIDER_NAME" {// 参数配置access_key = var.alicloud.access_keysecret_key = var.alicloud.secret_keyregion     = var.region
}- 实例
## provider.tfprovider "alicloud" {access_key = var.alicloud.access_keysecret_key = var.alicloud.secret_keyregion     = var.region 
}-  阿里云提供商接受多种输入凭据进行身份验证的方式 - Static credentials
- Environment variables
- Shared credentials/configuration file
- ECS Role
- Assume role
- Sidecar Credentials
 
详细使用查看官网:Terraform Registry
配置多个 Provider
 
可以为同一个 Provider 定义多个配置,并选择基于每个资源或每个模块使用哪一个。这样做的主要原因是支持一个云平台的多个区域。
引用方式:
- <PROVIDER NAME>.<ALIAS>
- alicloud.beiling
- alicloud.hangzhou
在其他配置文件中指定资源区域时,可以使用此模式引用
## provider.tfprovider "alicloud" {access_key = var.alicloud.access_keysecret_key = var.alicloud.secret_key
}provider "alicloud" {alias = "beijing"region = "cn-beijing-b"
}provider "alicloud" {alias = "hangzhou"region = "cn-hangzhou-a"
}Resource 资源
 
- 资源来自 Provider,是Terraform中最重要的元素。每个资源块描述一个或多个基础对象,例如网络、计算实例或更高级别的组件,例如DNS记录。
- 资源名称必须以字母或下划线开头,并且只能包含字母、数宇、下划线和破折号。
resource "resource_type" "name" {// resource_config
}Resource-ECS 资源
 
Terraform Registry
定义一台 ECS 实例
- 可用区
- 安全组
- 实例规格
- 系统盘类型
- 名称描达
- 镜像
- 实例名称
- 交换机
- 带宽
- 付费类型
- 账户密码
## alicloud_ecs.tfresource "alicloud_instance" "myecs" {// 可用区availability_zone = var.region// 安全组,需要提前定义生成security_groups = alicloud_security_group.group.*.id// 实例规格instance_type = "ecs.n1.tiny"// 系统磁盘类型system_disk_category = "cloud_efficiency"// 系统磁盘名称svstem_disk_name = "tf_svstem_disk_name"// 系统盘描述system_disk_description = "tf_system_disk_description"// 系统镜像IDimage_id = "centos7_5_X64_206_allbase_20211130.vhd"// 实例名称instance_name = "mytestecs"// 交换机,需要提前定义生成switch_id = alicloud_vswitch.vsw.id// 带宽internet_max_bandwidth_out = 1// 付费类型internet_charge_type = "PayByTraffic"// 账号密码password = "root@123"
}Resource-DNS 资源
 
Terraform Registry
定义一条 DNS 解析记录
- ZoneName: evescn.site
- Type: A
- Record: demo
- 完整域名:demo.evescn.site
## alicloud_dns.tf
## TYPE A
## demo.evescn.com# 老版本 API
resource "alicloud_dns_record" "record" {name        = "evescn.com"host_record = "demo"type        = "A"value       = alicloud_instance.mytestecs.public_ip
}# 新版本 API
resource "alicloud_alidns_record" "record" {domain_name = "evescn.com"rr          = "demo"type        = "A"value       = alicloud_instance.mytestecs.public_ipremark      = "demo-web"status      = "ENABLE"
}DataSource 
 
Data数据源
 
Terraform Registry
datasource 提供资源的数据,可以通过参数过滤数据并供其他模块引用;使用 data 块声明
- 过滤阿里云上 centos_7 x86_64 镜像
data "alicloud_images" "images_ds" {owners     = "system"name_regex = "^centos_7"architecture = "x86_64"
}// output 把值传递出去,给其他地方引用
output "first_image_id" {value = "${data.alicloud_images.images_ds.images.0.id}"
}DataSource 引用
 
ecs 配置创建替换 image_id。
resource "alicloud_instance" "myecs" {availability_zone = var.regionsecurity_groups = alicloud_security_group.group.*.idinstance_type = "ecs.n1.tiny"system_disk_category = "cloud_efficiency"svstem_disk_name = "tf_svstem_disk_name"system_disk_description = "tf_system_disk_description"// 私有 datasource output 变量,替换此处image_id = data.alicloud_images.images_ds.images.0.idinstance_name = "mytestecs"switch_id = alicloud_vswitch.vsw.idinternet_max_bandwidth_out = 1internet_charge_type = "PayByTraffic"password = "root@123"
}Variables 变量
 
变量允许自定义 Terraform 模块,而无需更改模块自己的源代码。这可以实现跨不同的 Terraform 配置共享模块,使模缺可组合和可重用。
variable "alicloud_access_key" {type = string
}variable "alicloud_secret_key" {type = string
}variable "region" {type = string
}- 在variables.tf文件中定义变量;
- 在同一个模块的所有变量中必须是唯一的;
- 可以从环境变量或者文本文件中读取;
- Terraform默认读取- terraform.tfvars;
Variable 可选参数
 
- default变量的默认值
- type变量的类型
- description变量的描述信息
- validation定义变量验证规则
- sensitive限制变量在UI中显示
- nullable变量是否可为空
variable "region" {type = stringdescription = "region name"default = "cn-beijing"sensitive = true
}Variable 参数类型
 
- any
- string
- number
- bool
- list()
- set()
- map()
- object([ATTR_NAME = ATTR_TYPE, ...)
- tuple([, ...])
Variable Map
 
示例:使用
map类型的变量来定义DNS域名
## variables.tfvariable "dns_record" {type = map(string)description = "define dns name"
}## terraform.tfvarsdns_record = {"dev"  = "dev-nginx","stag" = "stag-nginx","prod" = "prod-nginx",
}- 引用环境变量
定义一条 DNS 解析记录。
## alicloud_dns.tf
## TYPE A
## demo.evescn.com# 老版本 API
resource "alicloud_dns_record" "record" {name        = "evescn.com"// 引用环境变量host_record = var.dns_record["dev"]type        = "A"value       = alicloud_instance.mytestecs.public_ip
}# 新版本 API
resource "alicloud_alidns_record" "record" {domain_name = "evescn.com"// 引用环境变量rr          = var.dns_record["dev"]type        = "A"value       = alicloud_instance.mytestecs.public_ipremark      = "demo-web"status      = "ENABLE"
}Variable List
 
示例:使用
list类型的变量来定义环境列表
## variables.tfvariable "env_list" {type = list(string)description = "deploy env name"
}## terraform.tfvarsenv_list = [ "dev", "stag", "prod" ]Variable object
 
示例:使用
object类型的变量来定义ECS属性信息
## variables.tf
variable "ecs_info" {type = object({ ecs_image = string, ecs_name = string })
}## terraform.tfvarsecs_info = {ecs_image = "centos_7_5_x64_20G_alibase_20211130.vhd"ecs_name = "evescn"
}Variable 的使用方式
 
在变量声明后,可以使用 var.VAR_NAME 的方式引用;VAR_ NAME即variables.tf定义;
- 环境娈量
- terraform.tfvars | terraform.tfvars.json
- *.auto.tfvars | *.auto.tfvars.ison
- 命令行 -var | -var-file
## -var
terraform apply -var="region=cn-beijing"
terraform apply -var='env_list=["dev", "stag", "prod"]' -var="region=cn-beijing"## -var-file
terraform apply -var-file="dev.tfvars"## env
export TF_VAR_region='cn-beijing'
export TF_VAR_env_list='["dev", "stag", "prod"]'locals 局部变量
 
局部、本地变量;局部值有助于避免在配置中多次重复相同的值或表达式;
## 定义locals {ecs_name = "evescn"owner    = "evescn"
}## 引用local.ecs_name
local.ownerOutput 输出变量
 
output可以打印已定义的变量,并且可以公开信息以供其他Terraform配置使用。输出值类似于编程语言中的返回值。
## outputs.tfoutput "dev_dns_name" {value = alicloud_dns_record.record.host_record
} Output 可选参数
 
- description变量的描述信息;
- sensitive限制变量在- UI中显示;
- depends_on依赖关系
Output-子模块之间的引用
 
例如: 如果一个名为ecs_server的子模块 声明了一个名为 instance_ip_addr 的输出,则可以将该值作为module.ecs_server.instance_ip_addr
module.<MODULE NAME>.<OUTPUT NAME>
Terraform 模版
 
Terraform 可以更轻松地扩展基础架构并保持其配置整洁。但是,随着基础架构的增长,单个目录变得难以管理。我们这个时候就需要使用模块
Module 简介
 
Terraform 模块是一种可重用现有代码的方法,减少基础设施组件开发的代码量。Terraform 模块是一个或者多个 .tf 文件集合。

实际上任何 Terraform 配置本身已经是一个模块。如果在此目录中运行 Terraform,则这些配置文件将被视为根模块
Module 语法
 
- name:模块的名称,在terraform中可以使用模块名称进行引用
- source:模块代码的路径,本地或者远程的仓库
- version:版本信息;
module "name" {source     = "xxx.io/your-org/terraform_test_module"version    = "1.0.0"argument_1 = var.test_1argument_2 = var.test_2
}Module 工作原理
 
- 远程模块:存储到根模块下的.terraform目录中(修改后,必须get/init)
- 本地模块:将通过软连接的方式引用本地的源目录(修改后,无需操作)
使用 terraform get 下载模块;
 使用 terraform graph 查看模块; -module-depth 汇总对象;
Module 调用方式
 
本地文件: "./module_name"TF注册表: "hashicorp/consul" "hashicorp/aws"
GitHub:
- http "github.com/hashicorp/example"
- ssh "git@github.com:hashicorp/example.git"
 bucket: "bitbucket.org/hashicorp/terraform-consul-aws"
通用Git:
- http: "git::https://example.com/vpc.git"
- ssh: "git::ssh://username@example.com/storage.git"
Module 输入、输出变量
 
模块的输出值,便于其他模块引用
 引用方式: module.MODULE_NAME.OUTPUT_NAME
Module 实例化
 
一个模块可以被多次实例化;
 每个实例定义唯一的名称,指定相同的 source 来源;
module "dev_ecs" {source = "./module/ecs"instance_name = "ecs_01"
}module "prod_ecs" {source = "./module/ecs"instance_name = "ecs_02"
}Module 模块优点
 
- 解决代码重复问题;
- 加强代码可读性,代码整洁性;
- 资源标准化;
- 减少人为错误发生频率;
Expressions 表达式#
 
条件表达式
condition ? true_val : false_valcondition 条件 (返回值true/false)
- true_val 条件为true的值
- false_val 条件为false的值
DEMO-条件表达式
var.region != "" ? var.region: "cn-beijing"当region变量存在时 region = var.region, 反之 region = “cn-beijing”
- for表达式
[ for VAR in OBJECT : VAR]
[ for INDEX, VAR in OBJECT: "${INDEX}=${VAR}"]借助for表达式可以对数据进行处理,生成新的数据对象;
> [ for e in var.env_list: e ]
["dev","stag","prod",
]
> [ for i,e in var.env_list: "${i} = ${e}" ]
["0 = dev","1 = stag","2 = prod",
]> var.dns_record
tomap({"dev" = "dev.app""prod" = "prod.app""stag" = "stag.app"
})
> [ for k,v in var.dns_record : "${k} ${v}" ]
["dev dev.app","prod prod.app","stag stag.app",
]- splat表达式
splat 表达式提供了一种更简洁的方式来表达可以用for表达式执行的常见操作。
var.list[*].attr> var.user_role
[{"name" = "evescn""role" = "admin"},{"name" = "hlr""role" = "develop"},
]
> var.user_role[*].name
["evescn","hlr",
]
> var.user_role.*.name
["evescn","hlr",
] Terraform 函数
 
Functions - Configuration Language | Terraform | HashiCorp Developer
Terraform 语言包括许多内置函数,可以从表达式中调用这些函数来转换。函数调用的一般语法是函数名后跟括号中以逗号分隔的参数。
function(arg1,arg2)- 数值函数
| 函数 | 功能 | 
|---|---|
| max | 获取最大值 | 
| min | 获取最大值 | 
| parseint("string", N) | 将字符串解析为整数,N 表示转换为 N 进制 | 
…将集合扩展为单个参数
max(1,2,3,4,5)
max([1,2,3,4,5]…)
min(1,2,3,4,5)
min([1,2,3,4,5]…)
parseint("101", 10)- String字符串函数
| 函数 | 功能 | 
|---|---|
| format | 格式化 | 
| join | 字符串拼接 | 
| replace | 替换字符串 | 
| split | 字符串分割 | 
format("Hello %s!", "evescn")
join(",", ["name","age","title"])
replace("a=b=c", "=","-")
split(",", "name,age,title")- Collection集合函数
| 函数 | 功能 | 
|---|---|
| alltrue() anytrue() | 判断元素中都是、存在true | 
| chunklist( list, size) | 按照指定size拆分list | 
| compat(list) | 去除list中的空元素 | 
| concat(list1, list2) | 合并两个list | 
| contains(list, value) | 判断元素是否存在list中 | 
| distinct(list) | 去除list中的重复元素 | 
| element(list, index) | 根据index获取list中的元素 | 
| list[index] | 根据index获取list中的元素 | 
| flatten(list,list,list) | 将多层list转换成单list | 
| index(list, value) | 返回value元素的index | 
- Map映射函数
| 函数 | 功能 | 
|---|---|
| length(list) | 计算list的长度 | 
| lookup(map,key,default) | 检索map的key,不存在返回default | 
| merge(map1,map2,map3) | 合并map,相同key会被最后覆盖 | 
| keys(map) | 建map中key的list | 
| values(map) | 创建map中value的list |