配置语法
Terraform
的配置文件都是以.tf
为后缀Terraform
支持两种模式HCL、JSON
Provider
插件
providers
地址:Terraform Registry
Terraform
通过 provider
管理基础设施,使用 provider
与云供应商 API
进行交互,每个 Provider
都包含相关的资源和数据源。
声明 Provider
每个 Terraform
模块必须声明它需要哪些 Provider
,以便 Terraform
可以安装和使用它们。
提供者要求在一个 required_providers
块中声明。
## versions.tf
terraform {
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_key
secret_key = var.alicloud.secret_key
region = var.region
}
- 实例
## provider.tf
provider "alicloud" {
access_key = var.alicloud.access_key
secret_key = var.alicloud.secret_key
region = 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.tf
provider "alicloud" {
access_key = var.alicloud.access_key
secret_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.tf
resource "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"
// 系统镜像ID
image_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_ip
remark = "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.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"
// 私有 datasource output 变量,替换此处
image_id = data.alicloud_images.images_ds.images.0.id
instance_name = "mytestecs"
switch_id = alicloud_vswitch.vsw.id
internet_max_bandwidth_out = 1
internet_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 = string
description = "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.tf
variable "dns_record" {
type = map(string)
description = "define dns name"
}
## terraform.tfvars
dns_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_ip
remark = "demo-web"
status = "ENABLE"
}
Variable
List
示例:使用
list
类型的变量来定义环境列表
## variables.tf
variable "env_list" {
type = list(string)
description = "deploy env name"
}
## terraform.tfvars
env_list = [ "dev", "stag", "prod" ]
Variable
object
示例:使用
object
类型的变量来定义ECS
属性信息
## variables.tf
variable "ecs_info" {
type = object({ ecs_image = string, ecs_name = string })
}
## terraform.tfvars
ecs_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.owner
Output
输出变量
output
可以打印已定义的变量,并且可以公开信息以供其他Terraform
配置使用。输出值类似于编程语言中的返回值。
## outputs.tf
output "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_1
argument_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_val
condition 条件 (返回值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 |