# Terraform状态State管理,让变更有记录

# 简介

最近工作中用到了Terraform,权当学习记录一下,希望能帮助到其它人。

Terraform系列文章如下:

Terraform入门教程,示例展示管理Docker和Kubernetes资源 (opens new window)

Terraform插件Provider管理,搜索、定义、下载 (opens new window)

Terraform状态State管理,让变更有记录 (opens new window)

Terraform模块Module管理,聚合资源的抽取与复用 (opens new window)

Terraform常用命令 (opens new window)

State状态是Terraform用于管理基础设施和配置的,它是真实资源的映射,也可以提供大规模基础设施平台的效率。它的主要功能是绑定远程资源平台(如AWS)和本地代码配置的关系。说白了,就是它存储了在实际平台中各种资源的状态,现有的样子。

# 先通过示例感受一下State

如果概念不好理解,就先通过示例感受一下吧。

关键配置如下,具体请去GitHub参考我的代码:

provider "kubernetes" {
  config_path = "~/.kube/config"
}

module "pkslow-nginx" {
    source = "./nginx"
    namespace = "pkslow"
    applicationName = "pkslow-nginx"
    image = "nginx:1.19.5"
    replicas = 3
    nodePort = 30201
}

先执行apply操作:

$ terraform apply
module.pkslow-nginx.kubernetes_deployment.test: Creating...
module.pkslow-nginx.kubernetes_deployment.test: Creation complete after 4s [id=pkslow/pkslow-nginx]
module.pkslow-nginx.kubernetes_service.test: Creating...
module.pkslow-nginx.kubernetes_service.test: Creation complete after 0s [id=pkslow/pkslow-nginx]

它创建了两个资源,这里在项目的当前目录就会新生成一个terraform.tfstate,它是默认的状态文件。它是一个Json格式的文件,存储了apply新建的资源的状态,如叫什么名字、是什么属性、IP等。

这时,如果我们再次apply,它会什么都不生成,因为状态文件与实际基础设施一样,而配置又没有改动,所以可以认为配置与实际一样,不需要变更:

$ terraform apply
No changes. Your infrastructure matches the configuration.

我把NodePort改为30301,再重新apply

$ terraform apply
Plan: 0 to add, 1 to change, 0 to destroy.

module.pkslow-nginx.kubernetes_service.test: Modifying... [id=pkslow/pkslow-nginx]
module.pkslow-nginx.kubernetes_service.test: Modifications complete after 0s [id=pkslow/pkslow-nginx]

可以看到它只变更了两个资源中的其中一个。

通过destroy操作删除资源时,也是要读状态文件的,如果状态文件丢失了,它就无法正常删除了。

$ mv terraform.tfstate terraform.tfstate.bak

$ terraform destroy
No changes. No objects need to be destroyed.
Either you have not created any objects yet or the existing objects were already deleted outside of Terraform.
Destroy complete! Resources: 0 destroyed.

有对应的状态文件,就会根据状态文件删除:

$ terraform destroy
Plan: 0 to add, 0 to change, 2 to destroy.

module.pkslow-nginx.kubernetes_service.test: Destroying... [id=pkslow/pkslow-nginx]
module.pkslow-nginx.kubernetes_service.test: Destruction complete after 0s
module.pkslow-nginx.kubernetes_deployment.test: Destroying... [id=pkslow/pkslow-nginx]
module.pkslow-nginx.kubernetes_deployment.test: Destruction complete after 0s

# 查看状态

可以通过命令terraform state查看状态,主要命令有:

$ terraform state

Subcommands:
    list                List resources in the state
    mv                  Move an item in the state
    pull                Pull current state and output to stdout
    push                Update remote state from a local state file
    replace-provider    Replace provider in the state
    rm                  Remove instances from the state
    show                Show a resource in the state

操作如下:

$ terraform state list
module.pkslow-nginx.kubernetes_deployment.test
module.pkslow-nginx.kubernetes_service.test

$ terraform state show module.pkslow-nginx.kubernetes_deployment.test
# module.pkslow-nginx.kubernetes_deployment.test:
......

# 生产实践

在生产中,状态文件一般不会保存在本地,通常会保存在云存储中,如etcd、gcp、oss等。

如gcs的配置:

terraform {
  backend "gcs" {
    bucket  = "tf-state-prod"
    prefix  = "terraform/state"
  }
}

阿里云oss的配置:

terraform {
  backend "oss" {
    bucket = "bucket-for-terraform-state"
    prefix   = "path/mystate"
    key   = "version-1.tfstate"
    region = "cn-beijing"
    tablestore_endpoint = "https://terraform-remote.cn-hangzhou.ots.aliyuncs.com"
    tablestore_table = "statelock"
  }
}

参考:

官网 State (opens new window)

Backends settings (opens new window)

上次更新: 2023/8/18 23:39:36