前言
正如之前所说的,在有了 vCenter 之后,我们可以尝试把 Terraform 的部署平台从套娃虚拟化的 pve 迁移到 esxi 上来,方便管理,减小性能损耗。
Terraform 上 vSphere provider 的文档 真的难看,和 vm 有关的全部挤在一个页面,还只有一级目录,一点重点都没有,还有不同版本的配置放在一起的。最后还是找 cloud-init 上 VMware datasource 的文档 才知道要怎么搞的。本文就总结一下实际要做的步骤,外加一点个人的理解。
目标
- 支持使用 Terraform 在 esxi 平台上面全自动创建实例
- 新创建的实例自动初始化
创建虚拟机模板
下载 cloud image
先到 镜像站,下载最新的 ova 镜像(因为 vSphere 可以直接导入 ova 镜像),对应的应该是这个链接:https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cloud-images/noble/current/noble-server-cloudimg-amd64.ova
关于 cloud image 是什么,可以看我之前的博客。
导入 ova 镜像
这里在 vSphere 的界面里,选择**部署 OVF 模板
**这个功能,把刚刚下载的镜像导入进去,然后就能得到一台崭新的虚拟机了。
这个时候先不要着急启动,到配置里面,去把 vApp 选项给关掉,不然可能会影响后面的 cloud-init。
这个 vApp 呢,好像是 VMware 自己搞的一套配置项,具体是和 ovf/ova 里面的配置文件配合使用的,vApp 里面的每一项配置需要 ovf/ova 镜像提供支持。参考。
不过由于我们是使用 cloud-init 从外界的 datasource 传入配置信息的,所以就不需要这个镜像自己的配置了。而 vApp 的设置可能会覆盖掉我们从 datasource 传入的配置,所以要禁用 vApp。
关闭 vApp 之后呢,我们把这台虚拟机转换成模板,防止意外更改配置。
至此,模板就准备好了。
有了模板之后,我们就可以创建实例了。
写 tf 文件
先是很多引用,引用目前已有的资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
provider "vsphere" {
user = var.vsphere_user
password = var.vsphere_password
vsphere_server = var.vsphere_server
allow_unverified_ssl = true
api_timeout = 10
}
data "vsphere_datacenter" "datacenter" {
name = "Datacenter"
}
data "vsphere_datastore" "datastore" {
name = "0590"
datacenter_id = data.vsphere_datacenter.datacenter.id
}
data "vsphere_host" "esxi_host" {
name = "10.21.22.13"
datacenter_id = data.vsphere_datacenter.datacenter.id
}
|
然后引用模板
1
2
3
4
|
data "vsphere_virtual_machine" "template" {
name = "ubuntu-noble-24.04-cloudimg_240822"
datacenter_id = data.vsphere_datacenter.datacenter.id
}
|
最后再声明我们需要的资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
resource "vsphere_virtual_machine" "vm" {
name = "clone_test"
resource_pool_id = data.vsphere_host.esxi_host.resource_pool_id
datastore_id = data.vsphere_datastore.datastore.id
num_cpus = 8
memory = 4096
guest_id = data.vsphere_virtual_machine.template.guest_id
scsi_type = data.vsphere_virtual_machine.template.scsi_type
network_interface {
network_id = data.vsphere_network.network.id
adapter_type = data.vsphere_virtual_machine.template.network_interface_types[0]
}
disk {
label = "disk0"
size = data.vsphere_virtual_machine.template.disks.0.size
thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
}
cdrom {
client_device = true
}
clone {
template_uuid = data.vsphere_virtual_machine.template.id
}
extra_config = {
"guestinfo.userdata" = local.userdata
"guestinfo.userdata.encoding" = local.userdata-encoding
"guestinfo.metadata" = local.metadata
"guestinfo.metadata.encoding" = local.metadata-encoding
}
}
|
重点讲一下 extra_config
这个选项。参考 cloud-init 文档。
这几个选项是 VMware datasource 的配置方法。guestinfo.*.encoding
传入的是具体内容的编码,而 guestinfo.*
传入的是编码过后的内容。
只支持 metadata
,userdata
和vendordata
。关于如何配置网络,也就是network
配置,是通过直接写在 metadata 里面配置的。
接下来就是对 tf 和 user-data 做进一步的个性化了,具体根据需求决定吧。
我的代码文件 在这里。
总结
说难其实也不难,就是看 vSphere 的 provider 文档看了好久,有好几种配置的方式,也没有研究出来到底应该用哪一种,在这里耽误了好多时间。后面看到 cloud-init 的文档,方向就清晰很多了。
然后是感叹,pve 的 provider 的 bug 是真的多,比如说创建了机器之后就不能改配置了,不然逼着你重启,关键是重启也是有问题的,重启会卡死。现在换到 vSphere 就一点问题都没有了,爽到飞起,这就是金钱的力量吗。XD