《Terraform 101 从入门到实践》 第四章 States状态管理

news2024/11/28 13:45:13

《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" to "local_file.pkslow-file"
Successfully moved 1 object(s).

$ terraform state list
local_file.pkslow-file

要注意这里只是修改状态文件的名字,代码里的HCL并不会修改。

删除状态里的资源:

$ terraform state rm local_file.pkslow-file
Removed local_file.pkslow-file
Successfully removed 1 resource instance(s).

远程状态

状态文件默认是在本地目录上的terraform.tfstate文件,在团队使用中,每个人的电脑环境独立的,那么需要保证每个人当前的状态文件都是最新且与现实资源真实对应,简直是天方夜谭。而状态不一致所带的灾难也是极其可怕的。所以,状态文件最好是要存储在一个独立的大家可共同访问的位置。对于状态的管理的配置,Terraform称之为Backends

Backend是两种模式,分别是localremotelocal模式很好理解,就是使用本地路径来存储状态文件。配置示例如下:

terraform {
  backend "local" {
    path = "pkslow.tfstate"
  }
}

通过这样配置后,不再使用默认的terraform.tfstate文件,而是使用自定义的文件名pkslow.tfstate

对于remote模式,则有多种配置方式,Terraform支持的有:

  • s3
  • gcs
  • oss
  • etcd
  • pg
  • http
  • kubernetes

等,能满足主流云平台的需求。每一个配置可以参考官网,在本地我采用数据库postgresql的方式,让大家都能快速实验。

我通过Docker的方式启动PostgreSQL,命令如下:

$ docker run -itd \
    --name terraform-postgres \
    -e POSTGRES_DB=terraform \
    -e POSTGRES_USER=pkslow \
    -e POSTGRES_PASSWORD=pkslow \
    -p 5432:5432 \
    postgres:13

terraform块中配置backend,这里指定数据库连接信息即可,更多参数请参考:https://www.terraform.io/language/settings/backends/pg

terraform {
  backend "pg" {
    conn_str = "postgres://pkslow:pkslow@localhost:5432/terraform?sslmode=disable"
  }
}

当然,把敏感信息直接放在代码中并不合适,可以直接在命令行中传入参数:

terraform init -backend-config="conn_str=postgres://pkslow:pkslow@localhost:5432/terraform?sslmode=disable"

执行init和apply之后,连接数据库查看,会创建一个叫terraform_remote_state的Schema,在该Schema下有一张states表来存储对应的状态信息,如下:

表中字段name是namespace,而data是具体的状态信息,如下:

{
  "version": 4,
  "terraform_version": "1.0.11",
  "serial": 0,
  "lineage": "de390d13-d0e0-44dc-8738-d95b6d8f1868",
  "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=="
        }
      ]
    }
  ]
}

Workspace 工作区

如果我们用Terraform代码生成了dev环境,但现在需要uat环境,该如何处理呢?

首先,不同环境的变量一般是不一样的,我们需要定义各种的变量文件如dev.tfvarsuat.tfvarsprod.tfvars等。但只有各自变量是不够的,因为还有状态。状态也必须要隔离,而Workspace就是Terraform用来隔离状态的方式。默认的工作区为default,如果没有指定,则表示工作于default工作区中。而当指定了工作区,状态文件就会与工作区绑定。

创建一个工作区并切换:

$ terraform workspace new pkslow

切换到已存在的工作区:

$ terraform workspace select pkslow

而当我们处于某个工作区时,是可以获取工作区的名字的,引用为:${terraform.workspace},示例如下:

resource "aws_instance" "example" {
  count = "${terraform.workspace == "default" ? 5 : 1}"

  # ... other arguments
}

之前讲过默认的状态文件名为terraform.tfstate;而在多工作区的情况下(只要你创建了一个非默认工作区),状态文件就会存在terraform.tfstate.d目录下。而在远程状态的情况下,也会有一个映射,Key为工作区名,Value一般是状态内容。

敏感数据

本地状态文件都是明文存储状态信息的,所以要保护好自己的状态文件。对于远程状态文件,有些存储方案是支持加密的,会对敏感数据(sensitive)进行加密。

状态锁

本地状态文件下不需要状态锁,因为只有一个人在变更。而远程状态的情况下,就可能出现竞争了。比如一个人在apply,而另一个人在destroy,那就乱了。而状态锁可以确保远程状态文件只能被一个人使用。但不是所有远程状态的方式都支持锁的,一般常用的都会支持,如GCS、S3等。

所以,每当我们在执行变更时,Terraform总会先尝试去拿锁,如果拿锁失败,就该命令失败。可以强制解锁,但要非常小心,一般只建议在自己明确知道安全的时候才使用,比如死锁了。

共享状态-数据源

既然远程状态文件是可以共享的,那状态信息也是可以共享的。这样会带来的一个好处是,即使两个根模块,也是可以共享信息的。比如我们在根模块A创建了一个数据库,而根模块B需要用到数据库的信息如IP,这样通过远程状态文件就可以共享给根模块B了。

注意这里我强调的是根模块,因为如果A和B在同一个根模块下,那就不需要通过远程状态的方式来共享状态了。

远程状态的示例:

data "terraform_remote_state" "vpc" {
  backend = "remote"

  config = {
    organization = "hashicorp"
    workspaces = {
      name = "vpc-prod"
    }
  }
}

resource "aws_instance" "foo" {
  # ...
  subnet_id = data.terraform_remote_state.vpc.outputs.subnet_id
}

本地状态的示例:

data "terraform_remote_state" "vpc" {
  backend = "local"

  config = {
    path = "..."
  }
}

resource "aws_instance" "foo" {
  # ...
  subnet_id = data.terraform_remote_state.vpc.outputs.subnet_id
}

要注意的是,只有根模块的输出变量才能被共享,子模块是不能被获取的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/335672.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

个人学习系列 - 解决拦截器操作请求参数后台无法获取

由于项目需要使用拦截器对请求参数进行操作,可是请求流只能操作一次,导致后面方法不能再获取流了。 新建SpringBoot项目 1. 新建拦截器WebConfig.java /*** date: 2023/2/6 11:21* author: zhouzhaodong* description:*/ Configuration public class W…

Docker-consul的容器服务更新与发现

一.Consul概述1.1 什么是服务注册与发现服务注册与发现是微服务架构中不可或缺的重要组件。起初服务都是单节点的,不保障高可用性,也不考虑服务的压力承载,服务之间调用单纯的通过接口访问。直到后来出现了多个节点的分布式架构,起…

Threejs中的Shadow Mapping(阴影贴图)

简而言之,步骤如下: 1.从灯光位置视点(阴影相机)创建深度图。 2.从相机的位置角度进行屏幕渲染,在每个像素点,比较由阴影相机的MVP矩阵计算的深度值和深度图的值的大小,如果深度图值小的话&…

Office Server Document Converter Lib SDK Crack

关于 Office Server 文档转换器 (OSDC) 无需 Microsoft Office 或 Adob​​e 软件即可快速准确地转换文档。antennahouse.com Office Server 文档转换器 (OSDC) 会将您在 Microsoft Office(Word、Excel、PowerPoint)中创建的重要文档转换为高质量的 PDF …

【编程基础之Python】2、安装Python环境

【编程基础之Python】2、安装Python环境安装Python环境在Windows上安装Python验证Python运行环境在Linux上安装Python验证Python运行环境总结安装Python环境 所谓“工欲善其事,必先利其器”。在学习Python之前需要先搭建Python的运行环境。由于Python是跨平台的&am…

机器学习之K-means原理详解、公式推导、简单实例(python实现,sklearn调包)

目录1. 聚类原理1.1. 无监督与聚类1.2. K均值算法2. 公式推导2.1. 距离2.2. 最小平方误差3. 实例3.1. python实现3.2. sklearn实现4. 运行(可直接食用)1. 聚类原理 1.1. 无监督与聚类 在这部分我今天主要介绍K均值聚类算法,在这之前我想提一…

01-幂等性解释,问题及常用解决方案

目录 1. 幂等性简介 2. 后端如何解决幂等性问题 2.1 数据库层面 -> 2.1.1 防重表 -> 2.1.2 数据库悲观锁(不建议,容易出现死锁情况) -> 2.1.3 数据库乐观锁 -> 2.1.4 乐观锁CAS算法原理 2.2 锁层面 2.3 幂等性token层面 -> 2.3.1 简介文字描述: …

Java开发 - 问君能有几多愁,Spring Boot瞅一瞅。

前言 首先在这里恭祝大家新年快乐,兔年大吉。本来是想在年前发布这篇博文的,奈何过年期间走街串巷,实在无心学术,所以不得不放在近日写下这篇Spring Boot的博文。在还没开始写之前,我已经预见到,这恐怕将是…

中国社科院与美国杜兰大学金融管理硕士,让我们相遇在春暖花开时

在芸芸众生中,能拥有志同道合的朋友是一件多么幸运的事。人们常说:你是谁,就会遇见谁。走过半生才知道,看似命中注定的遇见谁、发生的事,其实都取决于自己。只有自己足够优秀,才能遇到更优秀的别人。在这个…

IT人的晋升之路——关于人际交往能力的培养

对于咱们的程序员来说,工作往往不是最难的,更难的是人际交往和关系的维护处理。很多时候我们都宁愿加班,也不愿意是社交,认识新的朋友,拓展自己的圈子。对外的感觉就好像我们丧失了人际交往能力,是个呆子&a…

【chatGPT】持续火热一路狂飙,简单了解下TA的功能和示例代码吧

🎉🎉 最近chatGPT持续火爆,一路狂飙,对应如何注册和使用的优质文章非常多。 所以,此篇文章除了整理chatGPT文章外,主要是讲解如何获取API Key进行接口的调用🎉🎉 目录1、chatGPT解读…

蓝牙单点技术实现路径介绍

本文主要介绍蓝牙设备与手机一对一相连的 蓝牙单点 技术。 准备工作 系统要求&#xff1a;蓝牙使用需要安卓 4.3 以及以上版本&#xff0c;智能生活 App SDK 从安卓 4.4 开始支持。Manifest 权限&#xff1a; <uses-permission android:name"android.permission.ACCE…

Fluent Python 笔记 第 3 章 字典和集合

3.1 泛映射类型 只有可散列 的数据类型才能用作这些映射里的键 字典构造方法&#xff1a; >>> a dict(one1, two2, three3) >>> b {one: 1, two: 2, three: 3} >>> c dict(zip([one, two, three], [1, 2, 3])) >>> d dict([(two, 2…

5. Spring 事务

文章目录1. Spring 事务简介2. Spring 事务角色3. Spring 事务属性3.1 事务配置3.2 案例&#xff1a;转账业务追加日志3.3 事务传播行为1. Spring 事务简介 Spring 事务作用&#xff1a;在数据层或业务层保障一系列的数据库操作同成功、同失败。 数据层有事务我们可以理解&am…

多传感器融合定位十三-基于图优化的建图方法其二

多传感器融合定位十二-基于图优化的建图方法其二3.4 预积分方差计算3.4.1 核心思路3.4.2 连续时间下的微分方程3.4.3 离散时间下的传递方程3.5 预积分更新4. 典型方案介绍4.1 LIO-SAM介绍5. 融合编码器的优化方案5.1 整体思路介绍5.2 预积分模型设计Reference: 深蓝学院-多传感…

Vue3 - 自定义指令封装

Vue3 - 自定义指令封装一. 自定义指令封装1.1 全局/局部注册自定义聚焦指令1.2 自定义指令相关参数1.3 自定义指令参数传递二. 总结一. 自定义指令封装 vue中有很多内置的指令&#xff0c;我们一般在开发中也经常用到&#xff0c;比如v-if&#xff0c;v-for等等。那么本篇文章…

Vue极简使用

Vue安装Vue模板语法安装Vue 安装nodejs 这里我安装的是14.5.4版本 https://nodejs.org/download/release/v14.15.4/解压后配置一下环境变量就行 安装cnpm镜像 (这个安装的版本可能过高&#xff0c;后面安装Vue可能出问题) npm install -g cnpm --registryhttps://registry…

二十二、Gtk4-ListView

GTK 4添加了新的列表对象GtkListView、GtkGridView和GtkColumnView。这个新特性在Gtk API参考—列表小构件概述中有描述。 GTK 4还有其他实现列表的方法。它们是GtkListBox和GtkTreeView&#xff0c;它们是从GTK 3接管的。在Gtk开发博客中有一篇关于Matthias Clasen所写的列表…

vscode执行Python输出exited with code=9009 in 0.655 seconds

vscode执行Python输出exited with code9009 in 0.655 seconds 想用vscode写个脚本&#xff0c;用自己电脑配置了下vscode的python环境&#xff0c;结果点击右上角三角图标运行时却只会输出exited with code9009 in 0.655 seconds 这就不太理解了&#xff0c;我在公司时是能正…

linux性能分析 性能之巅学习笔记和内容摘录

本文只是在阅读《性能之巅》的过程中&#xff0c;对一些觉得有用的地方进行的总结和摘录&#xff0c;并附加一些方便理解的材料&#xff0c;完整内容还请阅读Gregg的大作 概念和方法 性能分析领域一词的全栈代表了整个操作系统的软硬件在内的所有事物 软件生命周期和性能规划…