介绍
packer和terraform都是HashiCorp公司的产品,packer是个开源工具,用于构建虚机模板。他们的理念是INFRASTRUCTURE AS CODE,以code的方式来搭建基础架构。诚然各个云平台,从aws到微软的azure到阿里云,都提供了各自的工具来创建虚机模板。而packer提供给我们的是一个相对统一的工具,通过代码格式定义模板,然后作用于各个云平台。此篇文字记录了试用的过程以及踩过的坑。
目的
基于vmware的vsphere平台,构建自动化部署搭建环境所需要的虚机。
实践
- 创建ubuntu18.04模板
通过json文件来定义模板,创建文件ubuntu18.04,其中主要分builders,provisioners和variables三个部分,builders中用来定义虚机模板的硬件配置,网络配置等信息。provisioners用于处理预安装软件的情形,variables则定义变量。以下是一个例子,省略了部分信息。
{
"builders": [
{
"type": "vsphere-iso",
"vcenter_server": "{{user `vcenter-server`}}",
"username": "{{user `vcenter-username`}}",
"password": "{{user `vcenter-password`}}",
###省略
"ssh_username": "{{user `ssh-username`}}",
"ssh_password": "{{user `ssh-password`}}",
"vm_name": "{{user `vm-name`}}",
"convert_to_template": "true",
"network_adapters": [
{
"network": "{{user `network`}}",
"network_card": "vmxnet3"
}
],
###省略
"iso_paths": [
"{{user `os_iso_path`}}"
],
"floppy_files": [
"./ubuntu/preseed.cfg"
],
"http_directory": ".",
"boot_command": [
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"/install/vmlinuz",
" initrd=/install/initrd.gz",
" priority=critical",
" locale=en_US",
" file=/media/preseed.cfg",
""
]
}
],
"provisioners": [
{
"type": "file",
"sources": ["./ubuntu/containerd.io.deb","./ubuntu/docker-ce.deb","./ubuntu/docker-ce-cli.deb","./ubuntu/docker-compose-Linux-x86_64"],
"destination": "/tmp/"
},
{
"type": "shell",
"inline": [
"echo '{{user `ssh-password`}}' | sudo -S sh -c 'dpkg -i /tmp/containerd.io.deb /tmp/docker-ce.deb /tmp/docker-ce-cli.deb'",
"echo '{{user `ssh-password`}}' | sudo -S sh -c 'usermod -aG docker witadmin'",
"echo '{{user `ssh-password`}}' | sudo -S sh -c 'sudo mv /tmp/docker-compose-Linux-x86_64 /usr/local/bin/docker-compose'",
"echo '{{user `ssh-password`}}' | sudo -S sh -c 'sudo chmod +x /usr/local/bin/docker-compose'",
"echo 'Packer Template Build -- Complete'"
]
}
],
"variables":
{
"vm-name": "Ubuntu-1804-Template",
"datacenter": "DC",
###省略
"os_iso_path": "[datastore1] iso/ubuntu-18.04.5-server-amd64.iso"
}
}
对于其中比较重要的解释一下:
- type 用于定义类型,这里我们用的vsphere-iso,packer工具会使用vsphere-iso的provider进行工作,其调用vspshere api进行实际操控。
- iso_paths 定义iso文件的路径,这里可以指向exsi上存储的某个iso文件,在variables部分可以看到
- floppy_files 这里的内容会作为一个软盘挂载到虚机中,可能知道软盘,见过软盘的同学已经都转行了吧,哈哈。软盘有容量限制,超过1.44M会报失败,所以这里合适的是放一些需要自动执行的脚本文件。
- http_directory packer在运行过程中,会启用一个http服务器,这里指定的就是http服务器的根路径,这里适合放需要抓取的内容或者通过http可访问的内容
- boot_command 启动命令,这里要注意的是file=/media/preseed.cfg指明了自动应答文件,通过这个文件,可以让ubuntu18无人值守自动安装,具体内容格式参考ubuntu官方文档。
provisioners部分定义需要预安装/处理的内容
- "type": "file" 这里定义需要上传的文件,因为一般权限是非root用户,所以针对linux,最好是将文件都上传到/tmp目录
- "type": "shell" 这里定义执行的命令,我这里是把docker和docker-compose默认安装了。由于使用的是ubuntu系统,非root用户,当需要用到sudo权限的时候,这里需要小技巧传入sudo 的密码后执行。
创建模板
执行命令
packer.exe build ubuntu\ubuntu18.json
packer会连接vsphere,等待10分钟,即可创好虚机并自动转换为模板。注意网络中需要有DHCP服务器,因为packer会等待创建的虚机获得IP,然后才能通过ssh或者powershell(windows虚机)进行后面的动作,否则会创建失败。
创建虚机
有了模板,下一步可以根据模板来创建虚机了。terraform是我们要使用的工具,可以先定义好我们需要的虚机的各个方面,即一个蓝图,然后统一来执行。
用到的文件包括以下几个:
- main.tf 定义虚机
- varable.tf 定义用到的变量
- terraform.tfvars 定义变量的值,如果这里没有,运行时就会询问用户输入
- output.tf 定义输出的执行计划中关键项,会高亮显示(如果终端支持高亮)
看一个 main.tf的例子
provider "vsphere" {
user = var.vsphere_user
password = var.vsphere_password
vsphere_server = var.vsphere_server
# If you have a self-signed cert
allow_unverified_ssl = true
}
##### Data sources
data "vsphere_datacenter" "target_dc" {
name = var.vsphere_datacenter
}
data "vsphere_datastore" "target_datastore" {
name = var.vsphere_datastore
datacenter_id = data.vsphere_datacenter.target_dc.id
}
data "vsphere_compute_cluster" "target_cluster" {
name = var.vsphere_cluster
datacenter_id = data.vsphere_datacenter.target_dc.id
}
data "vsphere_network" "target_network" {
name = var.vsphere_network
datacenter_id = data.vsphere_datacenter.target_dc.id
}
data "vsphere_virtual_machine" "source_template" {
name = var.guest_template
datacenter_id = data.vsphere_datacenter.target_dc.id
}
resource "vsphere_virtual_machine" "witith01" {
name = "WiTiTH01"
resource_pool_id = data.vsphere_compute_cluster.target_cluster.resource_pool_id
datastore_id = data.vsphere_datastore.target_datastore.id
num_cpus = 2
memory = 1024
guest_id = data.vsphere_virtual_machine.source_template.guest_id
scsi_type = data.vsphere_virtual_machine.source_template.scsi_type
network_interface {
network_id = data.vsphere_network.target_network.id
adapter_type = data.vsphere_virtual_machine.source_template.network_interface_types[0]
}
disk {
label = "disk0"
size = 20
eagerly_scrub = data.vsphere_virtual_machine.source_template.disks[0].eagerly_scrub
thin_provisioned = data.vsphere_virtual_machine.source_template.disks[0].thin_provisioned
}
clone {
template_uuid = data.vsphere_virtual_machine.source_template.id
customize {
timeout = "20"
linux_options {
host_name = "WiTiTH01"
domain = var.guest_domain
}
network_interface {
ipv4_address = var.guest_ipv4_ith01
ipv4_netmask = 24
}
ipv4_gateway = var.guest_ipv4_gateway
dns_server_list = [var.guest_dns_servers]
}
}
}
- provider 指明了我们是用vsphere
- data 项定义了vsphere中的信息
- resource 定义了具体的虚机,指明了从哪个模板克隆
一般定义文件都是放在一个文件夹中,都定义好以后,可以通过命令初始化
terraform.exe init
这个一个项目只需运行一次,terraform会去下载vsphere的provider,就像nodejs项目的init类似
然后生成执行计划
terraform.exe plan -out ./test.out
这一步会检查并显示输出具体的计划,确认无误了就可以应用了
terraform.exe apply ./test.out
然后terraform就会去连接vsphere帮你创建虚机了。
坑爹的事情来了,我在创建虚机时,报错,虚机创建出来了,但是customize 失败,自定义项完全没有应用上去,虚机的network都没有,主机名也没变。花了一晚上的时间找原因。通过无数次比较,发现手动创建的ubuntu18模板没问题,而通过packer创建的模板就有问题。再查看虚机的日志,发现有问题的虚机会报错,缺少模块 File/stat.pm. 搜索得知,open-vm-tools 开源工具需要这个文件,在ubuntu下对应的包是perl-modules-5.26, 一看出问题的虚机上果然没有。从模板就没有。
所以,在packer制作模板时就要加上这个包,具体方法可以定义在preseed.cfg文件里面,指明安装
d-i pkgsel/include string open-vm-tools openssh-server vim wget curl python perl-modules-5.26
重新制作模板后,测试通过,可快速创建虚机。
最终效果,创建模板花了10分钟,创建3台ubuntu虚机花了2分钟,下一步就是将业务软件的安装全自动化,这又是另一个故事了。