《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新,书中的示例代码也是放在GitHub上,方便大家参考查看。
初闻不知Terraform,再闻已是云中人。
在以前,当我们需要把应用部署在服务器时,需要购买多台服务器和机房、组装交换机和网络、不间断电源UPS等。随着云时代的到来,我们可以在IaaS(Infrastructure as a Service)平台直接购买所有的基础设施,包括服务器、专用网络、DNS、负载均衡等,而你只需要专注于应用层面即可。
IaaS(Infrastructure as a Service)的意思是基础设施即服务,它是云服务的基础。著名的IaaS厂商有亚马逊、微软、谷歌和阿里云等。
云厂商为我们解决了许多运维问题:我们不再需要自己管理物理机器,而且能够根据需要随时创建和销毁云机器,还能根据业务和性能要求指定创建服务器的配置和数量。这种便利对于创业型的小公司和个人开发者尤其重要。
随时公司业务的良好发展,所需要的硬件资源越来越多,架构越来越复杂。通过界面操作手工创建服务器、数据库等资源的方式带来越来越多的问题。首先,只要是人工操作,都会有失误的可能,没有人能保证自己不会犯错;而人工操作在软件行业发生事故的案例屡见不鲜。其次,为保证正确率,人工操作一般只能串行,资源多的时候时间会很长。最后,如果我需要根据开发环境的配置再创建一个测试环境和生产环境,人工操作可能会造成差异和错误。
因此,对于这种复杂需要,最佳的方式是通过代码来创建所有硬件资源。这种思想就是基础设施即代码(Infrastructure as Code,很简称IaC),通过代码与定义、部署、更新和销毁基础设施。把硬件映射为软件,而开发和运维人员通过管理代码来管理硬件。
IaC的好处有:
最终,实现快速安全地应用部署交付(Devivery)。
在IaC这方面的优秀工具还是非常多的,而且不同的工具完成不同的职责,下面列出一些比较常见的工具:
| 图标 | 工具名 | GitHub STAR数 |
|---|---|---|
![]() |
Ansible | 50.9k |
![]() |
Terraform | 30.2k |
![]() |
Vagrant | 23k |
![]() |
Chef | 6.8k |
![]() |
Puppet | 6.4k |
![]() |
AWS CloudFormation | |
![]() |
Azure Resource Manager | |
![]() |
Google Cloud Deployment Manager |
其中,Ansible在配置自动化应该是领头羊的地位。而Terraform则在服务开通上的事实标准。这里并不想给各个工具做具体介绍,感兴趣的可以去官网或GitHub了解。
注:有些文章或书籍会把Docker和Kubernetes也列为IaC工具,它们的主要职责是在容器与服务编排方面。
我们的主角Terraform终于登场了。它是由HashiCorp公司研发的开源的IaC工具,它是由GO语言编写的,可以在各个平台上运行,支持Linux、Mac、Windows等。它简单易用,即使没有太多代码经验的人,也能读懂Terraform的配置代码HCL。
HCL,即HashiCorp Configuration Language,是HashiCorp公司开发的配置语言。后续我们会介绍一些常用语法。
Terraform是一个安全高效的用于对基础设施进行创建和变更且进行版本控制的工具。它支持私有云和公有云,如AWS、Azure、GCP和阿里云等。它的官方网站为https://www.terraform.io。
主要特性有:
截至2021年12月02日,Terraform的最新版本为1.0.11,而它在2021年6月8日才正式发布1.0.0版本。可见Terraform是如此年轻且有活力。而在Terraform还不是1.0.0版本的时候,已经有大量公司在生产环境上使用了。
Terraform是一个由Go语言编写的程序,它会读取HCL语言编写的配置文件,然后将变更信息通过RPC与插件通信,由插件调用云厂商的API完成变更操作。这就是Terraform的工作原理,架构图如下:

Terraform core:Terraform的核心组件,类似于指挥官,负责解析配置、管理状态、模块等核心功能。
插件Plugin:完成具体变更的组件,因为Terraform支持多种平台,它并没有把对所有平台的支持都放到核心组件中实现,而是通过插件的方式来提供这些功能。需要对接什么平台,就加入什么平台的插件,非常方面。
模块module:可以将完成特定功能的HCL封装成一个模块,以实现代码复用。类似于其它编程语言中的函数或方法。有入参和出参,一切都可自定义。
状态state:状态存在专门的状态文件里,它是作用是记录实际基础设施的状态。当再次执行变更请求时,Terraform会读取状态文件,判断是否真的需要变更实际的基础设施。如果状态文件记录的状态与HCL描述的一致,就不用再执行变更操作了。
Terraform就是一个二进制的程序,只要下载并添加到PATH中去就可以了。各个系统的安装方式没有太大差异。这里以Mac系统为例,做个简单介绍。
下载程序:
可以直接到官网界面(https://www.terraform.io/downloads.html)去下载,请根据自己的系统选择对应的文件:

下载后进行解压,并将该程序添加到环境变量中。
比如我的Terraform放在路径/Users/larry/Software/terraform中,则添加到环境变量的命令如下:
export PATH=$PATH:/Users/larry/Software/terraform
为了让它一直生效,我把上面命令放在home目录下的.bash_profile文件中。
检查是否安装成功如下:
$ terraform version
Terraform v1.0.11
on darwin_amd64
如果在纯终端的环境下,也可以通过命令进行下载和解压,命令如下:
# 下载安装包
$ wget https://releases.hashicorp.com/terraform/1.0.11/terraform_1.0.11_darwin_amd64.zip
# 解压
$ unzip terraform_1.0.11_darwin_amd64.zip
Terraform的主要应用场景是云服务的基础设施管理,但为了让大家能快速的接触与体验Terraform,我会先选择最简单的一个插件来入门,以免需要太多的环境设置。我们的任务是创建一个文本文件,内容由我们来指定。可以通过插件hashicorp/local来完成。
在当前目录创建一个main.tf文件,完整的代码如下:
terraform {
required_version = "= v1.0.11"
required_providers {
local = {
source = "hashicorp/local"
version = "= 2.1.0"
}
}
}
resource "local_file" "terraform-introduction" {
content = "Hi guys, this the tutorial of Terraform from pkslow.com"
filename = "${path.module}/terraform-introduction-by-pkslow.txt"
}
然后执行下面命令:
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/local versions matching "2.1.0"...
- Installing hashicorp/local v2.1.0...
- Installed hashicorp/local v2.1.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
看命令的输出结果可以知道,Terraform会自动帮我们去下载对应版本的插件hashicorp/local,并做一些初始化的操作。
接着我们通过命令terraform plan来查看将要执行的变更计划:
$ terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# local_file.terraform-introduction will be created
+ resource "local_file" "terraform-introduction" {
+ content = "Hi guys, this the tutorial of Terraform from pkslow.com"
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./terraform-introduction-by-pkslow.txt"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
输出日志中会提示需要创建、改变和销毁多少资源。
Plan: 1 to add, 0 to change, 0 to destroy
这里表示会创建一个资源。
废话少说,我们直接执行变更:
$ terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# local_file.terraform-introduction will be created
+ resource "local_file" "terraform-introduction" {
+ content = "Hi guys, this the tutorial of Terraform from pkslow.com"
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./terraform-introduction-by-pkslow.txt"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value:
会让你确认是否执行变更,如果是,则输入yes。我们直接输入yes并按回车。
Enter a value: yes
local_file.terraform-introduction: Creating...
local_file.terraform-introduction: Creation complete after 0s [id=f63c7933c953ea2d03820d1ec35a80c718bd4777]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
成功执行,创建了文件。
$ ls -l
total 24
-rw-r--r-- 1 larry staff 344 Dec 3 00:01 main.tf
-rwxr-xr-x 1 larry staff 55 Dec 3 00:13 terraform-introduction-by-pkslow.txt
-rw-r--r-- 1 larry staff 921 Dec 3 00:13 terraform.tfstate
上面还有一个tfstate文件,是用来记录状态的,以后会详细讲这块内容。
查看一下文件内容:
$ cat terraform-introduction-by-pkslow.txt
Hi guys, this the tutorial of Terraform from pkslow.com
与我们预期的内容一致。
如果再次执行apply会不会再次创建一个文件呢?还是创建失败,因为文件已存在?
带着这样的问题,我们再执行一次:
$ terraform apply
local_file.terraform-introduction: Refreshing state... [id=f63c7933c953ea2d03820d1ec35a80c718bd4777]
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
发现提示不需要变更,不会执行任何操作。
大家可以思考一下为什么,答案会在后面章节揭晓。
现在我不需要这个文件呢,通过destroy命令可以删除:
$ terraform destroy
local_file.terraform-introduction: Refreshing state... [id=f63c7933c953ea2d03820d1ec35a80c718bd4777]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# local_file.terraform-introduction will be destroyed
- resource "local_file" "terraform-introduction" {
- content = "Hi guys, this the tutorial of Terraform from pkslow.com" -> null
- directory_permission = "0777" -> null
- file_permission = "0777" -> null
- filename = "./terraform-introduction-by-pkslow.txt" -> null
- id = "f63c7933c953ea2d03820d1ec35a80c718bd4777" -> null
}
Plan: 0 to add, 0 to change, 1 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
local_file.terraform-introduction: Destroying... [id=f63c7933c953ea2d03820d1ec35a80c718bd4777]
local_file.terraform-introduction: Destruction complete after 0s
Destroy complete! Resources: 1 destroyed.
一样需要你确认是否真的需要删除,输入yes回车即可。
到这里,就已经真正地带大家体验了一下Terraform是如何工作的,介绍了它的整个流程,也就是Terraform官网所说的Write, Plan, Apply。希望大家能真正动手实践,包括后续的实验,这跟学编程语言是一样的。
最后,对于本次实验我想提几点:
-auto-approve即可。很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
@作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors 1、什么是behaviors 2、behaviors的工作方式 3、创建behavior 4、导入并使用behavior 5、behavior中所有可用的节点 6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors 1、什么是behaviorsbehaviors是小程序中,用于实现
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg
ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear
我认为我的问题最好用一个例子来描述。假设我有一个名为“Thing”的简单模型,它有一些简单数据类型的属性。像...Thing-foo:string-goo:string-bar:int这并不难。数据库表将包含具有这三个属性的三列,我可以使用@thing.foo或@thing.bar之类的东西访问它们。但我要解决的问题是当“foo”或“goo”不再包含在简单数据类型中时会发生什么?假设foo和goo代表相同类型的对象。也就是说,它们都是“Whazit”的实例,只是数据不同。所以现在事情可能看起来像这样......Thing-bar:int但是现在有一个新的模型叫做“Whazit”,看起来
我有一个要在我的Rails3项目中使用的数组扩展方法。它应该住在哪里?我有一个应用程序/类,我最初把它放在(array_extensions.rb)中,在我的config/application.rb中我加载路径:config.autoload_paths+=%W(#{Rails.root}/应用程序/类)。但是,当我转到railsconsole时,未加载扩展。是否有一个预定义的位置可以放置我的Rails3扩展方法?或者,一种预先定义的方式来添加它们?我知道Rails有自己的数组扩展方法。我应该将我的添加到active_support/core_ext/array/conversion
我的Rails应用程序中安装了carrierwave。但是,当用户上传多页pdf时,我只希望应用程序获取文档中的第一页并将其转换为jpeg。这可能吗?用什么命令?这是我的uploader。#encoding:utf-8classImageUploader[200,300]##defscale(width,height)##dosomething#end#Createdifferentversionsofyouruploadedfiles:version:thumbdoprocess:resize_to_fill=>[150,210]process:convert=>:jpgdefful
有没有办法跳过CSV文件的第一行,让第二行作为标题?我有一个CSV文件,第一行是日期,第二行是标题,所以我需要能够在遍历它时跳过第一行。我尝试使用slice但它会将CSV转换为数组,我真的很想将其读取为CSV,以便我可以利用header。 最佳答案 根据您的数据,您可以使用另一种方法和skip_lines-option此示例跳过所有以#开头的行require'csv'CSV.parse(DATA.read,:col_sep=>';',:headers=>true,:skip_lines=>/^#/#Markcomments!)do|