《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新,书中的示例代码也是放在GitHub上,方便大家参考查看。
军书十二卷,卷卷有爷名。
为什么需要状态管理
Terraform的主要作用是管理云平台上的资源,通过声明式的HCL配置来映射资源,如果云平台上没有资源则需要创建,如果有则不用。那Terraform要实现这个功能有多种方式。
一种是每次执行apply命令时都调用API接口检查一下远程的云资源是否与配置文件一致,如果没有则创建,如果有但不同则需要修改,如果有且相同则不用变更。这种机制能保证云平台的资源与HCL配置是一致的。缺点也是非常明显的,每次都需要调用API去检查远程资源,效率很低,特别是当资源特别多的场景。
另一种方式是每次变更资源的时候,都会创建一个映射文件,它保存云平台资源的状态。这样每次执行apply
命令时,只需要检查HCL配置与映射文件的差异即可。
Terraform选择的是第二种方式,通过映射文件来保存资源状态,在Terraform的世界里叫状态文件。Terraform这样做是基于以下考虑:
- 云平台真实状态的映射,解析状态文件即可以知道真实情况。
- 元数据存储,如资源之间的依赖关系,需要通过依赖关系来知道创建或销毁顺序。
- 提升性能,特别是在大规模云平台上,多次调用API去查询资源状态是很费时的。
- 同步状态,通过远程状态文件来同步状态,这也是Terraform最佳的实践。
讲到这里,已经回答了之前在第一章留下的思考题:
如果再次执行apply会不会再次创建一个文件呢?还是创建失败,因为文件已存在?为什么?
答案:不会创建,因为通过状态文件记录了变更,Terraform判断不再需要创建了。
状态管理的示例
为了更多注意力放在状态管理上,我们还是使用最简单的例子local_file
,具体代码如下:
resource "local_file" "terraform-introduction" {
content = "https://www.pkslow.com"
filename = "${path.root}/terraform-guides-by-pkslow.txt"
}
我们以实际操作及现象来讲解状态文件的作用和工作原理:
操作 | 现象及说明 |
---|---|
terraform apply | 生成资源:第一次生成 |
terraform apply | 没有变化:状态文件生成,不需要再创建 |
terraform destroy | 删除资源:根据状态文件的内容删除 |
terraform apply | 生成资源:状态显示没有资源,再次生成 |
删除状态文件 | 没有变化 |
terraform apply | 生成资源:没有状态文件,直接生成资源和状态文件(插件做了容错处理,已存在也会新生成覆盖) |
删除状态文件 | 没有变化 |
terraform destroy | 无法删除资源,没有资源存在的状态 |
我们一直在讲状态文件,我们先来看一下它的真面目。首先它的默认文件名是terraform.tfstate
,默认会放在当前目录下。它是以json
格式存储的信息,示例中的内容如下:
{
"version": 4,
"terraform_version": "1.0.11",
"serial": 1,
"lineage": "acb408bb-2a95-65fd-02e6-c23487f7a3f6",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "local_file",
"name": "test-file",
"provider": "provider[\"registry.terraform.io/hashicorp/local\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"content": "https://www.pkslow.com",
"content_base64": null,
"directory_permission": "0777",
"file_permission": "0777",
"filename": "./terraform-guides-by-pkslow.txt",
"id": "6db7ad1bbf57df0c859cd5fc62ff5408515b5fc1",
"sensitive_content": null,
"source": null
},
"sensitive_attributes": [],
"private": "bnVsbA=="
}
]
}
]
}
可以看到它记录了Terraform的版本信息,还有资源的详细信息:包括类型、名字、插件、属性等。有这些信息便可直接从状态文件里解析出具体的资源。
状态管理命令
可以通过terraform state
做一些状态管理:
显示状态列表:
$ terraform state list
local_file.test-file
查看具体资源的状态信息:
$ terraform state show local_file.test-file
# local_file.test-file:
resource "local_file" "test-file" {
content = "https://www.pkslow.com"
directory_permission = "0777"
file_permission = "0777"
filename = "./terraform-guides-by-pkslow.txt"
id = "6db7ad1bbf57df0c859cd5fc62ff5408515b5fc1"
}
显示当前状态信息:
$ terraform state pull
重命名:
$ terraform state mv local_file.test-file local_file.pkslow-file
Move "local_file.test-file&q