Terraform(一)

在这里插入图片描述

Terraform ['terəfɔ:m] 是 Hashicorp 公司开源的一种多云资源编排工具。使用者通过一种特定的配置语言(HCL - Hashicorp Configuration Language)来描述基础设施,由 Terraform 工具统一解析,构建资源之间的关系,生成执行计划,并通过调用各家云厂商的具体实现来完成整个基础设施生命周期的管理。

Terraform - Infrastructure as Code

官网 https://www.terraform.io/
中文官网 https://www.gaia.net/sc/brands_detail/0/0/93/hashicorp-terraform
教程 https://developer.hashicorp.com/terraform/tutorials

在这里插入图片描述

1. 相关概念

1.1 什么是 IaC

基础架构即代码 (Infrastructure as Code, IaC) 是指通过代码(而不是手动流程/控制台点击)来管理和配置基础架构

这里有两个关键词:

  • Infrastructure
  • Code

Infrastructure 是被管理对象,在这里主要是指公有云(还有私有云、混合云等)
Code 是管理方式,即像管理代码一样管理公有云资源。那么管理代码最重要的部分是版本管理。

使用 IaC,创建的配置文件包含了基础设施的 spec,这使得编辑和分发配置变得更加容易。IaC 还确保每次都提供相同的环境、相同的资源、相同的配置。通过编辑和记录配置的 spec,IaC 有助于避免未记录的、临时的配置更改(当然,前提是所有人都使用 IaC,而不是还会有人在控制台点击修改导致配置漂移)。

版本控制是 IaC 的重要组成部分,配置文件应该像任何其他软件源代码文件一样受到源代码控制。 另外,随着公有云的发展,公有云的标准化的 API 也使得将基础架构组件模块化 (Terraform 里叫做 modules) 成为可能,使用者可以像搭积木一样组合这些基础的组件。比如:在 AWS 上建个静态博客,就可以组合以下组件:

  • Route53
  • CloudFront
  • S3

IaC 的两种实现方式

有两种实现 IaC 的方法:声明式和命令式

  • 声明式方法定义了系统的理想状态,包括需要的资源以及它们应该具有的任何属性,IaC 工具将自动配置它。
    Terraform 就是基于 IaC 声明式的理念。在 Terraform 流行之前,另一个将声明式发扬光大的当然是:Kubernetes!
    声明式方法还保留系统对象当前状态的列表,这使得拆除基础架构更易于管理。

  • 相反,命令式方法定义了实现所需配置所需的特定命令,然后需要以正确的顺序执行这些命令。
    典型的就是 Ansible.

IaC 工具通常能够在两种方法中运行。如 Terraform, 它更喜欢声明式的方法,但是它的 Provider、Modules、函数中仍然残留不少命令式的方法, 如:local-exec

IaC 的好处

IaC(特别是声明式的)是随着公有云而发展起来的。

置备基础设施历来是一个耗时且成本高昂的手动过程。现在基础设施管理已经从数据中心的物理硬件、虚拟化转移到容器和云计算。借助云计算,基础设施组件的数量不断增加,每天都有更多的应用程序发布到生产环境中,并且基础设施需要能够频繁地启动、扩展和关闭。如果没有适当的 IaC 实践,管理当今基础设施的规模会变得越来越困难。
IaC 可以帮助您的组织管理 IT 基础设施需求,同时提高一致性并减少错误和手动配置。

IaC 优点

  • 降低成本
  • 提高部署速度
  • 减少(手动配置)错误
  • 提高基础设施一致性
  • 消除配置漂移

IaC 工具

目前主流的有:

  • 声明式:

      Terraform
      AWS CloudFormation
      Pulumi
      CrossPlane
    
  • 命令式:

      Puppet
      Chef
      Ansible
      SaltStack
    

为什么 IaC 对 DevOps 很重要?

IaC 是实施 DevOps 实践和 CI/CD 的重要组成部分。DevOps 和 CI/CD 主要是应用和组件层面的, 而 IaC 消除了开发人员的大部分配置工作,开发人员可以执行脚本让他们的基础设施准备就绪。这样一来,应用程序部署就不会因等待基础架构而停止,系统管理员也不需要管理耗时的手动流程。那么整个开发部署迭代的流程就会越来越快, 越来越快。

IaC 帮助您协调开发和运维,因为两个团队可以在代码仓库中看到基础架构全貌。而且每个环境都可以使用相同的部署过程。环境一致性也有保障,开发上测试通过的,生产上出问题的概率也小。

DevOps 最佳实践也适用于 IaC 中的基础架构。基础设施可以通过与应用程序在软件开发期间相同的 CI/CD 管道,对基础设施代码应用相同的测试和版本控制。将 IaC 的 modules 代码也引入 DevOps 理念,快速测试,快速迭代。

毋庸置疑,Terraform 是 IaC 领域事实上的领导者。

1.2 什么是 Terraform

Terraform 是一个安全、高效地部署、更改、版本化基础设施和应用程序的工具,可以用来管理多层次的资源。从上层的软件配置到底层的网络、系统配置都可以使用 Terraform 统一进行管理。

Terraform 用配置文件来描述一个应用。Terraform 会将配置文件与当前环境对比后,生成一个执行计划,这个计划会列出为了达到配置文件中定义的状态所需要执行的操作,然后执行计划以达到期望的状态。

Terraform 通过插件机制管理不同的资源提供者,以此来接入各种资源,如虚拟机,存储,网络和各种应用服务。
在这里插入图片描述

1.3 Terraform 的主要特性

  • Infrastructure as Code
    基于 IaC的设计,可以将基础设施以一种领域特定语言描述出来,消除了在基础设施自动化时描述语义上的歧义,同时减轻了人为因素造成的不确影响。将基础架构使用配置语法进行描述,这可以让数据中心的构建计划可以像其他代码一样进行版本化和追踪。
  • Execution Plans
    Terraform有一个规划步骤,它生成一个执行计划。执行计划显示当您调用应用程序时 Terraform 将执行的操作。关键基础设施的变更可以得到充分审查,保证了基础设施的可靠性。
  • Resource Graph
    Terraform 创建了一个所有资源的视图。基于 DAG(有向无环图,Directed Acyclic Graph)描述资源与资源之间的关系,由于 DAG 良好的拓扑性质,当资源属性与资源关系发生改变时,变更动作将被充分并行地执行。 Terraform 可以并行化没有依赖的创建与修改。因此,Terraform 可以高效地构建基础架构。操作人员也能更加了解环境的结构。
  • Change Automation
    Terraform 会自动的分析什么是需要修改的,从而避免了许多可能的人为错误。

1.4 Terraform 架构

Terraform 是一款基于插件的工具,因此其有一个核心应用 Terraform,和上百个插件。核心应用提供了一个统一的层来管理 IaC 代码,并且它还会负责安装所需的插件,调用它们、管理状态等。另一方面,插件可以与基础设施平台和应用通信,如AWS、GCP、Grafana、Jenkins、GitLab等。其中一些插件由 Hashicorp 团队维护,另外的那些则是由第三方维护。每个人都可以编写并发布自己的插件,访问下方网站可以获取插件库:https://registry.terraform.io/

在这里插入图片描述
Terraform 插件由两大主要类型:Provider 和 Provisioner

  • Provider 是通过 API 负责与实际基础设施或应用进行连接,并创建、修改和删除对象和资源。
  • Provisioner 是负责连接已经配置好的基础设施并对其进行更改。例如,你可以使用 AWS Provider 来配置一个 EC2 实例,并在配置完成后远程执行 Provisioner 在实例上执行某些命令行。(需要注意的是,Provisioner 通常不是最佳实践)

1.5 Terraform 核心概念

Terraform 中使用的核心概念/术语:

  • Variables:也被称为 input-variables(输入变量),它是 Terraform 模块使用的键值对,可以自定义。
  • Provider:一种插件类型,与 API 服务进行交互并访问相关资源。
  • Module:它是一个包含 Terraform 模板的文件夹,所有的配置都可以在这里定义。
  • State:它由 Terraform 管理的基础设施和相关配置的缓存信息组成。
  • Resources:它指一个或多个基础设施对象(计算实例、虚拟网络等)的块(block),这些对象用于配置和管理基础设施。
  • Data Source:它是由 provider 实现的,以返回外部对象的信息到 Terraform。
  • Output Values:这是 Terraform 模块的返回值,可以被其他配置使用。
  • Plan:这是指其中一个阶段,在这一阶段中会决定需要创建、更新或销毁什么,以便从基础设施的 real/current 状态转移到期望状态。
  • Apply:这一阶段会应用基础设施的更改 real/current 状态,以推动到期望状态。

1.6 Terraform 生命周期

Terraform 的生命周期由init、plan、apply和 destroy,4个阶段构成。

  • Terraform init 初始化工作目录,其中包括所有的配置文件。
  • Terraform plan 被用来创建执行计划以达到基础设施的期望状态。为了达到预期状态,会对配置文件进行更改。
  • Terraform apply 会对在 plan 阶段中定义的基础设施进行更改,从而使基础设施达到期望状态。
  • Terraform destroy 这一阶段用于删除所有的旧基础设施资源,这些资源在apply 阶段后被标记为污损(taint)。

1.7 Terraform 的工作原理

Terraform 可以让用户通过配置文件定义和管理整个基础设施和版本控制。这主要由 Terraform 架构中的两个主要组件来实现这一目标:Core 和 Provider

Terraform Core 如何工作

要完成工作,Terraform core 需要使用2个输入源。

  • 第一个源将用户配置输入到 Terraform,并定义需要创建或配置什么资源。
  • 第二个输入源包括向Terraform提供的关于当前基础设施设置情况的数据。

Terraform 会获取这些输入信息并决定下一步应该如何进行。它采用用户指定的期望状态,并将其与当前状态进行对比,进而对架构进行配置以消除两种状态之间的差距。Terraform core 本质上是要计算出需要创建、更新或删除的内容,以便全面配置基础设施

Terraform Provider 如何工作

第二个让 Terraform 运行的关键组件是 provider。常见的是云厂商,如 AWS 或 Azure,但其他基础设施或平台服务工具也可以。例如,Kubernetes 也是 Terraform 用的一个 provider。

Terraform 有上百个不同技术的 Provider 可供用户访问。例如,如果你正在使用 AWS,Terraform 可以访问 EC2 实例和在这一技术栈内的其他资源。接着,用户可以在不同层级上创建基础设施,比如在 Azure 上构建 Kubernetes。

这就是 Terraform 的工作原理:使用 Core 和 Provider 功能来快速完成应用程序和基础设施的设置,并且仅仅使用代码即可

1.8 Terraform 工作流程

Terraform 的工作流程由以下3个步骤组成:

  • Step 1:
    在 Terraform 工作流程的第一步中,用户需要使用 Haschicorp Configuration Language (HCL)来将基础设施资源声明为代码。

  • Step 2:审核
    接下来,Terraform 会展示其计划,它会根据用户设置的期望状态和现有资源的当前状态进行比较,来增加或移除资源。

  • Step 3:应用
    最终,接受计划的更改,来增加或删除任何基础设施资源。然后基础设施将在 Terraform 的帮助下进行全面部署。

2. Terraform vs Other Software

与 Terraform 类似的 Infrastructure as Code 工具大概有下面几种:

  • Chef
  • Puppet
  • Ansible
  • SaltStack
  • CloudFormation

下面将从几个方面来说明 Terraform 与其他工具对比的优势。

2.1 配置管理工具与编排工具

Chef、Puppet、Ansible、SaltStack 都可以称为配置管理工具,这些工具的主要目标是在已经存在的机器上安装和管理软件。而 Terraform 和 CloudFormation 可以称为编排工具,更注重于数据中心以及相关服务的高级抽象。他们的工作重点是创建资源并且引导进行初始化。

在现在的环境下,大家使用容器等服务,镜像已经包括了软件的安装与配置。一旦你有了镜像,你需要的是一些服务器去运行它。对于提供服务器这种需求,编排工具会比配置管理工具更适合做此类工作。

2.2 编程(/命令)式语言与声明式语言

Chef 和 Ansible 希望你去一步步编写程序以达到最终所期望的状态。
Terraform、CloudFormation、SaltStack、Puppet 希望你去声明最终想要的资源与资源的状态,工具本身会自动分析达到想要的状态需要进行怎样的操作。

在使用编程式语言时,工具不会获取历史的状态,所以我们需要考虑的更多以达到与之前版本的兼容。并且使用编程式语言会导致代码库变得越来越庞大,不利于人们理解与代码的复用。不过声明式的语言的表达能力是较为欠缺的,例如我们需要基础设施的滚动升级时,声明式的语言是很难满足要求的。

为此 Terraform 提供了一些基础服务,例如输入变量,输出变量,在销毁之前创建等。

2.3 C/S架构与客户端架构

Chef、Puppet、SaltStack 在默认情况下都使用了C/S架构。客户端(可能是 Web UI 或 CLI 工具)是用来发出命令(例如「deploy X」)的东西。

这些命令到达一个服务器,它负责执行你的命令并存储系统的状态。要执行这些命令,服务器会与 agent 进行通信,agent 必须在要配置的每个服务器上运行,这有几个缺点:

  • 必须在每台服务器上安装并运行额外的软件
  • 为了配置管理,您必须部署额外的服务器(甚至是一组服务器以实现高可用性)
  • 由于客户端,服务器和代理都需要通过网络进行通信,因此您必须为其打开额外的端口,并配置相互验证
  • 这些配置会引入大量不同类型的故障,当收到错误警告时,必须要弄清楚是哪一部分出现了故障

CloudFormation 也是C/S架构,但 AWS 透明地处理所有的服务器细节,作为最终用户,您只需要考虑客户端代码。
Ansible 客户端则通过 SSH 直接连接到您的服务器。
Terraform 使用云提供商 API 来配置基础架构,因此除了您已经使用云提供商之外,没有新的身份验证机制,并且不需要直接访问您的服务器。

综合对比

分类 Chef Puppet Ansible SaltStack CloudFormation Terraform
是否开源 开源 开源 开源 开源 闭源 开源
支持的云 All All All All AWS only All
工具类型 配置管理 配置管理 配置管理 配置管理 编排工具 编排工具
语言类型 编程式 编程式 编程式 声明式 声明式 声明式
架构 C/S C/S 客户端 C/S 客户端 客户端

原著这里提到的客户端架构,笔者理解为不需要额外安装或运行客户端程序,例如jenkins的节点需要运行agent.jar,所以是C/S架构。而ansible直接可以通过ssh(大部分系统自带)进行通信,则为客户端架构。

3. Terraform 的应用场景

3.1 应用场景 - Loadbalancer

某应用使用了 Loadbalancer 进行 Instance 间的流量均衡处理,以增大吞吐率、扩大并发数、缩短延迟。
在这里插入图片描述

  • 操作步骤:
    新建安全组、添加安全组规则、申请弹性公网 IP、创建负载均衡器、创建 Instance、在负载均衡器中添加负载均衡器监听器、配置会话保持、添加健康检查、在负载均衡器监听器中添加后端……

3.2 应用场景 - VPC

某应用需要隔离的网络环境,需要将应用搭建在 VPC 网络当中,架构如下:
在这里插入图片描述

  • 操作步骤:
    创建安全组、配置安全组、申请弹性公网 IP、创建 VPC、创建 vxnet、创建负载均衡器、配置负载均衡器、创建 Instance 等配置操作。

VPC网络是指私有网络。私有网络(Virtual Private Cloud,VPC)是一块在公有云上自定义的逻辑隔离网络空间,您可以为 云服务器、云数据库 等资源构建逻辑隔离的、用户自定义配置的网络空间,以提升用户云上资源的安全性,并满足不同的应用场景需求。

3.3 应用场景 - 资源扩容

随着业务调整和业务量增大,需要增加更多的节点和集群以承载更多的请求,此时需要对已有的资源进行扩容:
在这里插入图片描述

3.4 应用场景 - 快速部署

随着应用的不断迭代,应用部署和发布的成本也在增加,如何实现应用的快速部署和发布:
在这里插入图片描述
上述场景的共性:

操作流程配置固定;
手工操作效率低、时间长;
手工操作可能导致错误;
手工操作过程没有历史记录;
手工操作过程不能审计;
手工操作随着业务的复杂而不断增大。

3.5 使用 Terraform 自动化一切

  • 针对场景一、二:创建基础设施
    使用 Terraform,我们可以对基础设施进行编码,利用代码来进行资源的增删查改。
  • 针对场景三、四:扩容和部署
    修改资源代码以改变基础设施,并利用 privisioner 帮助运行部署脚本,完成扩容和部署。
    在这里插入图片描述

3.6 工具获取

terraform-providers: 集成了当前几乎所有公有云的iac工具实现
terraform aws 工具集:封装了aws的iac工具实现,例如申请ec2,创建vpc等等
编写配置文件:内容为按照手工操作流程,逐个调用aws工具集的工具实现

4. Terraform 改善基础架构的十个最佳实践

参考链接:https://geekflare.com/terraform-best-practices/

4.1 结构化

当您使用 Terraform 处理大型生产基础设施项目时,需要遵循适当的目录结构来应对项目中可能出现的复杂性。建议为不同目的建立单独的目录。如果您在开发、暂存和生产环境中使用 Terraform,请为每个环境设置单独的目录。

Terraform 配置也应该是分开的,因为经过一段时间后,不断增长的基础设施的配置将变得更加复杂。

	geekflare@geekflare:~$ tree terraform_project/
	terraform_project/
	├── dev
	│ ├── main.tf
	│ ├── outputs.tf
	│ └── variables.tf
	├── modules
	│ ├── ec2
	│ │ ├── ec2.tf
	│ │ └── main.tf
	│ └── vpc
	│ ├── main.tf
	│ └── vpc.tf
	├── prod
	│ ├── main.tf
	│ ├── outputs.tf
	│ └── variables.tf
	└── stg
	├── main.tf
	├── outputs.tf
	└── variables.tf
	
	6 directories, 13 files

您可以在文件 main.tf 本身内编写所有的 Terraform 代码(模块、资源、变量、输出),同时为变量和输出设置单独的 Terraform 代码使其更具可读性和易于理解。

4.2 命名规则

Terraform 中使用命名规则让资源易于理解、一目了然。

例如,假设您要为项目中的不同环境创建三个不同的工作区。与其将环境命名为env1 、env2 、env3 ,不如尝试使用dev、stage、prod 来命名。从名称本身来看,很明显每个环境都代表着不同的工作空间。资源、变量、模块等的也遵循类似的规则。

Terraform 中的资源名称应以相关资源名称开头,后跟下划线和其他详细信息。例如,用于在 AWS 中为 route table 创建 Terraform 对象的资源名称为 aws_route_table

所以如果正确地遵循命名规则,即使是复杂的代码也会更容易理解。

4.3 使用共享模块

强烈建议使用可用的官方 Terraform 模块。直接使用现有模块,能够有效节省时间和精力。Terraform registry 有很多现成可用的模块,企业可以根据需要对现有模块进行更改。

此外,每个模块应该只专注于基础设施的一个方面,比如创建 AWS EC2 实例、设置 MySQL 数据库等。举个例子,如果您想在 terraform 代码中使用 AWS VPC,可以直接使用 -simple VPC

module "vpc_example_simple-vpc" {
    
    
source
= "terraform-aws-modules/vpc/aws//examples/simple-vpc"
version = "2.48.0"
}

4.4 使用最新版本

Terraform 开发社区非常活跃,新功能发布频繁。建议在发布新的主要版本时使用最新版本的 Terraform。您可以轻松升级到最新版本。如果跳过多个主要版本,升级将变得非常复杂。

运行terraform -v命令以检查版本更新。

geekflare@geekflare:~$ terraform -v
Terraform v0.11.14
Your version of Terraform is out of date! The latest version
is 0.12.0. You can update by downloading from www.terraform.io/downloads.html

4.5 备份系统状态

请始终备份 Terraform 的状态文件,这些文件跟踪基础设施的元数据和资源。默认情况下,这些名为terraform.tfstate的文件本地存储在工作区目录中。

如果没有这些文件,Terraform 将无法确定在基础设施上部署了哪些资源。因此,必须备份状态文件。默认情况下,terraform.tfstate.backup会被创建并用来保存状态文件的备份。

geekflare@geekflare:~$ tree terraform_demo/
terraform_demo/
├── awsec2.tf
├── terraform.tfstate
└── terraform.tfstate.backup
0 directories, 3 files

如果要将备份状态文件存储到其他位置,在 terraform 命令中使用-backup标记并提供位置路径。大部分情况下,一个项目会有多个开发人员参与。因此为了让开发人员方便访问状态文件。应该使用terraform_remote_state数据源将其存储在远程位置。

以下示例将备份到 S3。

data "terraform_remote_state" "vpc" {
    
    
backend = "s3"
config = {
    
    
bucket = “s3-terraform-bucket”
key = “vpc/terraform.tfstate"
region = “us-east-1”
   }
}

在这里插入图片描述

4.6 锁定状态文件

可能有多个场景,其中不止一个开发人员试图同时运行 Terraform 配置。这可能导致 terraform 状态文件损坏甚至数据丢失。锁定机制能够有效防止此类情况发生,确保一次只有一个人在运行 terraform 配置,并且没有冲突。

下面是使用 DynamoDB 锁定位于远程位置的状态文件的示例。

resource “aws_dynamodb_table” “terraform_state_lock” {
    
    
name = “terraform-locking”
read_capacity = 3
write_capacity = 3
hash_key = “LockingID”

attribute {
    
    
name = “LockingID”
type = “S”
   }

}
terraform {
    
    
backend “s3” {
    
    
bucket = “s3-terraform-bucket”
key = “vpc/terraform.tfstate”
region = “us-east-2”
dynamodb_table = “terraform-locking”
   }
}

当多个用户尝试访问状态文件时,DynamoDB 数据库名称和主键将用于状态锁定并保持一致性。注意:并非所有后端都支持锁定。

4.7 使用自变量

self变量是一种特殊的变量,当您在部署基础设施之前不知道变量的值时可以使用它。假设您要使用仅在 terraform apply 命令后部署的实例的 IP 地址,也就是在它启动并运行之前您是不知道 IP 地址的。

在这种情况下,您可以使用自变量self.ATTRIBUTE。在这个例子中,您可以使用self.ipv4_address作为自变量来获取实例的 IP 地址。这些变量只允许在 terraform 配置的连接和配置块上使用。

connection {
    
    
host = self.ipv4_address
type = "ssh"
user = var.users[2]
private_key = file(var.private_key_path)
}

4.8 最小化爆炸半径

爆炸半径(Blast Radius)是衡量如果流程没有按计划进行时可能发生的损害的量度。

例如,如果您在基础设施上部署了一些 Terraform 配置,但配置没有得到正确应用,那么对基础设施造成的损害会有多大。因此,为了尽量减少故障影响范围,建议每次配置的基础设施数量不宜过多。即便出现问题,对基础设施的损害也能控制在较小范围,并且可以迅速得到纠正。一次性配置大量基础设施是非常危险的。

4.9 使用 var 文件

在 terraform 中,您可以创建一个带有扩展名的文件<em>.</em>tfvars,并使用-var-file此文件传递给terraform apply命令。这个方式可以帮助您传递那些您不想放入 terraform 配置代码中的变量。

始终建议通过-var-file在本地传递密码、密钥等变量,而不是将其保存在 terraform 配置或远程位置版本控制系统中。

例如,如果您想使用 terraform 启动 ec2 实例,您可以使用-var-file传递访问密钥和其他机密信息。创建文件 terraform.tfvars 并将密钥放入此文件中。

geekflare@geekflare:~$ gedit terraform.tfvars

access_key = "AKIATYWSDFYU5DUDJI5F"
secret_key = "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"

然后在 terraform 命令中使用这个 var 文件。

geekflare@geekflare:~$ terraform apply -var-file=/home/geekflare/terraform.tfvars

4.10 使用 Docker

当您运行 CI/CD 流水线构建作业时,建议使用 docker 容器。Terraform 提供了可以直接使用的官方 Docker 容器。如果需要更改 CI/CD 服务器,您可以轻松地在容器内传递基础设施。

在生产环境上部署基础设施之前,您还可以在 docker 容器上测试基础设施,非常容易部署。通过结合 Terraform 和 Docker,您可以获得可移植、可重用、可重复的基础设施。

猜你喜欢

转载自blog.csdn.net/u010230019/article/details/131673826