Ubuntu, Cloud-Init, vSphere and vRealize Automation - A short tale of misery
| 5 minutes
VMware vRealize Automation Packer Cloud-Init Ubuntu

Cloud-Init and Hostnames

First problem was Ubuntu 20.04 to properly boot from the Packer HTTP directory. I found approximately 3,125,319 blogs online all with different Ubuntu boot commands. I settled on this:

boot_command = [
    "c",
    "linux /casper/vmlinuz --- autoinstall ds=\"nocloud-net;seedfrom=http://{{.HTTPIP}}:{{.HTTPPort}}/\"",
    "<enter><wait>",
    "initrd /casper/initrd",
    "<enter><wait>",
    "boot<enter>"
]

Next up was a working user-data file for the boot customisation process. I settled on a mish-mash of different examples found online:

#cloud-config
autoinstall:
    version: 1
    early-commands:
        # Stop ssh for packer
        - sudo systemctl stop ssh
    locale: en_US
    keyboard:
        layout: en
        variant: us
    # general packages needed for machines - referenced from https://tekanaid.com/posts/hashicorp-packer-build-ubuntu20-04-vmware
    packages: [open-vm-tools, openssh-server, cloud-init]
    # network setup - referenced from https://tekanaid.com/posts/hashicorp-packer-build-ubuntu20-04-vmware
    identity:
        hostname: ubuntu-tmpl
        username: ubuntu
        password: '$6$rounds=4096$M7sE5MB76OAGlRVL$cB7KGUsihonBTndSGBkfsdN0EzIDBeuY6ENt3kRuazSEJZhqRxeSaC.5/E4KRksGdOTRPA8sXWlpRSlUUrXVo1'
    ssh:
        install-server: yes
        allow-pw: yes
    storage:
        layout:
            name: lvm
    apt:
        primary:
            - arches: [i386, amd64]
              uri: "http://archive.ubuntu.com/ubuntu/"
    user-data:
        disable_root: false
        timezone: UTC
    late-commands:
        - sed -i -e 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/g' /target/etc/ssh/sshd_config
        - echo 'ubuntu ALL=(ALL) NOPASSWD:ALL' > /target/etc/sudoers.d/ubuntu
        - curtin in-target --target=/target -- chmod 440 /etc/sudoers.d/ubuntu

Pay careful attention to the default user and password that is created. The password should be generated using sha-512 with 4096 rounds. Command was mkpasswd --method=sha-512 --rounds=4096 <password>. The password in this example was VMware1!.

After cloud-init is finished, I would have a “prep” script run to clean everything up, ready for template time:

#!/bin/bash

echo '> Cleaning all audit logs ...'
if [ -f /var/log/audit/audit.log ]; then
cat /dev/null > /var/log/audit/audit.log
fi
if [ -f /var/log/wtmp ]; then
cat /dev/null > /var/log/wtmp
fi
if [ -f /var/log/lastlog ]; then
cat /dev/null > /var/log/lastlog
fi
# Cleans SSH keys.
echo '> Cleaning SSH keys ...'
rm -f /etc/ssh/ssh_host_*
# Sets hostname to localhost.
echo '> Setting hostname to localhost ...'
cat /dev/null > /etc/hostname
hostnamectl set-hostname localhost
# Cleans apt-get.
echo '> Cleaning apt-get ...'
apt-get clean
# Cleans the machine-id.
echo '> Cleaning the machine-id ...'
truncate -s 0 /etc/machine-id
rm /var/lib/dbus/machine-id
ln -s /etc/machine-id /var/lib/dbus/machine-id

# Reset the machine-id value. This has known to cause issues with DHCP
#
truncate -s 0 /etc/machine-id
rm /var/lib/dbus/machine-id
ln -s /etc/machine-id /var/lib/dbus/machine-id

# Reset any existing cloud-init state
#
echo "Resetting Cloud-Init"
rm /etc/cloud/cloud.cfg.d/*.cfg
cloud-init clean -s -l

Once Packer is finished, you’ll end up with a VM template in vSphere. Go to vRealize Automation and rescan for images in the Cloud Accoount that contains this new template.

Here’s my first stumble. Deploying a VM from this template with a cloud-config specification would never be customised. No matter what I tried, it just didn’t work and not even something as basic as the hostname was being set. I found a boat load of blogs recommending I install the custom VMware Guest Info plugin for Cloud Init by running this installation script during the template build. Well, I tried that and still had no luck. I tried using dpkg-reconfigure cloud-init to specify OVF and VMware Guest Info as the the data source for cloud-init but had no luck there either as it was interactive and I couldn’t find a headless command to run it.

It wasn’t until a few days passed and many template builds later that I had a good look at the VMware Guest Info README. The install script repo for the VMware Data source had been archived! This caught my eye:

This datasource has been merged into cloud-init as DataSourceVMware

Right, I think that’s it! I added a quick line to my prep script:

# Adding VMware Data Source
echo 'datasource_list: [ "DataSourceVMware", "OVF" ]' > /etc/cloud/cloud.cfg.d/00-ovf-data.cfg

Re-ran the build and tested it in vRA. Yep, hostname is now being set! Let’s move on.

vRA-defined user not being set in vRA deployment

vRA supports Cloud-Init customisation of guests using Cloud-Init on Linux and Cloudbase-Init for Windows. With my new template now customising the hostname, I noticed the default ubuntu account was being reset and I couldn’t log in with the password. Looking at the deployment, vRA was pushing the following cloud-init config:

#cloud-config
hostname: u20

No config was being pushed for the default ubuntu user. Found on the docs here: https://cloudinit.readthedocs.io/en/latest/topics/examples.html#including-users-and-groups that in order to reset the default user, typically ubuntu on a fresh install, you need to add this code to your cloud-init:

#cloud-config
hostname: u20-2
system_info:
  default_user:
    name: ubuntu
    plain_text_passwd: ((secret:v1:AAHTS2SZncwnv3EGYDhbz9Q8w812JKePvy1l2zrPJFmIHLMyr3/h8g==))
    home: /home/ubuntu
    shell: /bin/bash
    lock_passwd: false

If you specify a remoteAccess user that differs to the ubuntu account, vRA will try to push another user as the default:

#cloud-config
hostname: u20-2
system_info:
  default_user:
    name: ubuntu
    plain_text_passwd: ((secret:v1:AAHTS2SZncwnv3EGYDhbz9Q8w812JKePvy1l2zrPJFmIHLMyr3/h8g==))
    home: /home/ubuntu
    shell: /bin/bash
    lock_passwd: false
users:
- default
- name: stell
  lock_passwd: false
  ssh_pwauth: true
  passwd: ((secret:v1:AAGgzY4Hjbqux3HW/PXJjXbycZ3UiWH62EfgdfCELzaZ3KQCNTvPTA==))
runcmd:
- sudo sed -i -e '/^PasswordAuthentication/s/^.*$/PasswordAuthentication yes/' /etc/ssh/sshd_config
- sudo sed -i -e '/^PermitRootLogin/s/^.*$/PermitRootLogin yes/' /etc/ssh/sshd_config
- sudo service sshd restart

In the above example, my cloud-config was the hostname and system_info > default_user config, and the remoteAccess configuration from the Cloud Template was parsed and added under the users block. Note: The remoteAccess user specified will passed to Salt Stack Config to connect to the guest and install the Salt Minion, so make sure you’re giving it the right access.

That’s pretty much it! Sorry for the rushed writing, these are notes more for myself than anything.

About Stellios Williams
Senior Cloud Solutions Architect - Service Providers VMware
This is my personal tech related blog for anything private and public cloud - including homelabs! My postings are my own and don’t necessarily represent VMware’s positions, strategies or opinions. Any technical guidance or advice is given without warranty or consideration for your unique issues or circumstances.
Comments
comments powered by Disqus
Advertisement