Background
For a while now I have been struggling with Packer templates built with Ubuntu 20.04 server deployed on VSphere 7.0. When I build the packer image and deploy VM’s with terraform specifying a static IP with terraforms customize block, DHCP would pick up an additional IP address as well as the static IP.
I found that the issue stemmed from packer requiring dhcp assignment for the post deploy ssh shell provisioner. To solve this issue a few lines of code were added to the provisioner to:
- Remove netplan config
- Remove dhcp from grub file
- Update grub
- Purge cloud-init
Code
I have included the .hcl code below, after building this template, all terraform provisioned vm’s off this template will only have the static IPs assigned via the customize block.
source “vsphere-iso” “this” { | |
vcenter_server = var.vsphere_server | |
username = var.vsphere_user | |
password = var.vsphere_password | |
datacenter = var.datacenter | |
cluster = var.cluster | |
insecure_connection = true | |
vm_name = “tf-ubuntu-server-20.04” | |
guest_os_type = “ubuntu64Guest” | |
ssh_username = “ubuntu” | |
ssh_password = “ubuntu” | |
ssh_timeout = “20m” | |
ssh_handshake_attempts = “50” | |
CPUs = 8 | |
RAM = 4128 | |
RAM_reserve_all = true | |
disk_controller_type = [“pvscsi”] | |
datastore = var.datastore | |
storage { | |
disk_size = 16384 | |
disk_thin_provisioned = true | |
} | |
iso_paths = [“[iSCSI Raid-10] OS/ubuntu-20.04.2-live-server-amd64.iso”] | |
iso_checksum = “sha256:b23488689e16cad7a269eb2d3a3bf725d3457ee6b0868e00c8762d3816e25848” | |
http_directory = “subiquity/http” | |
http_port_max = 8336 | |
http_port_min = 8336 | |
network_adapters { | |
network = var.network_name | |
network_card = “vmxnet3” | |
} | |
boot_wait = “5s” | |
boot_command = [ | |
” “, | |
“autoinstall net.ifnames=0 biosdevname=0 ip=dhcp ipv6.disable=1 ds=nocloud-net;seedfrom=http://192.168.0.168:{{ .HTTPPort }}/”, | |
“” | |
] | |
} | |
build { | |
sources = [ | |
“source.vsphere-iso.this” | |
] | |
provisioner “shell” { | |
inline = [ | |
“while [ ! -f /var/lib/cloud/instance/boot-finished ]; do sleep 5; done”, | |
“sudo rm /etc/netplan/*”, | |
“sudo sed -i ‘s/ip=dhcp//g’ /etc/default/grub”, | |
“sudo update-grub”, | |
“sudo apt -y purge cloud-init” | |
] | |
} | |
} |
I have also include a sample main.tf below:
provider "vsphere" { | |
vsphere_server = var.vsphere_server | |
user = var.vsphere_user | |
password = var.vsphere_password | |
# If you have a self-signed cert | |
allow_unverified_ssl = true | |
} | |
data "vsphere_datacenter" "dc" { | |
name = var.datacenter | |
} | |
data "vsphere_resource_pool" "pool" { | |
name = var.resourcepool | |
datacenter_id = data.vsphere_datacenter.dc.id | |
} | |
data "vsphere_datastore" "datastore" { | |
name = var.datastore | |
datacenter_id = data.vsphere_datacenter.dc.id | |
} | |
data "vsphere_network" "network" { | |
name = var.network_name | |
datacenter_id = data.vsphere_datacenter.dc.id | |
} | |
data "vsphere_virtual_machine" "ubuntu" { | |
name = var.ubuntu_name | |
datacenter_id = data.vsphere_datacenter.dc.id | |
} | |
resource "vsphere_virtual_machine" "k8Master1-0" { | |
name = "k8Master1-0" | |
resource_pool_id = data.vsphere_resource_pool.pool.id | |
datastore_id = data.vsphere_datastore.datastore.id | |
network_interface { | |
network_id = data.vsphere_network.network.id | |
adapter_type = "vmxnet3" | |
} | |
num_cpus = 4 | |
memory = 4128 | |
wait_for_guest_net_timeout = 0 | |
wait_for_guest_ip_timeout = 0 | |
disk { | |
label = "disk0" | |
thin_provisioned = true | |
size = 16 | |
} | |
guest_id = "ubuntu64Guest" | |
clone { | |
template_uuid = data.vsphere_virtual_machine.ubuntu.id | |
customize { | |
network_interface { | |
ipv4_address = "192.168.0.208" | |
ipv4_netmask = 24 | |
} | |
ipv4_gateway = "192.168.0.1" | |
linux_options { | |
host_name = "k8Master1-0" | |
} | |
} | |
} | |
} |
I hope this quick write up help anyone with this issue. It took me quite a bit of researching and was unable to find a single solution. I wished that a resource such as this one was available so I decided to make it.