terraform语法
# 一、内容介绍
- Provider插件
- Resource资源
- DataSuource数据源
- Variable变量
- Output输出
# 二、语法介绍
Terraform
的配置文件都是以.tf
为后缀;Terraform
支持两种模式HCL、JSON
;- HashiCorp Configuration Language
# 三、Provider插件
- Terraform通过provider管理基础设施,使用provider与云供应商API进行交互;
- 每个Provider都包含相关的资源呵呵数据源;
- provider: https://registry.terraform.io/browse/providers
# 声明Provider
- 每个
Terrform
模块必须声明它需要哪些Provider
,以便Terraform
可以安装和使用它们. - 提供者要求在一个
required_providers
块中.
## versions.tf
terraform {
required_version = "1.2.8" // 这里是terraform的版本号,可以通过`terraform -v`获取到
required_providers {
alicloud = {
//原地址
source = "aliyun/alicloud"
//版本
version = "1.183.0"
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
# 声明Provider
- 关键字
provider
Provider
名称
# provider.tf
provider "alicloud" {
access_key = var.alicloud_access_key
secret_key = var.alicloud_secret_key
region = var.region
}
provider "PROVIDER_NAME" {
//主题部分
//配置参数
access_key = var.alicloud_access_key
secret_key = var.alicloud_secret_key
region = var.region
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# alias-配置多个Provider
- 可以为同一个Provider定义多个配置,并选择基于每个资源或每个模块使用哪一个.这样做的主要原因是支持一个云平台的多个区域
- 引用方式:
. , alicloud.beijing
# provider.tf
provider "alicloud" {
alias = "beijing"
region = "cn-beijng-b"
}
# provider.tf
provider "alicloud" {
alias = "hanzhou"
region = "cn-hanzhou-b"
}
2
3
4
5
6
7
8
9
10
11
# 四、Resource资源
- 资源来自
Provider
,是Terraform
中最重要的元素.每个资源块描述一个或多个基础对象,例如网络、计算实例或更高级别的组件,例如DNS记录. - 资源名称必须以字母或下划线开头,并且只能包含字母、数字、下划线和破折号
resource "resource_type" "name" {
// resource_config
}
2
3
# Resource-ECS
- 定义一台ECS实例: 可用区、安全组、实例规格、系统盘类型、镜像、实例名称、带宽、交换机、付费类型、账户密码
- https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/instance
# alicloud-ecs.tf
resource "alicloud_instance" "myecs" {
provider = alicloud.shanghai
availability_zone = "cn-shanghai-b"
security_groups = alicloud_security_group.group.*.id
instance_type = "ecs.g7.large"
system_disk_category = "cloud_essd"
system_disk_name = "tf_system_disk_name"
system_disk_description = "tf_system_disk_description"
image_id = "centos_7_5_x64_20G_alibase_20211130.vhd"
instance_name = "mytestecs"
vswitch_id = alicloud_vswitch.vsw.id
internet_max_bandwidth_out = 1
internet_charge_type = "PayByTraffic"
password = "root@123"
# data_disks {
# name = "disk2"
# size = 20
# category = "cloud_efficiency"
# description = "disk2"
# encrypted = true
# kms_key_id = alicloud_kms_key.key.id
# }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Resource-DNS
- 定义一条DNS解析记录: ZoneName: terraform.chsaos.com; Type: A; Record: demo
- 完整域名: terraform.chsaos.com
- 需要在阿里云
RAM
给子账号添加DNS
的权限
# alicloud_dns.tf
# TYPE A
# terraform.chsaos.com
reource "alicloud_dns_record" "record" {
name = "chsaos.com"
host_record = "terraform"
type = "A"
value = alicloud_instance.myecs.public_ip
}
terraform validate
terraform plan
2
3
4
5
6
7
8
9
10
11
12
13
14
# 五、DataSource数据源
# DataSource
- datasource提供资源的数据,可以通过参数过滤并供其他模块引用;使用
data
块声明 - https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/data-sources/images
......
data "alicloud_images" "images_ds" {
owners = "system"
name_regex = "^centos_7"
status = "Available"
os_type = "linux"
architecture = "x86_64"
output_file = "./output.json"
}
output "first_image_id" {
value = "${data.alicloud_images.images_ds.images.0.id}"
}
......
2
3
4
5
6
7
8
9
10
11
12
13
14
# 六、Variable变量
# Variable
- 变量允许自定义
Terraform
模块,而无需更改模块自己的源代码.这可以实现跨不同的Terraform
配置共享模块,使用模块可以组合可重用
variable "access_key" {
type = string
}
variable "secret_key" {
type = string
}
variable "region" {
type = string
}
2
3
4
5
6
7
8
9
10
11
- 在
variable.tf
文件中定义变量 - 在同一个模块的所有变量中必须是唯一的
- 可以从环境变量或者文本文件中读取
Terraform默认读取
terraform.tfvars`
# Variable可选参数
- default变量的默认值
- type变量的类型
- description变量的描述信息
- validation定义变量的验证规则
- sensitive 限制变量在UI中显示
- nullable变零是否为空
variable "region" {
type = string
description = "region name"
default = "cn-shanghai"
sensitive = true
}
2
3
4
5
6
# Variable参数类型
- any
- string
- number
- bool
- list(
) - set(
) - map(
) - object({ATTR_NAME = ATTR_TYPE, ...})
- tuple([
, ...])
Variable-map-DNS
- 示例: 使用map类型的变量来定义DNS域名;
## variables.tf
variable "dns_record" {
type = map(string)
description = "define dns name"
}
## terraform.tfvars
dns_record = {
"dev" = "dev.chsaos.com"
"stag" = "stag.chsaos.com"
"prod" = "prod.chsaos.com"
}
2
3
4
5
6
7
8
9
10
11
12
# Variable-list-ENV
- 示例:使用list类型的变量来定义环境变量表
## variables.tf
variable "env_list" {
type = list(string)
description = "deploy env name"
}
## terraform.tfvars
env_list = ["dev","stag","prod"]
2
3
4
5
6
7
8
9
# Variable-object-ECS属性
- 示例: 使用object类型的变量来定义ECS属性信息
## variable.tf
variable "ecs_info" {
type = object({ecs_image = string,ecs_name = string})
}
## terraform.tfvars
ecs_info = {
ecs_image = "centos_7_9_x64_20G_alibase_20220824.vhd"
ecs_name = "mydemoecs"
}
2
3
4
5
6
7
8
9
10
# Variable的使用方式
在变量声明后,可以使用var.VAR_NAME
的方式引用;VAR_NAME
即variables.tf
定义;
- 环境变量
- terraform.tfvars | terraform.tfvars.json
- *.auto.tfvars | *.auto.tfvars.json
- 命令行 -var | -var-file
## alicloud_dns.tf
reource "alicloud_dns_record" "record" {
name = "chsaos.com"
host_record = var.dns_record["dev"]
type = "A"
value = "alicloud_instance.myecs.public_ip"
}
## -var
terraform apply -var="region=cn-shanghai"
terraform apply -var='env_list=["dev","stag"]' -var="region=cn-shanghai"
## -var-file
terraform app -var-file="dev.tfvars"
## env
export TF_VAR_region = 'cn-shanghai'
export TF_VAR_env_list = '["dev","stag"]'
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Variable-locals
局部、本地变量;局部值有助于避免在配置中多次重复想想的值或表达式
## 定义
locals {
ecs_name = "mydemoecs"
owner = "chsaos"
}
## 引用
local.ecs_name
local.owner
2
3
4
5
6
7
8
9
# 七、output输出变量
# output
output可以打印已定义的变量,并且可以公开信息以供其他Terraform
配置使用.输出值类似于编程语言中的返回值.
## output.tf
output "dev_dns_name" {
value = alicloud_dns_record.record.host_record
}
2
3
4
- 运行 terraform plan
# output可选参数
- description 变量的描述信息
- sensitive 限制变量在UI中显示
- depends_on 依赖关系
# Output-子模块之间的引用
例如: 如果以一个名为ecs_server的子模块,声明了一个名为instance_ip_addr的输出,则可以将该值作为module.ecs_server.instance_ip_addr.
module.
# 八、Module模块
Terraform
可以更轻松地扩展基础架构并保持其配置整洁.但是,随着基础架构的增长,单个目录变得难以管理.
# Module
假设: 创建多台服务器? 一遍又一遍重复相同的配置代码?
---这就是模块真正有用的地方
# Module简介
terraform
模块是一种可重用现有代码的方法,减少基础设施组件开发的代码量.
Terraform
模块是一个或多个.tf
文件集合.
.
├── main.tf
├── output.tf
├── README.md
└── variables.tf
2
3
4
5
实际上任何Terraform
配置本身已经是一个模块.如果在此目录中运行Terraform
,则这些配置文件将被视为根模块
# Module语法
name: 模块的名称,在terraform
中可以使用模块名称进行引用
source: 模块代码的路径,本地或者远程的仓库
version: 版本信息
参数信息:
module "name" {
source = "xxxx.io/your-org/terraform_test_module"
version = "1.0.0"
argument_1 = var.test_1
argument_2 = var.test_2
}
2
3
4
5
6
# Module项目实践
项目参考
youdianzhishi-terraform/terraform-module-example
中的/env/dev
# Module工作原理
远程模块: 存储到根模块的.terraform目录中(修改后,必须get/init).
本地模块: 将通过软连接的方式引用本地的源目录(修改后,无需操作).
使用terraform get下载模块
使用terraform graph查看模块; -module-depath汇总对象;
# Module调用方式
本地文件: "./module_name"
TF注册表: "hashicorp/consul/aws"
GitHub:
- http "github.com/hashicorp/example"
- ssh "git@github.com/hashicop/example.git"
bucket:
通用Git:
- http "git::https://example.com/vpc.git"
- ssh "git::ssh://username@example.com/storage.git"
2
3
4
5
6
7
8
9
# Module-输入、输出变量
# Child module instance(ECS)
//main.tf
resource "alicloud_instance" "myecs" {
vswitch_id = var.vsw_id
......
}
//variables.tf
variable "vsw_id" {}
# Child module network(VPC)
//main.tf
resource "alicloud_vpc" "vpc" {
......
}
resource "alicloud_vswitch" "vsw" {
vpc_id = alicloud_vpc.vpc.id
}
//outputs.tf
output "vsw_id" {
value = alicloud_vswitch.vsw.id
}
# Root module
module "dev_ecs" {
source = "./moduels/ecs"
instance_name = "ecs_01"
vsw_id = module.network.vsw_id
}
module "network" {
source = "./module/vpc"
...
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Module实例化
一个模块可以被多次实例化
每个实例定义唯一的名称,指定相同的source
来源;
module "dev_ecs" {
source = "./module/ecs"
instance_name = "ecs_01"
}
module "prod_ecs" {
source ="./module/ecs"
instance_name = "ecs_02"
}
2
3
4
5
6
7
8
9
# Module模块优点
- 1.解决代码重复问题
- 2.加强代码读性,代码整洁性
- 3.资源标准化
- 4.减少认为错误发生频率
# 九、Expressions表达式
# 条件表达式
condition ? true_val : false_val
- condition 条件(返回值true/false)
- true_val 条件为true的值
- false_val 条件为false的值
实例仓库: "youdianzhishi-terraform/terraform-expr-demo"
$ terraform plan
# consle调试界面
$ terraform console
> var.region
"cn-shanghai"
> var.region != "" ? var.region : "cn-shanghai"
"cn-shanghai"
2
3
4
5
6
7
8
# DEMO
当region变量存在时
region = var.region
,反之region = "cn-shanghai"
var.region != "" ? var.region : "cn-shanghai"
# for表达式
借助for表达式可以对数据进行处理,生成新的数据对象
[ for VAR in OBJECT : VAR ]
[ for INDEX,VAR in OBJECT: "${INDEX}=${VAR}" ]
2
# 列表遍历(terraform console模式下)
$ terraform console
> [ for value in var.env_name : "${value}"]
[
"dev",
"test",
"stag",
"prod",
]
> [ for index,value in var.env_name : "${index}-${value}"]
[
"0-dev",
"1-test",
"2-stag",
"3-prod",
]
# map遍历(terraform console模式下)
terraform console
> [ for v in var.dns_record : "${v}" ]
[
"dev.app",
"prod.app",
"stag.app",
"test.app",
]
> [ for k,v in var.dns_record : "${k}:${v}" ]
[
"dev:dev.app",
"prod:prod.app",
"stag:stag.app",
"test:test.app",
]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# splat表达式(动态表达式)
splat表达式提供了一种简洁的方式来表达可以用for表达式执行的常见操作.
var.list.*.attr # 历史书写方式,不推荐
var.list[*].attr
# terraform console模式下
$ terraform console
> var.ecs_spec
tolist([
tomap({
"id" = "100"
"name" = "ecs01"
"type" = "ecs.n1.tiny"
}),
tomap({
"id" = "101"
"name" = "ecs02"
"type" = "ecs.n1.tiny"
}),
])
> var.ecs_spec[*].id
tolist([
"100",
"101",
])
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 十、Functions内置函数
# 函数
Terraform
语言包括许多内置函数,可以从表达式中调用这些函数来转换.
函数调用的一般语法是函数名后跟括号以逗号分离的参数.
function(arg1,arg2)
# terraform console模式下
$ terraform console
> min(1,2,3)
1
> max(1,2,3)
3
2
3
4
5
6
7
8
9
10
# 数值函数
max() 获取最大值
min() 获取最小值
...将集合扩展为单个参数
parseint() 将字符串解析为整数
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)
> parseint("100",10) # 转成十进制数
100
> parseint("100",2) # 转成二进制数
4
2
3
4
5
6
7
8
9
10
# String字符串函数
- format() 格式化
- split() 字符串分割
- join()字符串拼接
- replace()替换字符串
format("Hello %s!","terraform")
join(",",["name","age","title"])
replace("a=b=c","=","-")
split(",","name,age,title")
2
3
4
# 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) list[index] | 根据index获取list中的元素 |
flatten(list,list,list) | 将多层list转换成单list |
index(list,value) | 返回value元素的index |
# Map映射函数
函数 | 功能 |
---|---|
length(list) | 计算map的长度 |
lookup(map,key,default) | 检索map的key,不存在返回default |
merge(map1,map2,map3) | 合并map,相同key会被最后覆盖 |
keys(map) values(map) | 创建map中key的list 创建map中value的list |
- 01
- AWS NAT-NetWork-Firwalld配置(一)04-09
- 02
- AWS NAT-NetWork-Firwalld配置(二)04-09
- 03
- kubernetes部署minio对象存储01-18