作者 | 何贵民 阿里云开放平台高级开发工程师 主要负责开源生态工具(Terraform,Ansible,Spinnaker)与阿里云的集成,专注于借助主流开源工具帮助企业上阿里云和云上运维提效
1 Terraform State简介
Terraform State 是用来存放基础设施资源及其属性和状态的机制。上篇文章《一分钟部署阿里云ECS集群》对State做了详细的阐述,本文将在此基础上做一点补充。
Terraform State 从存储形态上分为两种:
- local:本地存储
即资源状态存放在本地的一个state文件中,默认为执行目录下的名为terraform.tfstate
文件。此方式也是Terraform默认的存储形式。 - remote:远端存储
即资源状态存放在远端的一个服务中,如阿里云的OSS,Terraform Cloud,HashiCorp Consul等。远端存储带来的好处是实现了与资源定义模板管理的解耦,可以让State脱离本地磁盘而存储,在提升State安全性的同时,团队协作可以不再受制于Terraform的执行环境,执行目录和多人执行时间的限制,提升了管理的灵活性。
Terraform State的存储是由一个称之为 Backend
的组件决定的,local state使用的是local backend。除了local backend,其他所有的backend在使用之前都需要在模板中显示定义并通过 terraform init
来实现加载和配置。
2 Terraform Backend简介
Backend
是存储State的机制,它决定了State数据的加载逻辑和Terraform命令执行之后State的数据的更新过程。如下是Terraform生命周期中与Backend的交互过程。
Terraform 通过 init
命令完成Backend的加载和配置。执行 plan
和 apply
的命令,在加载资源模板的同时,通过Backend加载State中的存量数据(如果有);命令结束后,将Provider/Provisioner响应中的数据通过Backend更新到State中,最终达到State数据与模板定义的一致。
从功能实现级别的角度,Backend可以分为两种:
- Standard
即State管理的标准化实现,覆盖标准的功能点“State存储”和“State加锁”。这种Backend目前只适用于在本地系统上运行所有操作的场景,尽管也实现了对State的远程存储,但Backend的执行逻辑仍发生在本地并通过直接调用API请求来完成。
目前这种Backend总共有13种,阿里云的OSS Backend也属于此类。
- Enhanced
可以看作是Standard
的加强版,即Backend的执行逻辑不仅可以发生在本地,还可以通过API或者CLI的方式发生在远端。目前这种Backend的种类有两种,一是local
,另一个是只支持Terraform Cloud的remote
。
阿里云也提供了一个标准的Backend - oss
,在Terraform 0.12.2中予以支持,并在Terraform 0.12.6 和 0.12.8 版本中对 oss
进行了升级,支持 profile
设置, ecs_role_name
, assume_role
等鉴权方式。
3 阿里云 OSS Backend详解
OSS Backend 是基于阿里云的表格存储服务(OTS)和对象存储服务(OSS)实现的Standard Backend,其中OTS用来存储运行过程中产生的“Locking”,保证State的正确性和完整性;OSS用来存储最终的State文件。接下来将详细介绍OSS Backend。
3.1 工作原理
OSS Backend的工作流程可以分为加锁,存储State,释放锁三步,下图是一个简单的工作流程图:
主要包含以下几个部分:
- 运行Terraform命令后,Backend首先会从OTS中获取LockID,如果已经存在,表明State被损坏或者有人正在操作,返回报错;否则,自动生成一个LockID并存储在OTS中;
- 如果是
init
命令,初次会生成一个新的state文件并存储在OSS的指定目录下,并释放LockID; - 如果是
plan
,apply
,destroy
等涉及到修改State的命令,会在命令结束后将最新的数据同步更新到State文件中,并释放LockID; - 如果是
state
,`` show 等不涉及修改的操作,会直接读取State内容并返回。
3.2 模板定义
和Provider一样,Backend在使用时同样需要在模板中定义。Backend 通过关键字 backend
来声明:
terraform {
backend "oss" {
profile = "terraform"
bucket = "terraform-oss-backend-1024"
key = "prod/terraform.tfstate"
tablestore_endpoint = "https://tf-oss-backend.cn-hangzhou.ots.aliyuncs.com"
tablestore_table = "terraform-oss-backend-1024"
acl = "private"
encrypt = true
...
}
}
对 backend
的定义包含如下几个部分:
-
terraform
为运行主体,定义了Backend
的操作主体。Backend 的逻辑实现是存放在 Terraform 仓库中的,服务于所有Provider和Provisioner,因此它的运行主体是terraform
,而不是具体某个Provider; -
oss
为Backend类型,用来标识一个特定的Backend; - 大括号里面的内容为参数配置,用来定义Backend属性,比如鉴权信息,OSS Bucket的名称,存放路径,OTS配置信息等。更多参数和含义可参考官方文档:
https://www.terraform.io/docs/backends/types/oss.html
如上代码声明了一个 oss
backend,其中state存储在名为“terraform-oss-backend-1024”的bucket中,对应的文件为“prod/terraform.tfstate”,并声明state文件为只读和加密;锁信息存储在一个名为“terraform-oss-backend-1024”的表格中,这个表格位于杭州的OTS实例“tf-oss-backend”中。
3.3 一键生成OSS Backend模板
为了更快捷的编写OSS Backend模板,阿里云提供了一个Terraform Module:remote-backend,可用来自动生成OSS Backend模板:
module "oss-backend" {
source = "terraform-alicloud-modules/remote-backend/alicloud"
create_backend_bucket = true
create_ots_lock_instance = true
create_ots_lock_table = true
region = "cn-hangzhou"
state_name = "new/terraform.tfstate"
encrypt_state = true
}
运行完成后,会在当前目录下生成一个名为 terraform.tf
的配置文件,文件内容即为已经配置好的OSS Backend:
terraform {
backend "oss" {
bucket = "terraform-remote-backend-94a22ee-0714-e8ef-8573-21df8b021f86"
prefix = "env:"
key = "new/terraform.tfstate"
acl = "private"
region = "cn-hangzhou"
encrypt = "true"
tablestore_endpoint = "https://tf-oss-backend.cn-hangzhou.ots.aliyuncs.com"
tablestore_table = "terraform_remote_backend_lock_table_38001042_0714_e8ef_8573_21df8b021f86"
}
}
生成后的 terraform.tf
可以直接跟目标模板放在同一个目录下,以用于对后续State的远端存储。
如果想把生成 terraform.tf
的state也存放在上述的OSS Backend中,只需再次运行 terraform init
命令,本地目录下的local state将会自动同步到OSS Backend中,如下所示:
总结
OSS Backend遵循Standard Backend的实现逻辑,覆盖“State存储”和“State加锁”两大功能点,保证了State的安全性和体验的一致性。借助OSS服务的安全,高可靠和OTS服务的实时访问等特点,为用户提供了标准的,安全可靠的远端存储State的能力。
OSS Backend对Terraform用户,尤其是阿里云Provider的用户无疑是一大利好,在降低资源管理成本的同时,为团队协作提供了更多的便利。