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文件中

定义一个系统镜像数据源,需要的参数:名称、架构、类型、状态等

表达式

条件表达式

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 来源
posted @ 2024-08-22 23:24  Anliven  阅读(34)  评论(0编辑  收藏  举报