Skip to main content

Create vSphere Template with Packer

Table of Contents

The last months I built a lot of environments for tests with IBM Connections Componentpack, Rancher, plain Kubernetes, IBM Domino and some more. In former years, I deployed single virtual machines, cloned them and created snapshots to “easily” jump back in cases of errors. Then I found Packer, which helped me to automate the first virtual machines on my local notebook.

Now I use Packer to create templates for VMware vSphere, which then are deployed and multiplied with Terraform. Terraform needs some packages installed in the template, that it can provision virtual machines on vSphere.

  • Open VM-Tools

  • Perl

You can find all files and scripts on Gitlab.

The definition is simplified to make it better readable. As best practise I would recommend to add a variabe section to the packer file, so you avoid to type the same information over and over again.

In this article I just prepare the template. Working with Terraform will be covered in a future post.

One thing more, to install additional software on the provisioned servers later, I will use Ansible. Ansible needs ssh and Python.

First CentOS template
#

To create a template for CentOS, we start with a kickstart file, which is used by Packer to install and configure the template.

Create a root password

echo 'import crypt,getpass; \
  print crypt.crypt(getpass.getpass(), "$5$16_CHARACTER_SALT_HERE")' | python -

Replace $16_CHARACTER_SALT_HERE with 16 random characters.

Example to generate 16 random characters

openssl rand -base64 24 | cut -c-16

Kickstart File
#

You can find one in my GPN19 repo at Gitlab.com.

Simple kickstart file

install
lang en_US.UTF-8
keyboard de
timezone Europe/Berlin
auth --useshadow --enablemd5
services --enabled=NetworkManager,sshd
eula --agreed
ignoredisk --only-use=sda
reboot

bootloader --location=mbr
zerombr
clearpart --all --initlabel
part swap --asprimary --fstype="swap" --size=1024
part /boot --fstype xfs --size=200
part pv.01 --size=1 --grow
volgroup rootvg01 pv.01
logvol / --fstype xfs --name=lv01 --vgname=rootvg01 --size=1 --grow

authconfig --enableshadow --passalgo=sha256
rootpw --iscrypted $5$cnxfyyiayqjelmbt$4/Lq1vPDBp2BZznXcLukwVy4n0DPp6tX.PrCz7YA62B

%packages --nobase --ignoremissing
@core
%end

Packer JSON
#

To tell Packer how our template should be installed, start with following file:

{
  "builders": [  
    {
      "type": "vmware-iso",
      "boot_command": [
         "<tab> text ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/kickstart-de.cfg<enter>"
      ],
      "communicator": "ssh",
      "guest_os_type": "centos7-64",
      "http_directory": "http",
      "iso_checksum_type": "sha256",
      "iso_checksum_url": "http://ftp.halifax.rwth-aachen.de/centos/7.6.1810/isos/x86_64/sha256sum.txt",
      "iso_url": "http://ftp.halifax.rwth-aachen.de/centos/7.6.1810/isos/x86_64/CentOS-7-x86_64-Minimal-1810.iso",
      "ssh_username":"root",
      "ssh_password":"password",  
      "ssh_wait_timeout": "600s",
      "shutdown_command": "shutdown -P now",
      "version": 14
    }
  ],
  "provisioners": [ 
      {
          "type": "shell",
          "expect_disconnect": true,
          "execute_command": "sudo UPDATE=true bash '{{ .Path  }}'",
          "environment_vars": [
            "UPDATE=true"
          ],
          "scripts": [  
            "script/epel.sh",
            "script/kernel.sh",
            "script/sshd.sh",
            "script/vmtools.sh",
            "script/update.sh",
            "script/reboot.sh",
            "script/ansible.sh",
            "script/cleanup.sh"
          ]
      }
  ],
  "post-processors": [ 
      [
        {
            "type": "vsphere",  
            "cluster": "HMUC PWR HOSTS",
            "host": "vsphere.example.com",
            "datacenter": "HMUC",
            "resource_pool": "rp_hvie_devops",
            "username": "cstoettner@example.com",
            "password": "{{user `vsphere_password`}}",
            "datastore": "devops-01_sas_7.2k_raid10",
            "vm_name": "stoeps-centos-gpn19",
            "vm_folder": "devops",
            "vm_network": "vm-net-devops",
            "disk_mode": "thin",
            "insecure": "true",
            "overwrite": "true"
        },
        {
            "type": "vsphere-template",  
            "host": "vsphere.example.com",
            "insecure": "true",
            "datacenter": "HMUC",
            "username": "cstoettner@example.com",
            "password": "{{user `vsphere_password`}}",
            "folder": "/devops/templates"
        }
      ]
   ]
}
  • Builder (building the vmware itself)

  • Provisioner (run some scripts on the new deployed machine)

  • Post-Processor (upload to VMware vSphere)

  • The order is important, or Terraform can’t recognize the vm tools

  • Post-Processor to upload the VM to vSphere

  • Post-Processor to tag it as template

  • I set the root password to password in the kickstart

The kickstart file generates the user root with password password. During the deployment with Terraform I disable the password login with passwd -l root, so the root user needs to use a ssh-key for authentication.

Thanks to Nico for the tip with passwd --lock.

This configuration file uses a lot of default values from VMware, like disk space, cpu count and so on. All these can be changed later during our Terraform deployment.

Within the Provisioner part, I use some scripts, to add:

  • EPEL repository

  • Install open-vm-tools, perl, python

  • Update all installed packages

  • Update the kernel to the latest version (in the moment 5.1)

    • The original CentOS kernel is quite old and the Docker support needs some tweaks like the usage of device-mapper, that’s the main reason for the update
  • Reboot (important to do this after the open-vm-tools installation, because without Terraform will not recognize the tools and not deploy)

  • Cleanup (deleting host keys, repositories and so on)

During my talk at GPN19, someone pointed me to Systemd machine id. I always ignored this, but I added the delete command to the cleanup script and the create command into my Terraform file. Thanks for this hint!

Create the template
#

packer build -var vsphere_password=My_Vsphere_password centos.json

I use a variable for the password, because I always check-in my definition files to git and I don’t want to have passwords there in the history.

I created a video of the creation, please try the command yourself, or have a look at it.

Now our template is uploaded to vSphere. Using it within Terraform will be another post.

Christoph Stoettner
Author
Christoph Stoettner
I work at Vegard IT GmbH as a senior consultant, focusing on collaboration software, Kubernetes, security, and automation. I primarily work with HCL Connections, WebSphere Application Server, Kubernetes, Ansible, Terraform, and Linux. My daily work occasionally leads to technical talks and blog articles, which I share here more or less regularly.

Related

Asciidoctor Windows

During my talk at FrOSCon I wasn’t sure how to install Asciidoctor on Windows. So I tried on a Windows 10 VM. When you want to use Asciidoctor on a Windows desktop, you need to download the Rubyinstaller and install it. Now you can open a administrative command window and install with gem install asciidoctor.

Using Docker and ELK to Analyze WebSphere Application Server SystemOut.log

I often get SystemOut.log files from customers or friends to help them analyzing a problem. Often it is complicated to find the right server and application which generates the real error, because most WebSphere Applications (like IBM Connections or Sametime) are installed on different Application Servers and Nodes. So you need to open multiple large files in your editor, scroll each to the needed timestamps and check the lines before for possible error messages.