还在手动点控制台建资源?Terraform和CloudFormation入门实战,这篇够你喝一壶了
提到搭建环境,很多兄弟可能还停留在“手工匠人”的模式。打开AWS控制台,点那个EC2,选镜像,配安全组,搞子网,再加个负载均衡……这一套下来,脑子都大了。最要命的是,你根本记不住上次那个安全组的入站规则到底是开了80端口还是8080端口。这种“雪花服务器”,配置漂移,环境不一致,简直是运维人的噩梦。
这就是为什么我们今天必须得聊聊基础设施即代码这档子事儿。这玩意儿不是什么新概念,但真正能落地用好的,真能救命。咱们今天挑两个最重量级的选手——Terraform和CloudFormation,来一场从入门到实战的“保姆级”教学。别被那些英文单词吓到了,咱们用大白话把它拆开了揉碎了讲。
咱们先说说这俩到底是啥
如果你还没接触过IaC,可能觉得这俩词儿挺高大上。其实吧,说白了,就是把你的服务器、网络、数据库这些基础设施,像写代码一样定义出来。
以前我们要建个仓库,得找施工队,拿图纸,一砖一瓦砌墙。现在有了IaC,就像是给了你一个3D打印机,你写好配置文件,告诉它我要几层楼、几个窗户、门朝哪开,一按按钮,房子自己就长出来了。
CloudFormation,这可是AWS的亲儿子。它是AWS自家出的模板服务,专门用来管理AWS的资源。你想想,亲儿子肯定最了解家里的情况,所以它对AWS新特性的支持是最快的,而且跟AWS的控制台集成得非常深。你写个JSON或者YAML文件,往S3桶里一扔,CloudFormation引擎一读,哗啦啦给你创建一堆资源。如果中间出错了,它还能自动回滚,就像撤销键一样,这点特别稳。
Terraform,则是HashiCorp公司搞的一个开源工具。这家公司简直是运维界的瑞士军刀厂,Vagrant、Consul都是他们家的。Terraform最大的特点就是“花心”,它不绑定任何一家云厂商。它支持AWS、Azure、Google Cloud,甚至还能管理本地的VMware、Kubernetes。这就好比你找了个全能装修队,既能给你家盖别墅,也能给隔壁老王家盖洋房,用的还是同一套图纸。这对于多云架构来说,简直是神器。
那到底选哪个?如果你公司只死磕AWS一家,CloudFormation确实稳,毕竟是亲生的。但如果你不想被一家云厂商绑定死,或者将来有上多云的打算,那我强烈建议你从Terraform入手。咱们今天也主要拿Terraform来举例,顺便把CloudFormation的坑也给你填上。
工欲善其事,必先装个“破”软件
咱们别光说不练,先把环境搭起来。
如果你用的是Mac,那简单,打开终端,如果你装了Homebrew,直接敲:
brew install terraform要是Linux或者Windows,去官网下个二进制包,解压后把路径加到环境变量里就行。这没什么技术含量,我就不贴那些流水账似的教程了。装好后,敲个 terraform version,只要能蹦出版本号,那就说明成了。
CloudFormation这玩意儿不需要你单独装软件,它就在AWS的控制台里,或者说它本身就是AWS的一部分。你只要有个AWS账号,有AK/SK密钥,用AWS CLI或者直接在网页上点都行。不过为了显得咱们专业点,咱们还是推荐用CLI操作,毕竟天天点鼠标那是文员干的事儿。
Terraform入门:从Hello World开始
咱们先来搞定Terraform。这玩意儿的核心就是那个 .tf 文件。别看到代码就头大,Terraform用的语言叫HCL(HashiCorp Configuration Language),这语言设计得特别人性化,基本上你只要会点英语,就能猜个八九不离十。
咱们先建个文件夹,叫 terraform_demo,进去之后,先建个 main.tf 文件。这就像是咱们写文章的大纲,所有资源都在这儿定义。
第一步,咱们得告诉Terraform,我们要用哪个云厂商的服务。这叫Provider。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
provider "aws" {
region = "ap-northeast-1" # 咱们选东京区域,速度还行
# 这里默认会读取你环境变量里的 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY
}你看,这段代码多直白。terraform 块里声明了我们要用 hashicorp/aws 这个provider,版本大概是4.0以上的。然后 provider "aws" 里指定了区域。这就好比你去饭店,先告诉服务员我要点川菜,然后找个位置坐下。
接下来,咱们来点实际的,建个最简单的EC2服务器(虚拟机)。
resource "aws_instance" "my_server" {
ami = "ami-0c55b159cbfafe1f0" # 这是一个Amazon Linux 2的镜像ID,不同区域不一样,得去控制台查
instance_type = "t2.micro" # 穷人版配置,免费额度能覆盖
tags = {
Name = "MyFirstTerraformServer"
}
}这段代码里,resource 是关键词,后面跟着资源类型 aws_instance 和资源名称 my_server。花括号里面就是参数了。镜像ID(AMI)这东西比较烦人,每个地区都不一样,你得去AWS控制台那个Launch Instance界面里抄一个现成的。t2.micro 是那种能跑得动但快不起来的小水管机型,咱们测试用足够了。
代码写好了,接下来就是见证奇迹的时刻。
在终端里,先敲 terraform init。这个命令是干啥的呢?它是去下载刚才咱们指定的那个AWS插件。就像你装完游戏得更新一下补丁包一样。你会看到进度条哗啦啦地走,最后提示你 Terraform has been successfully initialized!。
然后,敲 terraform plan。这个命令是我最喜欢Terraform的地方。它不会真的去建服务器,而是先预演一遍。它会告诉你,如果你执行了这个计划,AWS上会发生什么变化。你会看到绿色的 + 号,表示要增加资源。如果看到红色的 - 号,那就是要删除。这给了咱们一个后悔的机会。以前用脚本跑,回车键一按,想收都收不回来,手抖一下就是事故。
确认无误后,最后一把梭哈:terraform apply。敲完这个命令,它会让你确认一下,输入 yes。然后你就看着终端里的日志在跑,AWS那边的控制台里,实例状态从 Pending 变成了 Running。
不用登录控制台,不用点那些眼花缭乱的下一步按钮,一台服务器就这么诞生了。那种感觉,真的比手动点出来爽多了。这就是代码的力量,这就是“声明式”的魅力——我不告诉你怎么做,我只告诉你我要什么,剩下的你自己搞定。
CloudFormation:AWS的亲儿子怎么玩?
既然Terraform这么好用,那CloudFormation是不是就没人用了?也不是。在很多大厂,为了合规和安全,CloudFormation依然是首选。毕竟它是AWS亲生的,有些AWS的新功能,Terraform可能还得等插件更新,CloudFormation立马就能用。
CloudFormation的玩法稍微硬核一点。它不支持HCL,只认JSON或者YAML。说实话,JSON那大括号套中括号的格式,写多了能把人看瞎,所以咱们一般都用YAML。
咱们还是建个文件,叫 template.yaml。
AWSTemplateFormatVersion: '2010-09-09'
Description: 'My First CloudFormation Stack'
Resources:
MyEC2Instance:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: 'ami-0c55b159cbfafe1f0'
InstanceType: 't2.micro'
Tags:
- Key: Name
Value: 'MyFirstCfnServer'你看,这个结构也很清晰。Resources 下面定义资源。MyEC2Instance 是资源的逻辑名称,Type 指定了资源类型,Properties 里面写参数。这跟Terraform的逻辑其实是通的,只是语法换了身衣服。
运行CloudFormation,咱们得用AWS CLI。
aws cloudformation create-stack --stack-name my-first-stack --template-body file://template.yaml这命令一敲,AWS就开始干活了。你可以去控制台的CloudFormation界面看,它会创建一个叫 Stack 的东西。这个Stack就像是一个容器,把所有相关的资源都包进去了。
CloudFormation有个特别牛的功能叫“回滚”。如果创建过程中某一步失败了,比如安全组配置写错了,它会自动把刚才创建成功的那些资源全给删了,保证环境干净,不留一堆烂摊子。这点对于强迫症运维来说,简直是福音。以前用Shell脚本建到一半报错,你得手动去删那一堆半成品,删漏了还得花钱,那叫一个酸爽。
进阶一点:变量和状态管理
刚才咱们写的都是“硬编码”,把镜像ID直接写死在代码里。这在生产环境是大忌。真正的运维,代码和配置是分离的。
在Terraform里,咱们可以定义变量。建个 variables.tf 文件:
variable "instance_type" {
description = "The type of EC2 instance"
default = "t2.micro"
}然后在 main.tf 里引用:instance_type = var.instance_type。这样,以后想换个机型,改变量文件就行,不用动主逻辑。甚至可以在运行 terraform apply 的时候,通过命令行传参,或者搞个 terraform.tfvars 文件专门存环境变量。
这里得提一句Terraform最让人头疼,但也最核心的东西:状态文件。
你每次运行Terraform,它都会在当前目录下生成一个 terraform.tfstate 文件。这文件千万别小看,它记录了当前资源在云上的真实状态。Terraform之所以能那么聪明地知道是该创建还是该修改,全靠这个文件比对。
这就带来了一个团队协作的问题。如果你把代码传到了Git,但状态文件在本地,那同事拉取代码后运行,状态就对不上了。所以,生产环境一定要把状态文件存到远端,比如S3桶里,或者用Terraform Cloud。
配置远端状态也不难,在 main.tf 里加个backend配置:
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "ap-northeast-1"
}
}这样,大家就共享一份状态,谁在改代码,谁在跑Apply,一目了然。这事儿CloudFormation就不用操心,因为状态都在AWS自己肚子里存着呢,你只要管好模板就行。这也是CloudFormation省心的地方。
咱们再来聊聊“销毁”
运维不仅仅是建,还得会拆。以前手动删资源,经常漏删个EIP或者EBS卷,结果月底账单一来,莫名其妙多出几百块。
Terraform在这方面简直是神器。你想想,它能创建,就能销毁。只要一句 terraform destroy。这命令一敲,它会根据状态文件,把你刚才创建的所有资源,一个个按顺序删得干干净净。那种看着资源一个个消失,最后只剩下一个空目录的感觉,真的是极度舒适,解压神器。
CloudFormation也一样,删掉Stack,里面的资源自然就跟着没了。
不过这里有个坑,大家要注意。有些资源如果加了 prevent_deletion 的标签,或者状态文件丢失了,销毁的时候就会报错。特别是状态文件丢了,那真是叫天天不应,只能去控制台手动删,然后导入状态,那过程简直是渡劫。所以,状态文件的备份和权限管理,一定要重视,一定要重视,一定要重视!重要的事情说三遍。
实战中的那些坑和心得
理论讲了一堆,咱们聊点实战里的“坑”。
1. 依赖关系的坑
Terraform虽然能自动推断依赖,比如你建个EC2,它知道得先有VPC和Subnet。但有些隐式依赖它看不出来。比如你得等RDS数据库建好,才能往里面导数据。这时候就得显式指定 depends_on。
resource "aws_instance" "web" {
# ...
depends_on = [aws_instance.db]
}如果不加这个,Terraform可能会并行创建,结果Web服务器起起来了,数据库还没好,应用启动报错,排查半天才发现是顺序问题。
2. 配置漂移
这是最恶心的。你代码里写的是t2.micro,结果哪天为了临时救急,你在控制台手动把它改成了t3.medium。这时候,Terraform状态文件里记的还是t2.micro。下次一跑 terraform apply,它一看实际跟状态不符,二话不说给你改回去。这时候业务如果不兼容t2.micro,直接就崩了。
解决办法就是:管住手! 既然上了IaC,就别去控制台瞎点。实在要点,点完记得刷一下状态文件,用 terraform refresh 同步一下。或者用Terraform的 lifecycle 忽略某些变更,但这属于掩耳盗铃,不推荐。
3. 模块化
写到后面,你会发现 main.tf 越来越长,甚至好几个项目配置都差不多。这时候就该上模块了。把通用的配置抽出来,打个包。比如搞个 modules/web-server,以后新项目直接引用:
module "my_web" {
source = "./modules/web-server"
instance_count = 3
}这就像写代码封装函数一样,复用性极强。Terraform官方Registry上还有好多别人写好的模块,拿来稍微改改就能用,简直是摸鱼利器。但要注意,用别人的模块得看清楚版本,有时候作者更新了接口,你一拉代码就崩了,所以版本锁定很有必要。
结尾:从“搬砖”到“建筑师”
说了这么多,其实Terraform和CloudFormation只是IaC世界的冰山一角。Ansible、Pulumi这些工具也都各有千秋。但不管用哪个工具,核心思想都是一样的:把基础设施当软件来管理。
一旦你习惯了这种“代码即基础设施”的模式,你就再也回不去那个手动点控制台的时代了。你会发现自己从每天重复造轮子的“搬砖工”,变成了设计架构、编写蓝图的“建筑师”。以前熬夜配环境,现在代码提交,CI/CD流水线一跑,环境自动生成。那种掌控感,才是运维工作的核心价值所在。
别光看,赶紧找个AWS或者阿里云的免费账号练练手。哪怕先建个VPC,再建个Bucket,慢慢你就会发现其中的乐趣。遇到报错了别怕,看日志,查文档,Stack Overflow上搜一搜,这都是必经之路。
运维这条路,技术更新快,但万变不离其宗。掌握了IaC,你就在云原生时代站稳了脚跟。咱们共勉!
公众号:运维躬行录
个人博客:躬行笔记
如果这篇文章对你有点启发,哪怕只是帮你避了一个坑,或者让你对IaC有了那么一丢丢兴趣,哪怕只是觉得这哥们写得还挺接地气,都请帮忙点赞、在看、转发三连。咱们下期见,聊聊怎么用Ansible把服务器配置管理玩出花来!