Terraform 语法配置

发布时间 2023-08-01 17:18:20作者: evescn

Terraform 语法配置

Terraform 语法

配置语法

  • Terraform 的配置文件都是以 .tf 为后缀
  • Terraform 支持两种模式 HCL、JSON

Provider 插件

providers 地址:https://registry.terraform.io/browse/providers

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

详细使用查看官网:https://registry.terraform.io/providers/aliyun/alicloud/latest/docs

alias

配置多个 Provider

可以为同一个 Provider 定义多个配置,并选择基于每个资源或每个模块使用哪一个。这样做的主要原因是支持一个云平台的多个区域。

引用方式:

  • <PROVIDER NAME>.<ALIAS>
  • alicloud.beiling
  • provider.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 资源

https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/instance

定义一台 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 资源

https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/alidns_record

定义一条 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"
}

DatSource 数据源

https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/data-sources/images

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}"
}
DatSource 引用

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_ NAMEvariables.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 模块是一个或者多个 .rf 文件集合

实际上任何 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:

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 函数

https://developer.hashicorp.com/terraform/language/functions

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

Backend 配置