Terraform
文章目录
- 简介
- 安装
- 简单使用案例
- 概念
- 原理
- 状态管理
- Backend 远程状态存储机制
- 配置语法
- Argument 参数
- Block 块
- terraform块
- required_providers
- backend
- provider块: 与基础设施交互
- resource块: 定义基础架构
- data块: 数据源
- 表达式(Experssion)和函数(Functions)
- 变量
- variable 输入变量(入参)
- output 输出变量(出参)
- local 局部变量
- Modules 模块
- 创建模块
- 调用子模块
- 使用子模块输出值
- cli基本命令
- terraform init
- terraform workspace 工作空间
- terraform plan 预览计划、不执行
- terraform apply 执行计划
- terraform state 状态管理
- terraform destroy 销毁资源
简介
编写一些 配置文件 就可以管理多个云平台上的基础设施。
安装
https://developer.hashicorp.com/terraform/downloads
- mac brew安装【对xcode版本有要求】
#安装 HashiCorp tap
brew tap hashicorp/tap
#使用hashicorp/tap/terraform
brew install hashicorp/tap/terraform
# 验证安装
terraform version
简单使用案例
- 新建terraform项目的文件夹
- 编写 Terraform 配置文件:创建一个名为的文件main.tf,语法是HCL
- 在文件夹下执行terraform命令:
# 初始化(下载一个名为 provider 的插件,使terraform与云平台交互)
terraform init
# 把编写的配置 应用在云平台上
terraform apply
# 销毁
terraform destroy
示例项目
https://github.com/hashicorp/learn-terraform-init
概念
原理
通过 配置文件 与 基础设施 进行绑定,将配置文件的改动执行成基础设施的变更
要做到这个,Terraform就需要记住当前基础设施的状态, 才能知道要改动那些资源
状态管理
-
记录方式:
backend
默认将每次执行操作时的状态信息存储在当前工作目录下的terraform.tfstate文件里 -
流程
我们对Terraform的代码进行了一些修改,导致生成的执行计划将会改变状态,那么在实际执行变更之前,Terraform会复制一份当前的tfstate文件到同路径下的terraform.tfstate.backup中,以防止由于各种意外导致的tfstate损毁。
Backend 远程状态存储机制
支持远程状态存储与状态锁
配置语法
https://developer.hashicorp.com/terraform/language
Terraform的配置文件以 “.tf” 结尾
注释
# 单行注释,其后的内容为注释
// 单行注释,其后的内容为注释
/* 和 */ 多行注释,可以注释多行
Argument 参数
将一个值或表达式赋值给指定的参数名
参数名 = 参数值
参数值的类型支持:
- 基本类型
- string:字符串类型,由一个或多个Unicode字符组成,例如 “hello”。
- number:数字类型,可以表示整数和浮点数。
- bool:布尔类型,只能是 true 或 false。
- 集合类型
- map(…):映射类型,以键值对(key-value pair) 的方式组合起来的数据元素集
合,其中key为string类型,对应的值可以是string,number,bool等类型,且所
有元素的值必须是同一类型。 - list(…):列表类型,具有同类型的数据元素集合,元素可以是基本类型和块类
型,列表索引从0开始。 - set(…):集合类型,类似于列表类型,但是集合中的元素是没有任何辅助标识符
或顺序,且元素具有唯一性。
- map(…):映射类型,以键值对(key-value pair) 的方式组合起来的数据元素集
- 特殊类型 null
Block 块
块将多个参数聚合在一起,并支持嵌套。块由块类型、块标签和块主体构成
- 顶级块:可以游离于任何其他块独立定义在配置文件中的块
Terraform支持的顶层块类型包括:provider,resource,data,variable,output,module,locals等关键字
<BLOCK TYPE> "<BLOCK LABEL>" "<BLOCK LABEL>" {
# Block body
<IDENTIFIER> = <EXPRESSION> # Argument
}
<顶级块类型> "<块标签>" "<块标签>" {
//块主体
<参数名> = "参数值"
<嵌套块类型> "<块标签>" {
}
}
terraform块
// Terraform 配置
terraform {
// 指定 Terraform 版本要求
required_version = "Terraform版本约束"
// 指定 Provider要求
required_providers {
<Provider1本地名称> {
source = "Provider源地址, 全球唯一" //registry源
version = "Provider版本约束" //版本约束
}
<Provider2本地名称> {
source = "Provider源地址, 全球唯一"
version = "Provider版本约束"
}
}
// 定义 Terraform 存储其状态数据文件的位置
backend "backend类型" {
organization = "example_corp"
workspaces {
name = "my-app-prod"
}
}
}
required_providers
- 必须在required_providers 必须声明需要哪些Provider, 才能安装和使用它们
<本地名称>
是特定于模块的,并在需要提供程序时分配。每个模块的本地名称必须是唯一的- 内置供应商:内置于 Terraform 中,因此您无需在required_providers块中声明它即可使用其功能
Terraform 依靠 provider的插件与基础设施 (云提供者、SaaS 提供者和其他 API )进行交互。
每种资源类型都由provider实现;没有provider,Terraform 无法管理任何类型的基础设施。
backend
- 默认后端
local
,它将状态存储在磁盘上的本地文件 - 更改后端的配置时,必须terraform init再次运行以验证和配置后端
- 目前支持的backend类型 及其配置:https://developer.hashicorp.com/terraform/language/settings/backends/local
provider块: 与基础设施交互
一些provider会要求配置一些信息来使用它们,如:端点URL、云区域…
- 为 <Provider1本地名称> 提供配置
// 默认配置
provider "<Provider1本地名称>" {
// Provider需要的配置参数
region = "1"
url = "1.1.1.1"
...
}
// alias 广州 配置
provider "<Provider1本地名称>" {
alias = "广州"
region = "2"
url = "2.2.2.2"
...
}
// alias 北京 配置
provider "<Provider1本地名称>" {
alias = "北京"
region = "3"
url = "3.3.3.3"
...
}
- <Provider1本地名称>应该要已包含在一个required_providers 块中
- 用 alias 可以为同一个provider的不同资源提供不同配置
- 官方支持的provider
https://developer.hashicorp.com/terraform/language/providers
resource块: 定义基础架构
//resource块
resource "<资源类型>" "<本地名称>" {
//resource块体
<资源参数> = "参数值"
<资源参数> = "参数值"
//metadata块
metadata {
//metadata块体
参数 = "参数值"
}
}
<资源类型>
,<资源参数>
: 每个 Terraform 提供者都有自己的文档,描述其资源类型及其参数。<本地名称>
:用于从同一 Terraform 模块的其他位置引用此资源,但在该模块的范围之外没有任何意义
data块: 数据源
Data Source 可以认为是特殊的Resource,通过关键字 “data” 进行声明。
Data Source 用于查询或计算一些已经存在资源的属性和信息 供其他地方使用
每个Data Source都属于一个provider
data "<data类型>" "<本地名称>" {
// 查询条件
most_recent = true
owners = ["self"]
tags = {
Name = "app-server"
Tested = "true"
}
}
- Data Source会导出一个或多个属性。引用ata Source属性的语法是
data.<data类型>.<本地名称>.<ATTRIBUTE>
:
resource {
参数 = data.data类型.本地名称.id
}
data类型 和 本地名称 的组合必须是唯一的
表达式(Experssion)和函数(Functions)
支持:
基础运算符
条件表达式
循环
字符串函数
数学计算函数
集合函数
类型转换
加密编码
文件操作
变量
variable 输入变量(入参)
声明变量
variable "<变量名称>" {
type = <变量接受的值类型:number、string、bool、list()、set()、map()>
default = <默认值>
description = <描述文档>
validation {
condition = <验证规则>
error_message = <报错信息>
}
sensitive = true // 是否敏感值,敏感值不打印
nullable = false // 是否可为空
}
引用变量: var.<变量名称>
resource "aws_instance" "example" {
instance_type = "t2.micro"
ami = var.<变量名称>
}
output 输出变量(出参)
output "<变量名称>" {
value = <表达式>
description = <描述文档>
sensitive = true // 是否敏感值,敏感值不打印
}
local 局部变量
只能在声明它的模块内的表达式中访问
locals {
<名称> = <值>
}
// 使用
local.<名称>
Modules 模块
对资源封装,模块是使用 Terraform 打包和重用资源配置的主要方式。
可以引用其他人的模块,发布自己的模块(Terraform Registry托管了大量公开可用的 Terraform 模块)
- 模块使用variable 输入变量 接受来自调用模块的值
- 使用output 输出变量 将结果返回给调用模块
- 根模块
每个 Terraform 配置至少有一个模块,称为它的 根模块.tf - 子模块
被另一个模块调用的模块通常称为子模块
创建模块
- 创建一个新目录
- 在其中放置一个或多个文件
.tf
- 简单模块可以直接全部定义都放在一个
main.tf
里
|- 模块目录/
|- |- main.tf 【模块入口】
|- |- variables.tf 【输入变量】
|- |- outputs.tf 【输出变量】
- 复杂模块建议拆分 嵌入模块
|- 模块目录/
|- |- main.tf
|- |- variables.tf
|- |- outputs.tf
|- |- modules/ 【嵌入模块目录】
|- |- |- 嵌入模块a/
|- |- |- |- main.tf
|- |- |- |- variables.tf
|- |- |- |- outputs.tf
|- |- |- 嵌入模块b/
|- |- |- 嵌入模块c/
|- |- examples/ 【调用样例目录】
调用子模块
调用模块意味着将该模块的内容包含到配置中,并为其 输入变量赋值
module "<子模块本地名称>" {
// 模块的参数
source = "【必输参数】子模块的源代码路径"
version = "模块版本"
<输入变量> = <值>
}
使用子模块输出值
module.<子模块本地名称>.<输出值>
cli基本命令
# 检查语法错误
terraform validate
# 格式化代码格式
terraform fmt
# 生成依赖图
terraform graph
# 转为图片格式
terraform graph | dot -Tsvg > graph.svg
terraform init
terraform init会完成代码中所使用到的Provider、Backend、Modules等模块的加载
terraform init -migrate-state
terraform init -reconfigure
terraform workspace 工作空间
# 创建工作区
terraform workspace new [NAME]
# 查看所有的
terraform workspace list
# 查看当前选择的
terraform workspace show
# 选择使用的工作区
terraform workspace select [NAME]
# 删除工作区
terraform workspace delete [NAME]
terraform plan 预览计划、不执行
检测云上资源的属性和状态文件差异,将差异结果显示在命令下方
# 创建变更计划,检查当前的变更是否符合预期
terraform plan
# 输出:
......
Plan: 15 to add, 26 to change, 15 to destroy.
......
No changes. Infrastructure is up-to-date.
Terraform 将您的 Terraform 配置与在该工作区的状态文件中跟踪的真实世界基础设施进行协调,并创建一个资源列表以创建、修改或销毁。
terraform apply 执行计划
# 扫描当前目录下的代码文件(自动创建一个新的变更计划),并执行相应的变更
terraform apply
terraform state 状态管理
# 【废弃】刷新当前 state 文件的配置(远端获取最新数据并将结果写入 state 文件中)
terraform refresh
# 列出当前 state文件中配置的资源
terraform state list
# 展示当前 state文件中配置的资源及其属性值
terraform show
# 展示某个资源的所有属性值
terraform state show <资源类型>.<资源名称>
# 加载您的远程状态并将其输出到标准输出
terraform state pull
# 手动写入状态
terraform state push # 这是极其危险的,应尽可能避免
terraform destroy 销毁资源
# 销毁并回收所有Terraform管理的基础设施资源
terraform destroy