Change can be hard. This is especially true when applying a new set of technologies or approaches. Fortunately, image mode for RHEL takes many of the benefits that are found in container technologies, including a simplified build process and portability across a variety of environments, and applies them to traditional Virtual Machine workflows. In the prior post, Creating a VMDK using image mode for RHEL, a VMDK-formatted disk image was produced as an output from a bootc image.
While the VMDK format is open source, they are traditionally used within the VMware family of solutions, such as VMware Workstation and VMware vSphere. In this post, we will describe how the previously created VMDK disk can be used as the basis for a virtual machine hosted in a VMware vSphere environment.
Read more about image mode for RHEL
Managing VMware vSphere with govc
vSphere provides several options for which to integrate with the platform, including a REST API and web based used interface. govc is a cli-based tool that is built on top of the vSphere API that not only simplifies the interactions with the platform but enables automation activities and will be used throughout the remainder of this series.
First, install govc on your local machine. Several installation options are available, including a container-based runtime or using one of the project's release artifacts.
The command below will download govc from the GitHub project and install it to a known location on the local machine PATH. Elevated rights are needed to successfully execute the command, so adjust as necessary depending on your environment.
curl -L -o - "https://github.com/vmware/govmomi/releases/latest/download/govc_$(uname -s)_$(uname -m).tar.gz" | tar -C /usr/local/bin -xvzf - govc
Confirm govc has been installed correctly by executing a simple command to check the version of the utility:
govc version
There are several different ways that details for how to connect to the remote vSphere can be provided to govc. The most straightforward is to set a series of environment variables. The most common variables that you will need are found below:
- GOVC_URL - URL to the vSphere environment
- GOVC_USERNAME - vSphere username
- GOVC_PASSWORD - vSphere password
- GOVC_TLS_CA_CERTS - List of certificates that can be used to communicate with vSphere that are not included within the Operating System truststore. Multiple certificate files can be provided, separated with a : character.
- GOVC_INSECURE - Disable certificate certificate verification
The full list of environment variables can be found within the Usage section of the project page.
Once these values have been set, confirm that you are able to communicate with the remote vSphere environment by listing items in the vSphere inventory using the tree subcommand:
govc tree
If the invocation returned successfully, your govc client has been properly configured.
Uploading the VMDK to vSphere
Now that activities can be performed against the vSphere environment using govc, the next step is to take the previously generated VMDK file produced by the bootc-image-builder utility and upload it to a location within vSphere. The specific location of where the VMDK should be stored depends largely on the target environment including any existing conventions on where content should be stored.
To upload a VMDK with govc, you will need the following properties:
- Datacenter
- Datastore
- Resource Pool (optional)
- Directory to store the VMDK
In the prior article, all activities were performed within a directory called rhel-bootc-vmdk and within this directory, the VMDK was produced in a file called disk.vmdk within the output/vmdk directory. Navigate to the rhel-bootc-vmdk directory so that all activities can be performed from this location.
First, rename the disk.vmdk file to rhel-bootc-vmdk.vmdk so that once it is uploaded to vSphere, it will have a more descriptive name to differentiate it from other content.
mv output/vmdk/disk.vmdk output/vmdk/rhel-bootc-vmdk.vmdk
Upload the rhel-bootc-vmdk.vmdk file to a desired directory in vSphere.
govc import.vmdk \
-dc="${DATACENTER}" \
-ds="${DATASTORE}" \
-pool="${DATACENTER_POOL}" \
output/vmdk/rhel-bootc-vmdk.vmdk \
${DESTINATION_FOLDER}
Confirm the file has been uploaded by listing files within the datastore directory
govc datastore.ls \
-dc="${DATACENTER}" \
-ds="${DATASTORE}" \
${DESTINATION_FOLDER}
rhel-bootc-vmdk-flat.vmdk
rhel-bootc-vmdk.vmdk
You will notice that there is a -flat.vmdk file that is present within the destination directory. This is expected as this file contains the actual content of the disk.
Creating a New Virtual Machine With the VMDK
With the VMDK uploaded to vSphere, the next step is to create a new Virtual Machine that the VMDK disk can then be attached to. The specific resources associated with the VM, like CPU count and memory, will vary depending upon the environment and use case. For the purposes of this implementation, a virtual machine with 2 CPU’s and 4 GB of RAM should suffice.
Create a new Virtual Machine called rhel-bootc-vmdk. In addition to the previously mentioned parameters, the following will also be needed:
- Network
- Firmware (either bios or efi)
Now, create the virtual machine
govc vm.create \
-dc="${DATACENTER}" \
-ds="${DATASTORE}" \
-pool="${DATACENTER_POOL}" \
-net="${NETWORK}" \
-disk.controller=pvscsi \
-on=false \
-c=2 \
-m=2048 \
-g="rhel9_64Guest" \
-firmware="${FIRMWARE}" \
rhel-bootc-vmdk
Additional options are also available if needed, so be sure to adjust accordingly. By specifying the -on=false option, the Virtual Machine will be created but not powered on.
Next, attach the VMDK to the newly created Virtual Machine:
govc vm.disk.attach \
-dc="${DATACENTER}" \
-ds="${DATASTORE}" \
-vm="rhel-bootc-vmdk" \
-link=false \
-disk="${DESTINATION_FOLDER}/rhel-bootc-vmdk.vmdk"
Finally, power on the Virtual Machine:
govc vm.power \
-dc="${DATACENTER}" \
-on=true \
rhel-bootc-vmdk
Confirm the state of the Virtual Machine is powered on by executing the following command:
govc vm.info -r -dc="${DATACENTER}" rhel-bootc-vmdk | grep "Power state" | awk '{ print $3 }'
If the preceding command is “poweredOn”, the machine has started successfully.
Integrating cloud-init
At this point, a vSphere Virtual Machine is running using the VMDK disk. However, what you might have noticed is that at no time up to this point have any considerations been made into how to remotely connect to the instance. While there are several options available for which users and their authentication details can be specified, including within the Containerfile during the bootc image build, one approach that is popular in VMware vSphere environments (and other cloud environments) is to make use of cloud-init to dynamically configure machines at runtime. The bootc image that was created previously included the cloud-init RPM package as part of the build process so that the capabilities of the component could be leveraged.
Note: There is no requirement within image mode for RHEL that users or remote access be configured. If there is no desire to implement either of these capabilities, the steps described in this section can be omitted.
cloud-init provides the capability to configure various aspects of a Virtual Machine, such as specifying host details, installing packages, and executing scripts. One type of host configuration that can be achieved using cloud-init is the creation of users. Multiple methods are available to specify how users can authenticate to instances, including interactive username/password and SSH. SSH-based authentication will be used in this instance as it provides several advantages over traditional username and passwords, and is ideal when automating at scale.
Configurations are provided through the use of Datasources and contain details related to actions that would be typically performed by the end user (userdata) and properties of the instances themselves (metadata). Both will be created and associated with our Virtual Machine instance.
The first step is to either create a new SSH public/private keypair or have one available for use. Click here for instructions on how to create a SSH public/private keypair.
Create a new directory within the rhel-bootc-vmdk directory called cloud-init which will be used to store cloud-init configuration files.
mkdir cloud-init
Create the cloud-init Metadata configuration in a file located at cloud-init/metadata.yaml that will contain the hostname of the instance:
instance-id: rhel-bootc-vmdk
local-hostname: rhel-bootc-vmdk
Next, create the cloud-init User Data configuration in a file located at cloud-init/user-data.yaml that will contain properties of the user that will be used to access the remote Virtual Machine.
#cloud-config
users:
- default
- name: cloud-user
sudo: ALL=(ALL) NOPASSWD:ALL
groups: sudo, wheel
lock_passwd: true
ssh_authorized_keys:
- ${SSH_PUB_KEY}
In the definition above, a new user named cloud-user is to be created with permissions to escalate to the root account without a password. By specifying the lock_password option as true, password-based authentication will be disabled, and access to the account will be facilitated with SSH-based authentication. Replace ${SSH_PUB_KEY} with the contents of the SSH public key associated with the SSH private key that will be used to access the Virtual Machine.
cloud-init configurations are applied using ExtraConfig Virtual Machine advanced settings as base64 encoded values. The gzip utility will also be used to provide compression support for the content. The resulting compressed string will then be base64 encoded.
Four properties need to be added to the Virtual Machine using the govc vm.change command:
- guestinfo.metadata - base64 encoded contents of the metadata.yaml file
- guestinfo.metadata.encoding - Encoding type for the content of the guestinfo.metadata property.
- guestinfo.userdata - base64 encoded contents of the user-data.yaml file
- guestinfo.userdata.encoding - Encoding type for the content of the guestinfo.userdata property.
Apply the cloud-init resources by updating the configuration of the Virtual Machine by applying the properties listed above:
govc vm.change \
-dc="${DATACENTER}" \
-vm="rhel-bootc-vmdk" \
-e guestinfo.metadata="$(gzip -c9 <cloud-init/metadata.yaml | { base64 -w0 2>/dev/null || base64; })" \
-e guestinfo.metadata.encoding="gzip+base64" \
-e guestinfo.userdata="$(gzip -c9 <cloud-init/user-data.yaml | { base64 -w0 2>/dev/null || base64; })" \
-e guestinfo.userdata.encoding="gzip+base64"
Restart the Virtual Machine to apply the cloud-init configurations:
govc vm.power \
-dc="${DATACENTER}" \
-reset=true \
rhel-bootc-vmdk
Once the Virtual Machine has restarted, we will be able to attempt remote access.
Connecting to the Virtual Machine
With the cloud-init configurations applied to the Virtual Machine, the final step is to confirm that the instance can be accessed via SSH. Obtain the IPv4 address of the Virtual Machine using the command below:
govc vm.ip -v4 -dc=${DATACENTER} -wait=10m rhel-bootc-vmdk
Note: the command will block for a maximum of 10 minutes or until an IP address has been assigned.
Connect to the Virtual Machine by specifying the location of the SSH private key, the IP address returned by the previous command as the user cloud-user:
ssh -i ${SSH_PRIVATE_KEY_LOCATION} cloud-user@${IP_ADDRESS}
If a prompt within the Virtual Machine appears, you have successfully incorporated cloud-init to remotely access the instance. Feel free to browse around the system, including verifying the version of Red Hat Enterprise Linux by viewing the contents of /etc/redhat-release.
cat /etc/redhat-release
The version returned should be aligned with the version of the bootc base image.
In this article, you explored how to take an VMDK produced with image mode for RHEL, and use it in a Virtual Machine within a VMware vSphere environment. For those who are familiar with running Virtual Machines in VMware, the processes and workflows should have been familiar. By reusing common paradigms for VMware Virtual Machine management, users are able to become productive quickly while also leveraging the key benefits of Image Mode for RHEL. In the next article, we will discuss how to scale the deployment of Virtual Machines in vSphere by creating and using OVF templates.
Last updated: July 24, 2024