terraform入门
1.介绍
基础结构即代码 (IaC) 工具允许您使用配置文件而不是通过图形用户界面来管理基础结构。IaC允许您通过定义可以版本、重用和共享的资源配置,以安全、一致和可重复的方式构建、更改和管理基础架构。
Terraform是HashiCorp的基础架构代码工具。它允许您在人类可读的声明性配置文件中定义资源和基础架构,并管理基础架构的生命周期。与手动管理基础架构相比,使用Terraform具有以下几个优点:
- Terraform可以管理多个云平台上的基础设施。
- 人类可读的配置语言可帮助您快速编写基础架构代码。
- Terraform的状态允许您跟踪整个部署中的资源更改。
- 您可以将配置提交到版本控制,以安全地在基础架构上进行协作。
说白了就是通过Terraform社区提供的多种插件实现通过api与云平台或者其他服务进行交互,比如操作云平台不用去平台点击操作等,
HashiCorp和Terraform社区已经编写了1,000多个提供商来管理Amazon Web Services (AWS),Azure,Google Cloud Platform (GCP),Kubernetes,Helm,GitHub,Splunk,和DataDog,
仓库地址:https://registry.terraform.io/browse/providers?product_intent=terraform
1.1标准化工作流
提供商将基础设施的各个单元 (例如计算实例或专用网络) 定义为资源。您可以将来自不同提供程序的资源组合到称为模块的可重用Terraform配置中,并使用一致的语言和工作流管理它们。
Terraform的配置语言是声明性的,这意味着它描述了基础架构所需的最终状态,而过程编程语言需要逐步说明才能执行任务。Terraform提供程序自动计算资源之间的依赖关系,以正确的顺序创建或销毁它们。
要使用Terraform部署基础结构,请执行以下操作:
- 范围-确定项目的基础设施。
- 作者-编写基础架构的配置。
- 初始化-安装Terraform管理基础设施所需的插件。
- 计划-预览Terraform将进行的更改以匹配您的配置。
- 应用-进行计划的更改。
1.2 架构
声明式vs命令式
1.3.Terraform 特性
声明式配置:
用户描述期望的基础设施状态,Terraform 会自动管理资源的创建、更新和删除。
跨平台支持:
Terraform 支持多种云提供商以及本地虚拟化环境。
模块化:
Terraform 提供模块化支持,方便重用配置。
2.安装
支持macOs、Windows、Linux,本次实现采用Linux环境部署,系统为Centos
在线安装
安装yum-config-manager
管理您的存储库。
yum install -y yum-utils
使用yum-config-manager
以添加官方的HashiCorp Linux存储库。
yum-config-manager -- add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
从新存储库安装Terraform。
yum -y install terraform
实际执行时报网络超时,所以采用了二进制方式安装
二进制安装
下载部署包
wget https://releases.hashicorp.com/terraform/1.10.5/terraform_1.10.5_darwin_arm64.zip
znzip terraform_1.10.5_darwin_arm64.zip
mv terraform /usr/bin
验证安装
[root@centos learn-terraform-docker-container]# terraform version
Terraform v1.10.5
on linux_amd64
+ provider registry.terraform.io/kreuzwerker/docker v3.0.2
开发一般是在windows,所以顺便加上部署方式
Terraform在MAC上安装还是相对简单的,由于缺少中文文档相关介绍内容,在Windows上安装也有踩了一些坑。推荐使用chocolatey进行安装。
安装Chocolatey
Chocolatey是一款基于Windows的包管理器,安装后可以轻松的像linux的yum、apt-get包管理器一样来管理你的windows中的应用。使用它来安装terraform的好处就是在后期删除升级都由它来管理,这是非常方便和快速的安装方法。
- 以管理员身份打开PowerShell,输入
Get-ExecutionPolicy
,返回Bypass
则代表目前执行的是绕过策略来安装。如果返回的是Restricted
受限制的,则需要运行Set-ExecutionPolicy AllSigned
或者Set-ExecutionPolicy Bypass -Scope Process
。 - 复制下面这条命令即可安装完成,这里没有太多坑。
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::Secu
安装terraform
choco install terraform
版本检查
PS C:\WINDOWS\system32> terraform version
Terraform v1.10.5
on windows_amd64
3.使用示例
3.1 Docker
创建目录
mkdir learn-terraform-docker-container
切换到目录并创建文件来定义基础设施
cd learn-terraform-docker-container
touch main.tf
写入如下内容到 main.tf
cat >main<<EOF
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 3.0.1"
}
}
}
provider "docker" {}
resource "docker_image" "nginx" {
name = "nginx:latest"
keep_locally = false
}
resource "docker_container" "nginx" {
image = docker_image.nginx.image_id
name = "tutorial"
ports {
internal = 80
external = 8000
}
}
EOF
上述描述Terraform中的基础设施文件为Terraform配置
在Terraform中,provider(提供程序)是用来与不同的基础设施平台进行交互的工具。例如,AWS、Azure、Google Cloud等。每个提供程序都需要在配置文件中进行声明,以便Terraform知道如何和哪个平台进行通信。
-
Terraform块
terraform {}
这个块是用来配置Terraform本身的一些设置的。它可以包含多个子配置,其中最常见的是指定要使用的提供程序(providers)。
-
required_providers
-
required_providers
是用来指定你在Terraform配置中使用的提供程序的。它告诉Terraform在哪儿下载这些提供程序,以及版本要求。 -
例如,如果你使用的是Docker的提供程序,你可以在这个块中这样写:
terraform { required_providers { docker = { source = "kreuzwerker/docker" version = "2.13.0" } } }
这段配置的意思是,你需要使用
kreuzwerker/docker
这个提供程序,并且使用的版本是2.13.0
。
-
-
provider source
source
字段指定了提供程序的来源。通常,提供程序从Terraform的官方注册中心(Terraform Registry)下载。- 在你提到的例子中,
source = "terraform.io/kreuzwerker/docker"
是指Docker提供程序来自于kreuzwerker
这个发布者。
-
版本约束
- 版本(
version
)是可选的,但建议明确指定版本。这样做是为了确保你的配置始终兼容特定版本的提供程序,避免将来Terraform自动下载新版本的提供程序时,出现不兼容的情况。 - 比如你可以指定某个版本或者版本范围,来确保使用的提供程序版本符合你的需求。
- 版本(
初始化项目,它会下载一个名为provider的插件,让Terraform与Docker交互。
terraform init
提供NGINX服务器容器apply
。当Terraform要求您确认类型时yes
并按ENTER
。
terraform apply
通过访问验证NGINX容器的存在本地主机: 8000在web浏览器中或运行docker ps
看看集装箱。
查看容器
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
425d5ee58619 e791337790a6 "nginx -g 'daemon of…" 20 seconds ago Up 19 seconds 0.0.0.0:8000->80/tcp tutorial
要停止容器,请运行terraform destroy
。
terraform destroy
您现在已经使用Terraform配置并销毁了NGINX web服务器。
3.2 Openstack
https://github.com/terraform-provider-openstack/terraform-provider-openstack/releases
新建工作目录
cd /home
mkdir learn-terraform-openstack
cd learn-terraform-openstack
创建配置文件 provider.tf
terraform {
required_providers {
openstack = {
source = "terraform-provider-openstack/openstack"
version = "1.38.0" # 使用与 OpenStack Train 版本兼容的提供程序版本
}
}
}
provider "openstack" {
user_name = "admin"
tenant_name = "admin"
password = "Hbis@xa202"
auth_url = "http://192.168.2.202:5000"
domain_name = "Default"
}
注意:选择与本地openstack版本兼容的提供商版本
在当前目录下执行 terraform init 命令,进行工作目录初始化和有关插件下载。由于是国外的源,需要耐心等待一些时间。 等到输出Terraform has been successfully initialized!的时候就表明初始化成功。 注:在openstack仪表板登录账户后,在访问API界面的“查看凭据”可以查看认证URL。
[root@centos learn-terraform-openstack]# terraform init
Initializing the backend...
Initializing provider plugins...
- Finding terraform-provider-openstack/openstack versions matching "1.38.0"...
- Installing terraform-provider-openstack/openstack v1.38.0...
- Installed terraform-provider-openstack/openstack v1.38.0 (self-signed, key ID 4F80527A391BEFD2)
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html
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.
实际的明文密码一般采用vault服务保存
a.操作网络资源
新创建network.tf
resource "openstack_networking_secgroup_v2" "terraform_test01" {
name = "terraform_test01"
description = "My neutron security group"
}
resource "openstack_networking_secgroup_rule_v2" "secgroup_rule_22" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 22
port_range_max = 22
remote_ip_prefix = "0.0.0.0/0"
security_group_id = "${openstack_networking_secgroup_v2.terraform_test01.id}"
}
-
openstack_networking_secgroup_v2
资源resource "openstack_networking_secgroup_v2" "terraform_test01" { name = "terraform_test01" description = "My neutron security group" }
这是一个
openstack_networking_secgroup_v2
资源,用来在 OpenStack 中创建一个新的 Neutron 安全组。- 第一个
terraform_test01
代表terraform资源的名称。
name
: 安全组的名称,这里是terraform_test01
,也就是在openstack平台展示的。description
: 安全组的描述信息,在这个例子中是"My neutron security group"
,用于描述该安全组的用途。
安全组是 OpenStack 中的网络防火墙,它控制入站和出站流量。每个安全组都有一系列的规则,用来定义哪些流量被允许进入或离开与该安全组关联的虚拟机。
- 第一个
-
openstack_networking_secgroup_rule_v2
资源resource "openstack_networking_secgroup_rule_v2" "secgroup_rule_22" { direction = "ingress" ethertype = "IPv4" protocol = "tcp" port_range_min = 22 port_range_max = 22 remote_ip_prefix = "0.0.0.0/0" security_group_id = "${openstack_networking_secgroup_v2.terraform_test01.id}" }
这是一个
openstack_networking_secgroup_rule_v2
资源,用来定义一条 安全组规则,控制流量的进出。direction
: 设置规则的方向,ingress
表示规则应用于入站流量,即允许进入实例的流量。如果是egress
,则是出站流量。ethertype
: 设置以太网类型,这里使用的是"IPv4"
,表示规则适用于 IPv4 流量。如果是"IPv6"
,则适用于 IPv6 流量。protocol
: 设置协议类型,这里使用的是"tcp"
,表示规则适用于 TCP 协议的流量。port_range_min
和port_range_max
: 定义了允许访问的端口范围。在这个例子中,两个值都为22
,表示允许流量进入端口 22(通常用于 SSH)。remote_ip_prefix
: 定义允许访问该端口的 IP 地址范围。在此例中,"0.0.0.0/0"
表示允许来自任何地方的流量,也就是对所有 IP 开放。security_group_id
: 关联的安全组 ID。这里使用了${openstack_networking_secgroup_v2.terraform_test01.id}
,这是引用前面定义的terraform_test01
安全组的 ID,以将规则添加到该安全组中。
执行应用
terraform apply
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
openstack_networking_secgroup_v2.terraform_test01: Creating...
openstack_networking_secgroup_v2.terraform_test01: Creation complete after 0s [id=b4715cf8-10ab-497f-a2b9-529099127f28]
openstack_networking_secgroup_rule_v2.secgroup_rule_22: Creating...
openstack_networking_secgroup_rule_v2.secgroup_rule_22: Creation complete after 0s [id=66196f37-f016-4427-b0c0-cf517898b84e]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
总结
创建了一个名为
terraform_test01
的 OpenStack 安全组,描述为 "My neutron security group"。为该安全组添加了一条规则,允许来自任何地方的入站 TCP 流量通过端口 22(通常用于 SSH)。
b.操作镜像
创建image.tf
resource "openstack_images_image_v2" "CirrOS_0_5_1" {
name = "CirrOS 0.5.1" # 镜像的名称
image_source_url = "http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-x86_64-disk.img" # 镜像文件的源 URL
container_format = "bare" # 容器格式,'bare' 代表裸机镜像
disk_format = "qcow2" # 磁盘格式,'qcow2' 是 OpenStack 支持的镜像格式
visibility = "public" # 镜像的可见性,'public' 代表该镜像对所有用户公开
properties = {
description = "CirrOS is a Tiny OS that specializes in running on a cloud" # 镜像的描述信息
original_source_url = "http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-x86_64-disk.img" # 原始源 URL
username = "cirros" # 用于登录镜像的用户名
password = "gocubsgo" # 用于登录镜像的密码
}
}
c.操作卷
创建没有镜像的卷
# 创建卷
resource "openstack_blockstorage_volume_v2" "test" {
region = "RegionOne"
name = "volume_test"
description = "测试创建卷"
size = 3 # 单位GB
}
# 绑定实例
resource "openstack_compute_volume_attach_v2" "va_1" {
instance_id = "af138e3d-d668-47c0-8fca-5ca5d6101295"
volume_id = "${openstack_blockstorage_volume_v2.test.id}"
}
上述instance_id
为已经存在的实例,当执行terraform destroy
删除卷时会解绑,并不会删除配置配置的实例。
使用镜像创建可启动卷
resource "openstack_blockstorage_volume_v2" "test" {
region = "RegionOne"
name = "volume_test"
description = "基于镜像创建卷"
size = 3 # 单位 GB
image_id = "your-image-id" # 替换为实际的镜像 ID
}
注意,每个项目下的资源名称必须唯一
d.操作实例
根据上述创建的镜像来创建实例
resource "openstack_compute_instance_v2" "test_instance" {
name = "test-instance"
image_id = "2365dea2-6e3e-4fc1-a87a-560d7c30fc5f" # 替换为实际的镜像 ID
flavor_id = "1" # 替换为实际的规格 ID
key_pair = ""
# 替换为实际的密钥对名称
network {
uuid = "9b2858ed-2e26-4fca-be5e-dbff7a34c255" # 替换为实际的网络 ID
}
security_groups = ["default"]
metadata = {
"instance_type" = "test"
}
availability_zone = "nova" # 如果有多个可用区,可以指定
}
- 镜像 ID: 使用
openstack image list
命令查看镜像列表,找到你需要的镜像 ID。 - Flavor ID: 使用
openstack flavor list
命令查看实例规格(flavor)列表,找到你需要的规格 ID。 - 网络 ID: 使用
openstack network list
命令查看网络列表,找到你想要连接的网络的 ID。 - 密钥对: 使用
openstack keypair list
查看你创建的密钥对,或者创建新的密钥对(例如:openstack keypair create my-key
)。
配置网络
确保你有一个可用的网络,并且你的实例配置使用了这个网络。在上面的示例中,network
部分使用了网络的 UUID。如果你没有现成的网络,你可以通过以下命令创建一个网络:
openstack network create my_network
然后创建子网
openstack subnet create --network my_network --subnet-range 192.168.1.0/24 my_subnet
当然,创建网络其实也可以使用terraform。
创建密钥对
如果你还没有创建密钥对,你可以使用以下命令创建:
openstack keypair create --public-key ~/.ssh/id_rsa.pub my-key
执行 terraform apply
后,发现实例创建成功,但是绑错了网络,如何修改?只需要修改网络ID即可,重新执行
openstack_compute_instance_v2.test_instance: Destroying... [id=6e8364fb-8e2e-43b3-a754-ee86b382e3c0]
openstack_compute_instance_v2.test_instance: Still destroying... [id=6e8364fb-8e2e-43b3-a754-ee86b382e3c0, 10s elapsed]
openstack_compute_instance_v2.test_instance: Destruction complete after 12s
openstack_compute_instance_v2.test_instance: Creating...
openstack_compute_instance_v2.test_instance: Still creating... [10s elapsed]
openstack_compute_instance_v2.test_instance: Creation complete after 14s [id=fba6ed15-0aa5-46ac-9524-503688c2ad74]
Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
发现其实是先删除然后重新创建,所以terraform采用声明式对用户来说只是维护了最终状态,其中的删除、创建自动实现了。
执行terraform plan
查看更新计划
[root@centos learn-terraform-openstack]# terraform plan
openstack_compute_instance_v2.test_instance: Refreshing state... [id=fba6ed15-0aa5-46ac-9524-503688c2ad74]
openstack_compute_flavor_v2.test-flavor: Refreshing state... [id=b04eb87a-869f-4c2b-a640-b0cbfc4cf86b]
openstack_networking_secgroup_v2.terraform_test01: Refreshing state... [id=c330e5a2-da51-4900-912e-1d5ff2b027dc]
openstack_blockstorage_volume_v2.test: Refreshing state... [id=39c425c3-96b0-4a26-9f8f-77ffed50632a]
openstack_images_image_v2.CirrOS_0_5_1: Refreshing state... [id=2365dea2-6e3e-4fc1-a87a-560d7c30fc5f]
openstack_networking_secgroup_rule_v2.secgroup_rule_22: Refreshing state... [id=3fc09045-a976-4be7-a072-fd9ec428d3c2]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# openstack_compute_instance_v2.test_instance must be replaced
-/+ resource "openstack_compute_instance_v2" "test_instance" {
~ access_ip_v4 = "10.0.0.57" -> (known after apply)
+ access_ip_v6 = (known after apply)
~ all_metadata = {
- "instance_type" = "test"
} -> (known after apply)
~ all_tags = [] -> (known after apply)
~ flavor_name = "m1.tiny" -> (known after apply)
~ id = "fba6ed15-0aa5-46ac-9524-503688c2ad74" -> (known after apply)
~ image_name = "CirrOS 0.5.1" -> (known after apply)
name = "test-instance-1"
+ region = (known after apply)
- tags = [] -> null
# (9 unchanged attributes hidden)
~ network {
对于网络会影响到实例的使用,所以terraform会执行重建
但是修改实例名称重新apply后并没有创建新的实例,而是基于当前已经部署的基础上修改
虽然修改了实例的名称(
name
属性),Terraform 认为这是一个可以进行更新的操作,而不是一个需要销毁并重新创建的操作。这是因为许多云服务提供商(包括 OpenStack)允许某些属性(如虚拟机实例的名称)在实例创建后进行修改,而不会影响资源本身的生命周期。
e.操作实例类型(Flavor)
resource "openstack_compute_flavor_v2" "test-flavor" {
name = "8m2c20d"
ram = 8096 # 内存,单位为 MB
vcpus = 2 # 虚拟 CPU 数量
disk = 20 # 磁盘大小,单位为 GB
is_public = true # 是否公开
extra_specs = {
"capabilities:hypervisor_type" = "s!= ironic"
}
}
4.基本命令
基础命令
- terraform init 初始化工作目录,加载相关provider插件,并解析当前目录下的tf文件
- terraform plan 代码预执行,告知用户将会对哪些资源进行变更
- terraform apply 执行任务
- terraform destroy 根据当前工作目录下的terraform状态文件来对任务进行销毁。也就是说只会销毁在这个工作目录下执行过的任务。
列出所有的对象
[root@centos learn-terraform-openstack]# terraform state list
openstack_blockstorage_volume_v2.test
openstack_blockstorage_volume_v2.test_1
openstack_compute_flavor_v2.test-flavor
openstack_compute_instance_v2.test_instance
openstack_images_image_v2.CirrOS_0_5_1
openstack_networking_secgroup_rule_v2.secgroup_rule_22
openstack_networking_secgroup_v2.terraform_test01
[root@centos learn-terraform-openstack]#
查看详情
[root@centos learn-terraform-openstack]# terraform state show openstack_blockstorage_volume_v2.test
# openstack_blockstorage_volume_v2.test:
resource "openstack_blockstorage_volume_v2" "test" {
attachment = []
availability_zone = "nova"
description = "测试创建卷"
id = "39c425c3-96b0-4a26-9f8f-77ffed50632a"
metadata = {}
name = "volume_test"
region = "RegionOne"
size = 3
snapshot_id = null
source_vol_id = null
volume_type = "iscsi"
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南