这些年,云计算发展迅速,越来越多的企业,把业务迁移到了云上。但是,云基础设施的管理,也变得越来越复杂。手动创建和管理云资源,不仅效率低,而且容易出错,也很难做版本控制和审计。
基础设施即代码(Infrastructure as Code,IaC),就是为了解决这个问题而生的。通过代码来定义和管理基础设施,既可以版本控制,又可以自动化部署,还可以保证环境的一致性。
在众多的IaC工具中,Terraform,是目前最流行的一个。它由HashiCorp公司开发,支持AWS、Azure、GCP、阿里云等几乎所有主流云平台,也支持VMware、OpenStack等私有云平台。
今天,我就从基础到高级,详细讲解一下Terraform的配置方法。无论你是Terraform新手,还是有一定经验的开发者,都能从本文中获得收获。
一、Terraform基础
在开始配置之前,先简单介绍一下Terraform的基本概念。
1. 什么是Terraform
Terraform,是一个开源的基础设施即代码工具。它使用一种叫做HCL(HashiCorp Configuration Language)的配置语言,来定义基础设施资源。然后,通过Terraform的命令,来创建、修改、删除这些资源。
Terraform的核心思想,是"声明式"的。你只需要描述,你想要什么样的基础设施,Terraform就会帮你实现。你不需要告诉它,具体怎么一步步做,它会自己计算,需要创建哪些资源,修改哪些资源,删除哪些资源。
2. Terraform的工作流程
Terraform的工作流程,通常包括以下几个步骤:
- Write(编写):用HCL编写配置文件,定义你想要的基础设施。
- Plan(计划):运行
terraform plan,Terraform会根据配置文件,计算出需要执行的操作,展示给你看。你可以检查,这些操作是不是你想要的。 - Apply(应用):运行
terraform apply,Terraform会执行plan中计算出的操作,创建、修改或删除资源。 - Destroy(销毁):运行
terraform destroy,Terraform会销毁配置文件中定义的所有资源。
这个工作流程,非常清晰,也非常安全。因为,在apply之前,你可以通过plan,先看一下,Terraform会做什么,确认无误后,再执行。
3. 安装Terraform
安装Terraform很简单。你只需要去官网,下载对应操作系统的二进制文件,然后,把它放到PATH环境变量包含的目录里,就可以了。
安装完成后,运行terraform version,如果能看到版本号,就说明安装成功了。
二、基本语法
Terraform的配置文件,使用HCL语言,后缀名是.tf。下面,介绍一下HCL的基本语法。
1. 资源(Resource)
资源,是Terraform中最基本的概念。一个资源,代表一个基础设施对象,比如一台EC2实例,一个S3存储桶,一个VPC网络等。
资源的定义语法如下:
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "example-instance"
}
}上面的代码,定义了一个AWS EC2实例。其中,aws_instance是资源类型,example是资源名称。资源类型和资源名称,组合起来,唯一标识一个资源。花括号里面,是资源的参数,比如AMI ID、实例类型、标签等。
2. 提供者(Provider)
提供者,是Terraform和云平台之间的桥梁。每个云平台,都有对应的提供者。比如,AWS的提供者是aws,Azure的提供者是azurerm,GCP的提供者是google。
提供者的配置,通常包括认证信息、区域等。比如:
provider "aws" {
region = "us-west-2"
access_key = "your-access-key"
secret_key = "your-secret-key"
}不过,不建议把accesskey和secretkey直接写在配置文件里。更好的做法是,使用环境变量,或者共享凭证文件,或者IAM角色。
3. 变量(Variable)
变量,可以让你的配置更加灵活,更加可复用。你可以把一些会变化的值,定义成变量,然后,在不同的环境中,传入不同的值。
变量的定义语法如下:
variable "instance_type" {
description = "EC2实例类型"
type = string
default = "t2.micro"
}使用变量的时候,用var.变量名的方式:
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = var.instance_type
}变量的值,可以通过多种方式传入。比如,命令行参数-var,变量文件-var-file,环境变量TFVAR变量名,或者交互式输入。
4. 输出(Output)
输出,可以把资源的某些属性,输出出来,供你查看,或者供其他配置使用。
输出的定义语法如下:
output "instance_public_ip" {
description = "EC2实例的公网IP"
value = aws_instance.example.public_ip
}运行terraform apply之后,你就可以在输出中,看到EC2实例的公网IP了。
5. 数据源(Data Source)
数据源,可以让你从外部获取数据,然后,在配置中使用。比如,你可以通过数据源,获取一个已经存在的VPC的信息,获取最新的AMI ID,获取当前账户的信息等。
数据源的定义语法如下:
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"]
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
}
}使用数据源的时候,用data.数据源类型.数据源名称.属性的方式:
resource "aws_instance" "example" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
}三、进阶用法
掌握了基本语法之后,我们来看一些进阶用法。
1. 模块(Module)
模块,是Terraform中代码复用的主要方式。你可以把一组相关的资源,封装成一个模块,然后,在不同的配置中,调用这个模块。
比如,你可以封装一个"VPC模块",包含VPC、子网、路由表、网关等资源。然后,在不同的环境中,调用这个模块,传入不同的参数,就可以创建出不同的VPC。
模块的目录结构,通常如下:
modules/
vpc/
main.tf
variables.tf
outputs.tf调用模块的语法如下:
module "vpc" {
source = "./modules/vpc"
vpc_cidr = "10.0.0.0/16"
public_subnets = [
"10.0.1.0/24",
"10.0.2.0/24",
]
private_subnets = [
"10.0.10.0/24",
"10.0.11.0/24",
]
}模块,是Terraform中非常重要的概念。合理使用模块,可以让你的配置,更加清晰,更加可复用,也更容易维护。
2. 状态管理(State)
Terraform通过状态文件,来记录它管理的资源的信息。默认情况下,状态文件保存在本地,文件名是terraform.tfstate。
状态文件,非常重要。它记录了资源和配置之间的映射关系。Terraform在执行plan和apply的时候,都会读取状态文件,来判断,哪些资源需要创建,哪些需要修改,哪些需要删除。
如果状态文件丢失了,Terraform就不知道,它管理了哪些资源,就可能会重复创建,或者无法修改。所以,一定要妥善保管状态文件。
对于团队协作来说,本地状态文件,是不够的。因为,每个人的本地状态,可能不一样,会导致冲突。所以,通常会使用远程状态,把状态文件,保存在共享的存储中,比如S3、GCS、Azure Blob Storage等。
配置远程状态的语法如下:
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-west-2"
}
}使用远程状态,不仅可以实现团队协作,还可以启用状态锁定,防止多人同时修改,导致状态冲突。
3. 工作区(Workspace)
工作区,可以让你在同一个配置下,管理多个环境。比如,开发环境、测试环境、生产环境。每个工作区,都有自己独立的状态文件。
创建工作区的命令:
terraform workspace new dev切换工作区的命令:
terraform workspace select dev查看当前工作区的命令:
terraform workspace show在配置中,可以通过terraform.workspace,获取当前工作区的名称,然后,根据不同的工作区,使用不同的配置。比如:
variable "instance_type" {
type = map(string)
default = {
dev = "t2.micro"
test = "t2.small"
prod = "t2.large"
}
}
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = var.instance_type[terraform.workspace]
}工作区,是管理多环境的一个简单有效的方式。但是,对于复杂的多环境管理,还是建议使用模块,配合不同的配置目录。
4. 条件表达式和循环
Terraform 0.12之后,引入了条件表达式和循环,让配置更加灵活。
条件表达式的语法,和很多编程语言类似:
condition ? true_value : false_value比如,根据环境,决定是否创建资源:
resource "aws_instance" "example" {
count = terraform.workspace == "prod" ? 1 : 0
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.large"
}上面的代码,只有在prod工作区,才会创建EC2实例。
循环,可以用for_each,来遍历一个集合,创建多个资源:
variable "subnets" {
type = map(string)
default = {
"subnet-1" = "10.0.1.0/24"
"subnet-2" = "10.0.2.0/24"
"subnet-3" = "10.0.3.0/24"
}
}
resource "aws_subnet" "example" {
for_each = var.subnets
vpc_id = aws_vpc.example.id
cidr_block = each.value
availability_zone = "us-west-2a"
tags = {
Name = each.key
}
}上面的代码,会根据subnets变量,创建三个子网。
四、最佳实践
最后,分享一些Terraform的最佳实践。
1. 目录结构要清晰
一个好的Terraform项目,目录结构应该清晰。通常,根目录放主配置,模块放在modules目录,变量文件按环境分开。比如:
.
├── main.tf
├── variables.tf
├── outputs.tf
├── provider.tf
├── terraform.tfvars
├── modules/
│ ├── vpc/
│ ├── ec2/
│ └── rds/
└── environments/
├── dev/
├── test/
└── prod/2. 使用模块,避免重复代码
不要把所有的资源,都写在一个大文件里。应该把相关的资源,封装成模块,然后,在主配置中调用。这样,既减少了重复代码,又让配置更加清晰,更容易维护。
3. 变量和输出要规范
变量,应该有明确的描述、类型和默认值。不要使用未定义的变量,也不要在配置中硬编码值。
输出,应该只输出必要的信息。不要输出敏感信息,比如密码、密钥等。
4. 使用远程状态,启用状态锁定
对于团队协作,一定要使用远程状态,并且启用状态锁定。这样,可以避免状态冲突,也可以保证状态文件的安全。
5. 执行plan,确认后再apply
在执行apply之前,一定要先执行plan,仔细检查,Terraform会做哪些操作。确认无误后,再执行apply。不要直接执行apply,那样,可能会导致意外的资源修改或删除。
6. 版本控制
Terraform配置文件,一定要用Git等版本控制工具管理。这样,可以追踪配置的变更历史,也可以在出问题的时候,回滚到之前的版本。
但是,状态文件,不要提交到版本控制。因为,状态文件中,可能包含敏感信息,而且,状态文件是动态变化的,不适合版本控制。
五、写在最后
Terraform,是一个非常强大的基础设施即代码工具。掌握了它,你就可以用代码,来管理你的云基础设施,实现自动化部署,保证环境一致性,提升工作效率。
本文,从基础到高级,介绍了Terraform的配置方法,包括基本语法、资源管理、变量和输出、模块、状态管理、工作区、以及最佳实践。希望能给你带来一些帮助。
当然,Terraform的内容,远不止这些。还有很多高级特性,比如自定义提供者、Terraform Cloud、Terraform Enterprise等,值得深入学习。
如果你对Terraform感兴趣,建议你动手实践一下。找一个云平台的免费账号,跟着教程,一步步配置,你会发现,Terraform其实并不难。
希望这篇文章,能帮你入门Terraform。如果你有任何问题,欢迎在评论区留言,我们一起交流。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录