Terraform 使用 - 从最简单例子开始

Terraform 是一个 IT 基础架构自动化编排工具,它的口号是 "Write, Plan, and create Infrastructure as Code", 基础架构即代码。具体的说就是可以用代码来管理维护 IT 资源,比如针对 AWS,我们可以用它创建,修改,删除 S3 Bucket, Lambda, EC2 实例,Kinesis, VPC 等各种资源。并且在真正运行之前可以看到执行计划(即干运行-dryrun)。由于状态保存到文件中,因此能够离线方式查看资源情况 -- 当然,前提是不要在 Terraform 之外对资源进行修改。

Terraform 配置的状态除了能够保存在本地文件中,也可以保存到 ConsulS3, azure, http, swift 等处。

Terraform 是一个高度可扩展的工具,通过 Provider 来支持新的基础架构,AWS 不过为目前官方内建 68 个 Providers 中的一个。其他能用 Terraform 的地方有 Alicloud(阿里云, 实名制备案才能用), Google Cloud, Heroku, Kubernetes, Microsoft Azure, MySQL, RabbitMQ, Docker 等等。愿意的话可以写自己的 Provider, 如搞个 Kafka 的话,用来管理 Topic 等的创建,维护工作。

Terraform 之前我们对 AWS 的操作用的是 awscli, 或 Serverless。awscli 什么都能做,但它是无状态的,必须明确用不同的命令来创建,修改和删除。Serverless 不是用来管理基础架构的,用它创建  Lambda 时创建资源都是很麻烦的事。AWS 提供的 CloudFormation 才是与 Terraform 较类似的工具,但是看到用法就头疼。

下面从最简单例子开始,看看怎么用 Terraform 创建,删改,修改 S3 Bucket。本地系统为 Mac OS。

1. Terraform 安装

brew install terraform

安装后 shell 命令就是 terraform, 常用的是 terraform init, terraform plan, terraform apply

2. 创建配置文件

像 git 一样,每个 Terraform 项目需要自己单独的目录空间,所以我们创建一个 terraform-learning 目录

mkdir terraform-learning
cd terraform-learning

该目录下的所有  *.tf 文件都会被 Terraform 加载,在初始化 Terraform 工作空间之前必须至少要有一个 *.tf 文件。我们这里建立文件 main.tf, 内容如下

Terraform 配置的语法是该公司 HashiCorp 独创的 HCL(HashiCorp configuration language), 它可以兼容 JSON 格式。

上面 tf 文件在 Vim 中的语法加亮是安装的 hashivim/vim-terraform 插件。

我们写好了 *.tf 文件后可以调用 terraform fmt 对配置文件进行格式化,它比较喜欢被 Java 弃用的等号对齐的格式。

3. 配置文件介绍

从正式跨入 terraform 命令正题之前先来大概的介绍一下上面那个 main.tf 文件。

1) provider "aws" 部分,它指定选用什么 provider, 以及验证信息。aws 既允许指定 access_key 和 secret_key

provider "aws" {
    region           = "us-east-1"
    access_key  = "your-access-key-here"
    secret_key   = "your-secret-key-here"
}

也能够指定证书文件中的 profile

provider "aws" {
    region                                  = "us-east-1"
    shared_credentials_file  = "~/.aws/credentials"   //不指定的话,默认值是 "~/.aws/credentials"
    profile                                  = "yanbin"                        //不指定的话,默认值是 "default"
}

如果是使用 shared_credentials_file 中的 profile, 请确定您以预先生成好的 credentials 文件及有效的 profile。

更多关于 AWS Provider 的配置请参考 https://www.terraform.io/docs/providers/aws/index.html

2) resource "aws_s3_bucket" "s3_bucket" 部分

这只是我们今天举的一个小例子,点击链接 aws_s3_bucket 查看 S3 Bucket 所有的配置项。Terraform 能够管理的所有 AWS 资源也能从前面那个链接中看到。

如果 bucket yanbin-test-bucket 不存在的话,运行 terraform apply 将会创建它,否则试图更新该 bucket。此例子只指定了 bucket 的 acl 和 tag 信息。terraform destroy 用来删除已存在的  bucket。

注意:terraform 配置文件中只指定要管理的资源对象,并不关心操作资源的行为--创建,修改,删除操作。操作行为与 Terraform 的状态有关系,无则创建,有则修改,更名会拆分为除旧立新两个操作,terraform destroy 用于显式删除资源。后面实例操作时会讲到。

注:resource "aws_s3_bucket" "s3_bucket" { 中,resource 后第一个是 type, 即资源名,第二个参是 name。其实 "s3_bucket" 在这里没什么用,只是一个描述或助记符而已(2017-08-28): 更正一下,在作为变量引用的时候就要用到它,例如在后面要为 Lambda 创建一个 S3 Event 的 Trigger, 就要写成 event_source_arn = "${aws_s3_bucket.s3_bucket.arn}", 引用时不需要知道实际的名称。

4. 初始化工作目录

在初始化 Terraform 工作目录之前, 其他命令如 apply, plan 多是不可用的,提示需要初始化工作目录,命令是

terraform init

它要做的事情像是 git init 加上 npm install,执行完了 terraform init 之后会在当前目录中生成 .terraform 目录,并依照 *.tf 文件中的配置下载相应的插件。

5. 执行 Terraform 管理命令

有了前面的准备之后,终于可以开始运行 Terraform 的管理命令了。Terraform 在正式执行之前提供了预览执行计划的机会,让我们清楚的了解将要做什么

terraform plan

由此计划还能知道关于 aws_s3_bucket 有些什么配置项,比如配置中可以加上 acceleration_status = "Enabled"

terraform apply

这样便在 AWS 上创建了一个 S3 bucket "yanbin-test-bucket", 同时会在当前目录中生成一个状态文件 terraform.tfstate, 它是一个标准的 JSON 文件。这个文件对 Terraform 来说很重要,它会影响 terraform plan 的决策,虽然不会影响到实际的执行效果。我们可以把它存到远端,如 S3 或 Consul。terraform state [list|mv|pull|push|rm|show] 用来操作状态文件。

此时什么也不改,再次执行 terraform plan, 会显示没什么要做的

aws_s3_bucket.s3_bucket: Refreshing state... (ID: yanbin-test-bucket)
No changes. Infrastructure is up-to-date.

如果对 main.tf 作点小改,改个 tag 属性,再次 terraform plan

~ aws_s3_bucket.s3_bucket
tags.Name: "Created by Terraform" => "sCreated by Terraform"
Plan: 0 to add, 1 to change, 0 to destroy.

为什么说 terraform plan 是基于状态文件 terraform.tfstate 作出的呢?我们可以删除这个状态文件,然后执行 terraform plan 看看

+ aws_s3_bucket.s3_bucket
    .....
    bucket: "yanbin-test-bucket"
    ......
    tags.Environment: "QA"
    ......
Plan: 1 to add, 0 to change, 0 to destroy.

Terraform 由于缺乏 terraform.tfstate 对比,所以认为是要添加一个 bucket, 但是实际执行 terraform apply 时,连接到远端 AWS, 发现该 bucket 已存在就只是进行更新。terraform apply 总能给出正确的操作结果。同理如果状态文件中说有那个 bucket, terraform plan 会说是更新,但 AWS 没有那个  bucket,实际执行 terraform apply 也会进行添加的。

资源更名

如果把 main.tf 中的

bucket = "yanbin-test-bucket"

改成

bucket = "yanbin-test-bucket-rename"

即欲为 bucket 更名,用 terraform plan 看下计划

实际上 terraform apply 也是先删除旧的,再创建新的。Terraform 像 git 一样用不同颜色和  +/- 号来显示变动操作

最后是 terraform destroy 命令,把 *.tf 文件中配置的所有资源从 AWS 上清理掉。

关于 Terraform 工作目录中文件命名

Terraform 运行时会读取工作目录中所有的 *.tf, *.tfvars 文件,所以我们不必把所有的东西都写在单个文件中去,应按职责分列在不同的文件中,例如:

provider.tf                -- provider 配置
terraform.tfvars      -- 配置 provider 要用到的变量
varable.tf                  -- 通用变量
resource.tf                -- 资源定义
data.tf                        -- 包文件定义
output.tf                    -- 输出

以此篇最简单的入门出发,以后可以深入了解 Lambda, Lambda 触发器,及 API Gateway, EC2 实例怎么用 Terraform 来管理,也知晓了资源的可用属性应该到哪里去查。

一个小提示:在执行像 terraform plan 或 terraform apply 等命令的时候,可以按下 ctrl + c 让控制台输出详细的日志信息。

本文链接 https://yanbin.blog/terraform-get-started-with-first-sample/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

3 Comments
Inline Feedbacks
View all comments
newbmiao
4 years ago

tags = {
Name = "Created by Terrform"
Environment = "Dev"
}


tag这里缺了一个“=”

感谢分享

Robin
Robin
5 years ago

Great