当前位置:   article > 正文

Terraform学习

terraform

Terraform学习

Terraform 与IaC

什么是Terraform

Terraform 是 HashiCorp 的基础设施即代码工具。它允许您在人类可读的声明性配置文件中定义资源和基础设施,并管理您的基础设施的生命周期。与手动管理基础设施相比,使用 Terraform 有几个优势:

  • Terraform 可以管理多个云平台上的基础设施。
  • 人类可读的配置语言可帮助您快速编写基础架构代码。
  • Terraform 的状态允许您在整个部署过程中跟踪资源更改。
  • 您可以将您的配置提交给版本控制,以安全地在基础架构上进行协作。

Terraform比Ansible更适合用于云资源的申请

管理任何基础设施

称为提供程序的 Terraform 插件让 Terraform 通过其应用程序编程接口 (API) 与云平台和其他服务进行交互。

标准化您的部署工作流程

跟踪您的基础设施

Terraform 在状态文件中跟踪您的真实基础架构,该文件充当您环境的真实来源。Terraform 使用状态文件来确定要对您的基础架构进行的更改,以便它与您的配置相匹配。

合作

Terraform 允许您使用其远程状态后端在您的基础设施上进行协作。当您使用 Terraform Cloud(最多五个用户免费)时,您可以安全地与您的队友共享您的状态,为 Terraform 提供稳定的运行环境,并防止多人同时更改配置时出现竞争情况。

您还可以将 Terraform Cloud 连接到版本控制系统 (VCS),如 GitHub、GitLab 等,允许它在您向 VCS 提交配置更改时自动建议基础架构更改。这使您可以像处理应用程序代码一样,通过版本控制来管理对基础架构的更改。

Terraform工作原理

image-20230105002220716

provider去调用云厂商的API去进行资源调用

什么是IaC

基础设施即代码(Infrastructure-as-Code,IaC)意味着使用代码来定义和管理基础设施,用户不必在每次开发、 测试或部署软件时都配置环境。所有基础设施参数都以称为清单的文件的形式保存。

开发人员对基础设施配置文件进行编码,并将其存储在版本控制中。如果有人编辑了一个文件,拉取请求和代码审查 工作流可以检查更改的正确性。因此,与所有代码文件一样,清单易于重用、编辑、复制和共享,它使构建、测试、准备 和部署基础设施更快、更一致。

IaC的优势

借助自动化流程,IaC 协助企业以多种方式管理其 IT 基础设施需求。以下是部署 IaC 的部分优势:

提升架构一致性:IaC 可提高一致性并减少通常会在手动配置过程中发生的错误。其还能够消除手动流程期间可能 会发生的配置漂移。IaC 会整理和记录您的配置规格,进而协助您避免出现未记录的临时配置改变。

降低运维成本:IaC 可通过编程方式管理虚拟机,这样就不必手动配置硬件及更新。一位操作员使用同一组代码, 即可部署并管理一台机器或 1,000 台机器。这样就意味着,需要的员工减少,不必再购买新硬件,成本会因此大 幅降低。

提升操作效率:基础设施编码化可为您提供配置模板,进而简化系统配置、维护和管理。其可以打造出可重复、可 扩展的弹性基础设施。这也意味着,DevOps 能够加速软件开发的各个环节,每天能发布的应用也将更多。

加快部署速度:IaC 能将开发人员耗时冗长的配置工作转变为简单的脚本执行,通过脚本执行就能让其基础设施准 备就绪。因此,部署应用不再需要等待基础设施,新软件的发布也大大提速。

降低操作风险:IaC 也支持版本控制,因此,配置文件也会和其他任何软件源代码文件,归入源代码控制。如此, 风险就会降低。

服务器自动化和配置管理工具通常可以用来实现 IaC。当然,也有一些专门针对 IaC 的解决方案。 一些常见的方案 如下:

image-20230105001548530

IaC的两种方式

采用基础设施即代码的方法有两种。尽管两种方法都能让大多数 IaC 工具正常运行,使用哪一种取决于手上的任务。

声明式

声明式方法也称为功能性方法,明确定义了系统的理想状态,但未明确指出达到该状态的方法。这种方法可让您明确 名义想要的资源,包括必需的属性。IaC 软件会自动配置理想的基础设施,声明式 IaC 工具将会自动应用作出的任何改 变。声明式 IaC 可多次执行且结果相同,无需人为干预。既声明式通常都是幂等的。

如:AWS CloudFormation、hashcrop Terraform、Puppet。

命令(编程)式

相比之下,命令式方法可让您明确定义配置基础设施的方式,以及实现的方法。命令式方法也叫作过程式方法,明确定义了实现特定配置所需的命令。之后需要按照正确的顺序执行这些命令,一次一个步骤。这个方法较脆弱,依靠的是明确的指示,不接受任何更新。需要改变时,命令式 IaC 工具将会要求操作员解读应如何应用这些改变。

如:Chef、Ansible。

但也并不是说声明式就比编程式要好,而是要根据场景使用适合的工具

Terraform 入门 - 腾讯云开发者社区-腾讯云 (tencent.com)

Terraform 工具处在什么位置:

img

img

Terraform比Ansible更适合作为基础云资源、IAAS层的管理工具

为什么说 IaC 对于 DevOps 至关重要?

image-20230105002525556

总结

image-20230105002612651

Terraform快速入门

本次Terraform学习的内容是围绕阿里云ECS的创建进行的,对相关概念的一些变量用法并未详细给出,但一个好的案例无疑是入门的最好方案,当你学会使用且在其中获取到快感,再进行下一步学习的时候更为高效。

Terraform安装

https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli

阿里云设置(环境准备)

在RAM中创建用于使用API的拥有Accesskey的用户

image-20230103174012471

image-20230103173655819

记得给策略,这边直接给全部权限

因为Terraform在执行时能根据环境变量获取相应信息,为了正常访问阿里云我们要需要下面生成的两个Key

用户登录名称 haha@1044463161295039.onaliyun.com
AccessKey ID xxx
AccessKey Secret xxx
  • 1
  • 2
  • 3

配置当前环境变量

export ALICLOUD_ACCESS_KEY="xxx"
export ALICLOUD_SECRET_KEY="xxx"
#export ALICLOUD_REGION="cn-shanghai"  region在tf文件中定义比较合适
#如果需要永久的就讲上面的配置放入/etc/profile中
#也能在tf文件中明文写入
  • 1
  • 2
  • 3
  • 4
  • 5

在本地安装和配置Terraform (aliyun.com)

Terraform 关键概念

Configuration:基础设施的定义和描述

“基础设施即代码(Infrastructure as Code)”,这里的Code就是对基础设施资源的代码定义和描述,也就是通过代码表达我们想要管理的资源。

Provider:基础设施管理组件

Terraform 通常用于对云上基础设施,如虚拟机,网络资源,容器资源,存储资源等的创建,更新,查看,删除等管理动作,也可以实现对物理机的管理,如安装软件,部署应用等。

【Provider】 是一个与Open API直接交互的后端驱动,Terraform 就是通过Provider来完成对基础设施资源的管理的。不同的基础设施提供商都需要提供一个Provider来实现对自家基础设施的统一管理。目前Terraform目前支持超过160多种的providers,大多数云平台的Provider插件均已经实现了,阿里云对应的Provider为 alicloud

provider.png

terraform入门操作指南 - L’E - 博客园 (cnblogs.com)

开始写TF文件

我们先使用下面的例子先了解Terraform在阿里云上的实现流程等内容。

例子:创建阿里云资源

包括vpc,vswitch、安全组、安全组策略、实例

然后我们创建一个干净的空文件夹,在里面创建一个main.tf文件(tf就是Terraform,Terraform代码大部分是.tf文件,语法是HCL,当然目前也支持JSON格式的Terraform代码,但我们暂时只以tf为例):

vim main.tf

# 定义云厂商(版本约束)
terraform {
  required_providers {
    alicloud = {
      source  = "aliyun/alicloud"
      version = "1.195.0"
    }
  }
}
# 配置云厂商
provider "alicloud" {
 region = "cn-shanghai"
 access_key = "LTAI5tALCyMfmyHjhq8rYQTz"
 secret_key = "oSWREzzKUi0vsaT3YPNbJDNp3YU7vI"
}
# 创建vpc
resource "alicloud_vpc" "vpc" {
 vpc_name = "vpc_1"
 cidr_block = "10.0.0.0/16"
}
# 创建vswitch
# alicloud_vswitch是阿里云的资源字段,vsw_1字段是tf文件中的自定义唯一资源名称
# vswitch_name字段是在阿里云上的自定义备注名
resource "alicloud_vswitch" "vsw_1" {
 vswitch_name = "vsw_aliyun1"
 vpc_id = alicloud_vpc.vpc.id
 cidr_block = "10.0.0.0/24"
 zone_id = "cn-shanghai-b"
}
# 新建安全组, 安全组与vswitch的定义相同
resource "alicloud_security_group" "nsg1" {
 name = "wyh_aliyun_nsg1"
 vpc_id = alicloud_vpc.vpc.id
}
# 将nsg_rule1、nsg_rule2加入安全组lyc_aliyun_nsg1中
resource "alicloud_security_group_rule" "nsg_rule1" {
 type = "ingress"
 ip_protocol = "tcp"
 nic_type = "intranet"
 policy = "accept"
 port_range = "1/65535"
 priority = 1
 security_group_id = alicloud_security_group.nsg1.id
 cidr_ip = "0.0.0.0/0"
}
# 创建ECS实例
resource "alicloud_instance" "instance" {
 # cn-shanghai
 availability_zone = "cn-shanghai-b"
 security_groups = ["${alicloud_security_group.nsg1.id}"]
 instance_type = "ecs.n1.small"
 system_disk_category = "cloud_ssd"
 image_id = "centos_7_9_x64_20G_alibase_20220824.vhd"
 instance_name = "wyh-terraform"
 vswitch_id = alicloud_vswitch.vsw_1.id
 internet_max_bandwidth_out = 1
 password = "5jejYWzSjZhWQc7G22"
}

  • 1
  • 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
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

配置网络代理

Provider 详情 - IaC Store (cloudiac.org)

vim ~/.terraformrc

provider_installation {
  network_mirror {
    url = "https://store.cloudiac.org/v1/mirrors/providers/"
    include = ["registry.terraform.io/*/*"]
  }

  direct {
    exclude = ["registry.terraform.io/*/*"]
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

初始化前需要配置网络代理信息

#init 初始化工作目录
terraform init
  • 1
  • 2

小黑科技:将internet_max_bandwidth_out 设置为0,公网ip就会消失

terraform init时会帮你排错

image-20230103154154544

image-20230104152436533

#用于创建执行计划,以确定实现配置文件中指定的资源状态所需的操作,是一种让用户可以十分方便的检查一组更改的执行计划是否符合期望的方法,而无需对实际资源或状态进行任何更改。
terraform plan
  • 1
  • 2

image-20230104152417980

#用于应用所需的更改,以达到所需的配置状态,同时执行结果会保存在本地状态文件terraform.tfstate中。
terraform apply
#输入yes
  • 1
  • 2
  • 3

image-20230104152737373

image-20230104153105300

资源创建后我们可以使用show来查看资源的情况

terraform show
  • 1

image-20230104153546505

阿里云页面查看

VPC创建成功

image-20230104153304750

VSwitch创建成功

image-20230104153327553

安全组成功

image-20230104153356462

实例创建成功

image-20230104153440935

为了避免浪费钱我们直接销毁

#销毁并回收所有Terraform管理的基础设施资源。
terraform destroy
  • 1
  • 2

image-20230104153737526

image-20230104153901102

阿里云页面的资源也被销毁了

Terraform对资源的描述有三种颜色

绿色 + :新加入的模板

黄色 ~ :修改(直接vim修改tf文件后terraform plan就可以看到变动的地方【diff】,apply就能直接修改)

红色 - :销毁

常用基础命令

terraform init :初始化一个包含Terraform代码的工作目录。

terraform plan :查看并创建变更计划。

terraform apply :生成并执行计划。

terraform destroy :销毁并回收所有Terraform管理的基础设施资源。

拓展基础命令

terraform show :展示(Read)当前所有归terraform控制的资源的状态信息【跟踪terraform.tfstate】。

terraform fmt :格式化Terraform代码文件的格式和规范。

terraform validate : 确保配置语法有效且内部一致。

terraform apply/destroy -auto-approve :以非交互的方式同意并执行。

terraform import :将已有云资源导入到terraform的state管理中。

terraform validate :验证模板语法是否正确。

terraform state list :列出当前state中的所有资源。

terraform state show sth. :展示某一个资源的属性。

terraform taint :标记资源为被污染。

terraform untaint :取消被污染标记。

terraform refresh :刷新当前State的内容,即再次调用API并拉取最新的数据写入到state文件中。

terraform graph :生成执行计划的关系图。

terraform graph | dot -Tsvg > graph.svg :将关系图导出为svg关系图。(先安装好yum install -y graphviz)

如图

image-20230104165419475

Terraform相关概念

provider{}

什么是provider

Terraform 是一个多云基础设施编排工具,是通过 Provider 来支持云基础架构。而Provider的本质是上游云厂商的 API的逻辑抽象,他们负责理解API交互并暴露资源。

我们可以将 Provider 可以理解为各个云厂商提供的与云资源交互的后端驱动,不同的基础设施提供商都需要提供一 个Provider来实现对自家基础设施的统一管理。

Terraform实现多云编排的方法就是Provider插件机制。

image-20230104182221937

image-20230104182207248

你可以在官网中查看各云厂商提供的插件Terraform官网所支持的providers

image-20230104170624315

image-20230104170709716

图片中说明version所依赖的Partner等信息,在编写tf文件的时候需要注意!不是每个provider都是由hashcorp管理的,如alicloud归属于aliyun管理。

官网中也给了如何使用provider的模板,就是我们tf文件中的前面两段内容。

version不写默认为latest

# 定义云厂商(版本约束)
terraform {
  required_providers {
    alicloud = {
      source  = "aliyun/alicloud"
      version = "1.195.0"
    }
  }
}
# 配置云厂商
provider "alicloud" {
 region = "cn-shanghai"
 access_key = "xxx"
 secret_key = "xxx"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

required_providers中的插件声明还声明了该源码所需要的插件的版本约束,在例子里就是version = ">=1.24.1"。Terraform插件的版本号采用MAJOR.MINOR.PATCH的语义化格式,版本约束通常使用操作符和版本号表达约束条件,条件之间可以用逗号拼接,表达AND关联,例如">= 1.2.0, < 2.0.0"。可以采用的操作符有:

  • =(或者不加=,直接使用版本号):只允许特定版本号,不允许与其他条件合并使用
  • !=:不允许特定版本号
  • >,>=,<,<=:与特定版本号进行比较,可以是大于、大于等于、小于、小于等于
  • >:锁定MAJOR与MINOR,允许PATCH号大于等于特定版本号,例如,>0.9等价于>=0.9, <1.0,~>0.8.4等价于>=0.8.4, <0.9

可以用添加后缀的方式来声明预览版,例如:1.2.0-beta预览版只能通过"="操作符(或是空缺操作符)后接明确的版本号的方式来指定,不可以与>=~>等搭配使用

推荐使用">="操作符约束最低版本。如果你是在编写旨在由他人复用的模块代码时,请避免使用"~>"操作符,即使你知道模块代码与新版本插件会有不兼容。

如果加入了export全局变量时,value可以使用变量来定义

Usage:

provider "alicloud" {
  access_key = "${var.access_key}"
  secret_key = "${var.secret_key}"
  region     = "${var.region}"
}
  • 1
  • 2
  • 3
  • 4
  • 5

Terraform官网—阿里云provider文档

注:配置provider的访问方式,不同云厂商的配置方式有所不同,请参考各云厂商的provider文档。 温馨提示:ak/sk密钥请勿公开或泄露,以免对您的账号造成资源或经济损失。

多个provider的配置方式:

image-20230104182951094

两种表示方式

1、合并设置

将定义provider和配置provider写在同一个文件provider.tf文件中。

# 定义云厂商(版本约束)
terraform {
  required_providers {
    alicloud = {
      source  = "aliyun/alicloud"
      version = "1.195.0"
    }
  }
}
# 配置云厂商
provider "alicloud" {
 region = "cn-shanghai"
 access_key = "xxx"
 secret_key = "xxx"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
2、分开设置

分别建立provider.tf和version.tf,将定义provider写在version.tf中,将配置provider写在provider.tf 中。

image-20230104232303241

image-20230104232319198

image-20230104232314111

很明显,分开的设置更加优雅,更加方便后续的修改!

resource{}

image-20230104232946998

由图中可知,resource主要分为三大部分

(1)块类型

(2)块标签(0到多个)

(3)块主体

Terraform语言的主要目的是声明资源。

可以将一组资源聚集到一个模块中

Terraform配置由一个根模块组成

image-20230105094712405

Terraform官网resource文档

直接搜索关键字ecs作为例子(自动定位到alicloud_instance)

image-20230104233443086

官网文档中有一些关键字

Example Usage 一个ecs创建的例子

Argument Reference 参数引用【输入】{用于控制资源}

image-20230104234837368

这些都是阿里云ecs资源所对应的资源名称,其中同资源后有attachment的是可附加、可追加的资源类型

注意一个恐怖的东西是ForceNew,每次都要plan一下避免出错是个好习惯

当块标签是ForceNew(强制新建)时,整个source块类型都会重做【原资源会被销毁】

Attributes Reference 属性引用 【输出】{可以将不同块之间的值在tf文件中调用}

Attributes是tf文件块类型的输出,当attchment时可以使用tf文件中写好的块.函数.值

上面几个是最常见的,其他关键字。。。。。在专属的资源文档中也有明文标注。

tips

1、resource是资源的代码块的固定值,描述资源是什么,如,在terraform模块中还是有:

image-20230104235632604

2、例如:alicloud_vswitch是每个厂商定义好的资源名称,如:

image-20230104235722922

image-20230104235826356

3、alicloud_vswitch是阿里云的资源字段,vsw_1字段是tf文件中的自定义唯一资源名称,vswitch_name字段是在阿里云上的自定义备注名

image-20230105000104965

如果想要创建多个vswitch,只需要更改“vsw_1”为“vsw_n”,还有注意cidr_block(网段)的值也要修改

locals { }

局部变量,同一个.tf文件中使用

使用locals{ }定义局部变量

使用local.xxx使用局部变量

image-20230105150023582

output { }

output块负责参数的输出Terraform管理的资源实例的每个导出属性的值可以在配置的其他地方使用。输出值是向模 块用户暴露部分信息的一种方式。

image-20230105154446803

plan一下,报错。

image-20230105154046391

原因:

为了降低意外导出原本仅用于内部的敏感数据的风险,Terraform要求任何包含敏感数据的根模块输出都显式地标记为敏感,以确认您的想法

│意图。

│如果要导出此数据,请添加以下参数,将输出值标注为敏感值:

│ sensitive = true

image-20230105154331792

plan-apply

image-20230105155154117

image-20230105155237222

variable { }

输入变量允许我们自定义Terraform模块的各个方面,而无需更改模块自己的源代码。此功能允许我们跨不同的 Terraform配置共享模块,使我们的模块可组合和可重用。

当我们在配置的根模块中声明变量时,我们可以使用CLI选项和环境变量设置它们的值。当我们在子模块中声明它们 时,调用的模块应该在模块中传递值。

先创建两个tf文件:

variables.tf 【定义变量】

terraform.tfvars 【变量传参】(tf文件名是规定的!Terraform执行时会读取这个文件里面变量的值)

例子:针对provider中的aksk,我们将他弄成变量的形式会更加安全

image-20230105162448074

# variables.tf文件内容
variable "ak" {
  type        = string
  sensitive   = false
  description = "aliyun_access_key"
}

variable "sk" {
  type        = string
  sensitive   = false
  description = "aliyun_secret_key"
}


# terraform.tfvars文件内容
ak = "LTAI5tALCyMfmyHjhq8rYQTz"
sk = "oSWREzzKUi0vsaT3YPNbJDNp3YU7vI"


# 修改provider.tf中的value
# 配置云厂商
provider "alicloud" {
  region     = "cn-shanghai"
  access_key = var.ak
  secret_key = var.sk
}
  • 1
  • 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

在terraform.tfvars中的变量可以用var.<变量名>的方式跨文件使用

Terraform加载变量值的顺序

1、环境变量【快速开始中的设置】

2、terraform.tfvars文件

3、terraform.tfvars.json文件

4、所有的.auto.tfvars或者.auto.tfvars.json文件,以字母顺序排序处理

5、通过-var或是-var-file命令行参数传递的输入变量,按照在命令行参数中定义的顺序加载

data { }

我们可以通过输入参数、过滤参数,得到我们所需要的数据。

image-20230105163730304

例子:创建三个不同名实例名的实例,通过过滤wyh-的名字前缀(name_regex),过滤出想要的模块,再使用output输出实例id。

# 创建ECS实例
resource "alicloud_instance" "instance" {
 # cn-shanghai
 availability_zone = "cn-shanghai-b"
 security_groups = ["${alicloud_security_group.nsg1.id}"]
 instance_type = "ecs.n1.small"
 system_disk_category = "cloud_ssd"
 image_id = "centos_7_9_x64_20G_alibase_20220824.vhd"
 instance_name = "wyh-terraform"
 vswitch_id = alicloud_vswitch.vsw_1.id
 internet_max_bandwidth_out = 1
 password = local.ins_passwd
}

#第一个实例下添加内容
resource "alicloud_instance" "instance2" {
 # cn-shanghai
 availability_zone = "cn-shanghai-b"
 security_groups = ["${alicloud_security_group.nsg1.id}"]
 instance_type = "ecs.n1.small"
 system_disk_category = "cloud_ssd"
 image_id = "centos_7_9_x64_20G_alibase_20220824.vhd"
 instance_name = "wyh-terraform2"
 vswitch_id = alicloud_vswitch.vsw_1.id
 internet_max_bandwidth_out = 1
 password = local.ins_passwd
}

resource "alicloud_instance" "instance3" {
 # cn-shanghai
 availability_zone = "cn-shanghai-b"
 security_groups = ["${alicloud_security_group.nsg1.id}"]
 instance_type = "ecs.n1.small"
 system_disk_category = "cloud_ssd"
 image_id = "centos_7_9_x64_20G_alibase_20220824.vhd"
 instance_name = "haha-terraform3"
 vswitch_id = alicloud_vswitch.vsw_1.id
 internet_max_bandwidth_out = 1
 password = local.ins_passwd
}

# 以名字前缀进行模块的过滤
data "alicloud_instances" "wyh-xxx" {
    name_regex = "wyh-"
}

# id取值与官网Data sources的Attributes Reference,为什么要加入*,因为有多个实例id,如果需要第一个就输入0.id,如此类推。
output "wyh_ins" {
    value = data.alicloud_instances.wyh-xxx.instances.*.id
}

locals {
  ins_passwd = "5jejYWzSjZhWQc7G22"
}
# 这个public_ip取值与官网的Attributes Reference
output "ecs_public_ip" {
  value       = alicloud_instance.instance.public_ip
  description = "this is alicloud_instance public IP"
}

# password来源于ecs的资源模块
output "ecs_passwd" {
  value       = alicloud_instance.instance.password
  sensitive = true
  description = "this is alicloud_instance password"
}

  • 1
  • 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
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

ecs-data的过滤方式【官网】

还能打标签去过滤,好!

image-20230105170524444

*为通配符,0、1、2可以选择实例id的顺序

image-20230105170325522

apply后发现过滤出实例名前缀为wyh-的两个实例id

image-20230105165314946

总结

1、数据源允许查询或计算一些数据【过滤信息】以供其他地方使用(output)

2、如果使用data的时候,data还未获取到该资源,则会报错。需要先有data获取到的资源,才 能引用data的输出数据。

概念小结

1、loacl是私有变量,variables是公用变量。

2、variable需要创建两个文件,terraform.tfvars文件名不要写错。

3、output可以直接输出模块中的值,也能输出data过滤的值,这些值能够在其他模块中使用。

Terraform文件组成及规范

terraform可以把所有内容都统一写在一个.tf文件中,但项目大了之后不便于阅读和管理,故建议分开层级。

单层级

代码塞一起,一个main.tf就包含了所有资源信息。【provider{}的概念中有分解为多层级的过程】

多层级

代码分开,有些文件名不能写错,会影响Terraform执行的读取

模块与多层级

阿里云模块设置【官网】

要求

层级不宜没有,也不宜过深。

不宜混乱,也不宜过于细致。

层级不宜嵌套过多,也不宜调用过乱。

image-20230105172507678

1、框架搭建

modules像个子配置文件,Terraform执行的时候也会读取modules文件夹中声明的资源

image-20230106151724776

层级如下

image-20230105175355970

2、拆分后的分析 编写variables.tf

文件拆分完之后我们会知道我们拆分完的文件都需要那些变量

image-20230105182019752

image-20230105182046528

ecs需要nsgid、vswitchid;security_groups需要vpcid。

编写ecs文件夹中的variables.tf

variable "vswitchid" {
  type        = string
  description = "ecs_instance need vswitchid"
}
# 官网可查类型
variable "nsgid" {
  type        = list(string)
  description = "ecs_instance need nsgid"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

编写security_groups文件夹中的variables.tf

variable "vpcid" {
  type        = string
  description = "nsg need vpc_id"
}
  • 1
  • 2
  • 3
  • 4

3、思考变量来源 编写outputs.tf

变量来着于哪?vpc/main.tf能输出vpcid、vswitchid;securit_groups/main.tf能输出nsgid。

编写vpc文件夹中的outputs.tf

output "vpc_id" {
  value = alicloud_vpc.vpc.id
}

output "vswitch_id" {
  value = alicloud_vswitch.vsw_1.id
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

image-20230106113231972

alicloud_vpc.vpc来自vac/main.tf中resrouce块的标签,id是官网中标识vpc能输出的值也是我们所需要的值。

image-20230106113456934

编写security_groups/outputs.tf

variable "vpcid" {
  type        = string
  description = "nsg need vpc_id"
}
  • 1
  • 2
  • 3
  • 4

4、项目主main中编写modue模块

我们需要通过module这个模块来将module文件夹下的子文件于变量关联起来,我们先写个框架,value后续填入

image-20230105181927960

source是module的来源地址,可以复制相对路径填入,根目录为terraform

image-20230106114310032

vswitchid、nsgid是ecs/variables.tf中的值【也就是ecs所需要的变量】,我们通过module在主main中,去于其他文件夹下的outputs的值联系起来,module.vpc.vswitch_id 内容来源分别是**【module+主main文件中的module名+对应的module的outputs.tf中的输出值】**

image-20230106140324739

module "ecs" {
  source = "./modules/ecs"
  vswitchid = module.vpc.vswitch_id
  nsgid     = module.nsg.nsg_id
}

module "nsg" {
  source = "./modules/security_groups"
  vpcid = module.vpc.vpc_id
}

module "vpc" {
  source = "./modules/vpc"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

5、init【重新初始化】 - plan【解决问题,确认资源信息】- apply

image-20230106143208095

使用module后需要init

image-20230106150707207

nsgid是个list,所以我直接加入一个【0】,三个实例一个安全组,在变量后都加入【0】

image-20230106150818269

很明显,很成功

因为我们设置了aksk的变量在主目录的中,但是在module下的provider无法调用,这样会比较麻烦,我们选择使用环境变量的方式将aksk填入。moudle中的provider关于aksk的值注释掉。

image-20230106151954302

export ALICLOUD_ACCESS_KEY="LTAI5tALCyMfmyHjhq8rYQTz"
export ALICLOUD_SECRET_KEY="oSWREzzKUi0vsaT3YPNbJDNp3YU7vI"
  • 1
  • 2

image-20230106152317390

至此一个优雅的Terraform就写好了。

容易踩坑的点

可读性方面[*]*好。这样获取所有属性的信息就不需要使用for循环了。

注意机器的资源如果是有 force new的,不会在原有机器上面修改,而是会删除重建,比如数ecs挂载2块数据盘 (之前的instance是一个data{}块),如果此时写2个data{}块,则会删除旧instance重新生成新的instance,很危 险,这是因为ecs的说明是force new,因此有这种说明的资源要注意。正确的做法是,找购买磁盘和附加磁盘的 函数,新购并附加到ecs上。

若文件资源A存在依赖B,要想删除资源A,需要先删除依赖于A的资源B。若不是正常顺序解绑,Terraform会卡死,只能Ctrl + C 发送SIGINT信号停止再次执行。

image-20230105180141424

创建磁盘: https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/ecs_disk

绑定磁盘到ECS: https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources /ecs_disk_attachment

建议

学习完本章后可以看这两篇文章查缺补漏,更进一步

Introduction · 《Terraform入门教程》 (lonegunmanb.github.io)

官网:https://developer.hashicorp.com/terraform/language
tALCyMfmyHjhq8rYQTz"
export ALICLOUD_SECRET_KEY=“oSWREzzKUi0vsaT3YPNbJDNp3YU7vI”


[外链图片转存中...(img-ol82AZtX-1673413321772)]

至此一个优雅的Terraform就写好了。

# 容易踩坑的点

可读性方面`[*]`比`*`好。这样获取所有属性的信息就不需要使用for循环了。

注意机器的资源如果是有 force new的,不会在原有机器上面修改,而是会删除重建,比如数ecs挂载2块数据盘 (之前的instance是一个data{}块),如果此时写2个data{}块,则会删除旧instance重新生成新的instance,很危 险,这是因为ecs的说明是force new,因此有这种说明的资源要注意。正确的做法是,找购买磁盘和附加磁盘的 函数,新购并附加到ecs上。

若文件资源A存在依赖B,要想删除资源A,需要先删除依赖于A的资源B。若不是正常顺序解绑,Terraform会卡死,只能Ctrl + C 发送SIGINT信号停止再次执行。

[外链图片转存中...(img-SNRrj8HR-1673413321772)]

创建磁盘: https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/ecs_disk

绑定磁盘到ECS: https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources /ecs_disk_attachment



# 建议

学习完本章后可以看这两篇文章查缺补漏,更进一步

[Introduction · 《Terraform入门教程》 (lonegunmanb.github.io)](https://lonegunmanb.github.io/introduction-terraform/)

官网:https://developer.hashicorp.com/terraform/language
  • 1
  • 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
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/184875
推荐阅读
相关标签
  

闽ICP备14008679号