Terraform

简介

编写一些 配置文件 就可以管理多个云平台上的基础设施 (计算、网络、存储、数据库等)。

安装

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

简单使用案例

  1. 新建terraform项目的文件夹
  2. 编写 Terraform 配置文件:创建一个名为的文件main.tf,语法是HCL
  3. 在文件夹下执行terraform命令
# 初始化(下载一个名为 provider 的插件,使terraform与云平台交互)
terraform init

# 把编写的配置 应用在云平台上
terraform apply

# 销毁
terraform destroy

示例项目

https://github.com/hashicorp/learn-terraform-init

概念

原理

通过 配置文件基础设施 进行绑定,将配置文件的改动执行成基础设施的变更

要做到这个,Terraform就需要记住当前基础设施的状态, 才能知道要改动那些资源

* 状态管理 Backend

Terraform需要记住当前基础设施的状态, 对于状态的管理的配置,Terraform称之为Backends

  • 状态文件默认是在本地目录上的terraform.tfstate文件

  • 流程
    我们对Terraform的代码进行了一些修改,导致生成的执行计划将会改变状态,那么在实际执行变更之前,Terraform会复制一份当前的tfstate文件到同路径下的terraform.tfstate.backup中,以防止由于各种意外导致的tfstate损毁。

local模式

默认,就是使用本地路径来存储状态文件

terraform {
 backend "local" {
   path = "terraform.tfstate"
 }
}
remote模式

远程状态存储机制:远程存储状态与状态锁

支持的有:
s3
gcs
oss
etcd
pg
http
kubernetes

配置语法

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

Terraform的配置文件以 “.tf” 结尾

k8s配置语法案例
// kubernetes
provider "kubernetes" {
  config_path    = "~/.kube/config"
  config_context = "my-context"
}

// kubernetes_namespace
resource "kubernetes_namespace" "test" {
  metadata {
    name = "my-first-namespace"
  }
}
// kubernetes_deployment
resource "kubernetes_deployment" "test" {
  metadata {
    name      = "nginx"
    namespace = kubernetes_namespace.test.metadata.name  //"my-first-namespace"
  }
  spec {
    replicas = 2
    selector {
      match_labels = {
        app = "MyTestApp"
      }
    }
    template {
      metadata {
        labels = {
          app = "MyTestApp"
        }
      }
      spec {
        container {
          image = "nginx"
          name  = "nginx-container"
          port {
            container_port = 80
          }
        }
      }
    }
  }
}
// kubernetes_service
resource "kubernetes_service" "test" {
  metadata {
    name      = "nginx"
    namespace = kubernetes_namespace.test.metadata.name  //"my-first-namespace"
  }
  spec {
    selector = {
      app = kubernetes_deployment.test.spec.template.metadata.labels.app	//"MyTestApp"
    }
    type = "NodePort"
    port {
      node_port   = 30201
      port        = 80
      target_port = 80
    }
  }
}

注释

# 		单行注释,其后的内容为注释
// 		单行注释,其后的内容为注释
/* 和 */	多行注释,可以注释多行

Argument 参数

将一个值或表达式赋值给指定的参数名

参数名 = 参数值

参数值的类型支持:

  • 基本类型
    • string:字符串类型,由一个或多个Unicode字符组成,例如 “hello”。
    • number:数字类型,可以表示整数和浮点数。
    • bool:布尔类型,只能是 true 或 false。
  • 集合类型
    • map(…):映射类型,以键值对(key-value pair) 的方式组合起来的数据元素集
      合,其中key为string类型,对应的值可以是string,number,bool等类型,且所
      有元素的值必须是同一类型。
    • list(…):列表类型,具有同类型的数据元素集合,元素可以是基本类型和块类
      型,列表索引从0开始。
    • set(…):集合类型,类似于列表类型,但是集合中的元素是没有任何辅助标识符
      或顺序,且元素具有唯一性。
  • 特殊类型 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
  1. 必须在required_providers 必须声明需要哪些Provider, 才能安装和使用它们
  2. <本地名称>是特定于模块的,并在需要提供程序时分配。每个模块的本地名称必须是唯一的
  3. 内置供应商:内置于 Terraform 中,因此您无需在required_providers块中声明它即可使用其功能

Terraform 依靠 provider的插件与基础设施 (云提供者、SaaS 提供者和其他 API )进行交互
每种资源类型都由provider实现;没有provider,Terraform 无法管理任何类型的基础设施。

backend
  1. 默认后端local,它将状态存储在磁盘上的本地文件
  2. 更改后端的配置时,必须terraform init再次运行以验证和配置后端
  3. 目前支持的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"
  ...
}
  1. <Provider1本地名称>应该要已包含在一个required_providers 块中
  2. 用 alias 可以为同一个provider的不同资源提供不同配置
provider

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

https://registry.terraform.io/?product_intent=terraform

  • kubernetes provider
    https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs
    https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/deployment#example-usage
    https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service#example-usage
resource块: 定义基础架构
//resource块
resource "<资源类型>" "<本地名称>" {
  //resource块体
  <资源参数>           = "参数值"
  <资源参数>           = "参数值"
  //metadata块
  metadata {
    //metadata块体
    参数           = "参数值"
  }
}
  1. <资源类型>, <资源参数>: 每个 Terraform 提供者都有自己的文档,描述其资源类型及其参数。
  2. <本地名称>:用于从同一 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 模块)

  1. 模块使用variable 输入变量 接受来自调用模块的值
  2. 使用output 输出变量 将结果返回给调用模块
  • 根模块
    每个 Terraform 配置至少有一个模块,称为它的 根模块.tf
  • 子模块
    被另一个模块调用的模块通常称为子模块
创建模块
  1. 创建一个新目录
  2. 在其中放置一个或多个文件.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的三部曲,init->plan->apply

# 检查语法错误
terraform validate

# 格式化代码格式
terraform fmt

# 生成依赖图
terraform graph
# 转为图片格式
terraform graph | dot -Tsvg > graph.svg
terraform init

terraform init会完成代码中所使用到的Provider、Backend、Modules等模块的加载

# 初始化包含 Terraform 配置文件的工作目录
terraform init
Backend初始化

如果更改了Backend, 重新init。要使用以下命令:
要么-reconfigure要么 -migrate-state

# 将现有state复制到新的Backend
terraform init -migrate-state

# 忽略现有的state
terraform init -reconfigure
terraform workspace 工作空间

每个工作区都有自己的 Terraform 配置并充当单独的工作目录。
大多数 Terraform 命令仅与当前选定的工作区交互,包括 provisioning 和 state

# 创建工作区
terraform workspace new [NAME]

# 查看所有的
terraform workspace list
# 查看当前选择的
terraform workspace show

# 选择使用的工作区
terraform workspace select [NAME]

# 删除工作区
terraform workspace delete [NAME]
  • 常见用途是:
    创建一组基础架构的并行、不同的副本,以在修改生产基础架构之前测试一组更改。
    (也就是开发环境、测试环境、集成环境、线上 各一个workspace)
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 force-unlock <process_id> 

如果是本地进程在占用terraform状态,kill 本地的进程

terraform destroy 销毁资源
# 销毁并回收所有Terraform管理的基础设施资源
terraform destroy
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xyc1211

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值