Repeatability and consistency -- These are tenants of cloud native infrastructure and just some of the many benefits that are inherently found within container images which led to the rapid adoption of the technology. Image mode for RHEL extends many of the benefits of running containers and applies them to building, deploying and managing traditional Operating System environments.
In the preceding articles (Creating a VMDK using image mode for RHEL and Integrating an image mode for RHEL produced VMDK into vSphere), we described the process for producing a VMDK file with image mode for RHEL, publishing the resulting file to a VMware vSphere environment, and creating a new Virtual Machine using the VMDK as the primary disk drive for the machine. These steps illustrated just how easy it can be to use image mode for RHEL content within vSphere. However, where this implementation falls short in comparison to running traditional containers are those tenants that were highlighted earlier. There were quite a number of steps that went into achieving the end goal, and introducing one divergence from any of the expected steps could result in an error or failure to ultimately make use of the desired Virtual Machine. Yes, automation could be implemented to streamline the overall process, but there are features in VMware that can support deploying Virtual Machines in a repeatable manner at scale.
Open Virtualization Format (OVF) is an open standard for packaging and distributing Virtual Machines, and an OVF Template in vSphere encapsulates the disks and configurations associated with a Virtual Machine. By making use of an OVF Template, not only can Virtual Machines be deployed with ease in a repeatable fashion, but their content includes several optimizations, such as compression, to reduce the time that it takes to deploy Virtual Machine instances. In this article, we will describe the process for creating and deploying an OVF template within a vSphere environment to support managing image mode for RHEL at scale.
Read more about image mode for RHEL
Creating an OVF Template
In the last article, Integrating a VMDK produced with image mode for RHEL into vSphere, we created a Virtual Machine in a vSphere environment using a VMDK. To create an OVF template, an existing Virtual Machine needs to be available as it represents the content that will be used within the template. You can choose to make use of the existing Virtual Machine deployed previously or choose to deploy another Virtual Machine for the purpose of acting as the content for the OVF template. For the purposes of this article, we will make use of the existing Virtual Machine.
Before we begin, ensure that you have the following prerequisites completed. The installation and configuration of these tools were described previously. Refer to the existing articles as needed:
- Creating a VMDK using image mode for RHEL
- Integrating a VMDK produced with image mode for RHEL into vSphere
Prerequisites
- Access to a vSphere environment
- A Virtual Machine deployed within the vSphere environment with an image mode for RHEL based VMDK disk
- govc CLI that has been authenticated to the vSphere environment
- jq CLI
- tee
Recall that we established a directory structure containing our content
Recall from the prior articles that all activities were performed within a directory called rhel-bootc-vmdk. Navigate to this directory, as it can be the start point to enable the creation and management of an OVF template from the existing Virtual Machine.
The govc export.ovf subcommand can be used to facilitate the creation of an OVF template from an existing Virtual Machine. Before the template can be created, power off the Virtual machine if it is running.
govc vm.power \
-dc="${DATACENTER}" \
-off=true \
${VM_NAME}
With the Virtual Machine powered off, create an OVF by exporting the Virtual Machine in a directory called ovf using the following command:
govc export.ovf \
-dc=${DATACENTER} \
-vm=${VM_NAME} \
-name=rhel-bootc \
-sha=1 \
ovf
Once the export is complete, the contents will be located within a directory called rhel-bootc and enclosed with the ovf directory. Three following directory structures will be present:
ovf/
└── rhel-bootc
├── rhel-bootc-disk-0.vmdk
├── rhel-bootc.mf
└── rhel-bootc.ovf
The .ovf file contains the descriptor for the OVF template, while the .mf file contains a SHA1 hash of all of the files related within the OVF template.
Creating a Virtual Machine from an OVF Template
With the OVF template created, new Virtual Machines can be created in a repeatable manner. The govc import.ovf command can be used to deploy OVF templates from content on the local file system. Another benefit of OVF templates is the ability to easily customize Virtual Machines from a known baseline at deploy time through the use of an options file. This JSON formatted file includes everything that one would want to configure as it relates to the Virtual Machine definition and simplifies how to deploy Virtual Machines in an automated way.
While an options file can be created from scratch, the starting point can be created from an existing OVF template file by using the govc import.spec command. Create an options file called options.json in the ovf directory from the previously created OVF template by using the following command.
govc import.spec ovf/rhel-bootc/rhel-bootc.ovf > ovf/options.json
The options file can be customized, such as modifying the type of disk provisioning to be thin, by using the jq and tee CLI’s
cat ovf/options.json | jq -r '.DiskProvisioning="thin"' | tee ovf/options.json
Notice in the output and in the options.json file that the DiskProvisioning="thin" property has been populated.
Create a new Virtual Machine called rhel-bootc-ovf by deploying the OVF Template along with the options file using the following command:
govc import.ovf \
-dc=${DATACENTER} \
-ds=${DATASTORE} \
--pool=${DATACENTER_POOL} \
-options ovf/options.json \
-name rhel-bootc-ovf \
ovf/rhel-bootc/rhel-bootc.ovf
Once complete, a new Virtual Machine called rhel-bootc-ovf will be created. Virtual Machines created from OVF templates are not started automatically by default. However, this behavior can be changed by specifying the PowerOn property within an options file (You may have noticed earlier that the PowerOn property currently defined within the options.json is set as false. Changing this value to true will automatically start the Virtual Machine
However, if you recall from the prior article, cloud-init is used to inject configuration at an Operating System level at runtime. While it would have been ideal to define these properties within the options file, these values are used in the context of a Virtual Machine ExtraConfig, and these properties are not defined within an options file. As a result, applying the configurations must be made after a Virtual Machine has been deployed. Let’s demonstrate how to use cloud-init in combination with an OVF template.
Prepare the cloud-init Metadata and User Data files by creating a metadata-ovf.yaml and user-data-ovf.yaml file within a directory called cloud-init with the following content (This directory should have been created from the previous article. However, if this directory does not currently exist, create one underneath the base rhel-bootc-vmdk directory for which all commands have been executed.
cloud-init/metadata-ovf.yaml:
instance-id: rhel-bootc-ovf
local-hostname: rhel-bootc-ovf
cloud-init/user-data-ovf.yaml:
#cloud-config
users:
- default
- name: cloud-user
sudo: ALL=(ALL) NOPASSWD:ALL
groups: sudo, wheel
lock_passwd: true
ssh_authorized_keys:
- ${SSH_PUB_KEY}
The contents of the User Data file here is identical to the User Data file created in the previous article. Only the contents of the Metadata file differs with regards to the name of the machine. Update the value of the ${SSH_PUB_KEY} with an SSH public key that can be used to connect to the instance remotely once it is running.
Modify the configuration of the rhel-bootc-ovf VirtualMachine to include the cloud-init configuration.
govc vm.change \
-dc="${DATACENTER}" \
-vm="rhel-bootc-ovf" \
-e guestinfo.metadata="$(gzip -c9 <cloud-init/metadata-ovf.yaml | { base64 -w0 2>/dev/null || base64; })" \
-e guestinfo.metadata.encoding="gzip+base64" \
-e guestinfo.userdata="$(gzip -c9 <cloud-init/user-data-ovf.yaml | { base64 -w0 2>/dev/null || base64; })" \
-e guestinfo.userdata.encoding="gzip+base64"
Power on the Virtual Machine and wait for the IP address to be allocated.
govc vm.power -on -dc=${DATACENTER} rhel-bootc-ovf
govc vm.ip -v4 -dc=${DATACENTER} -wait=10m rhel-bootc-ovf
Once an IP address has been returned, attempt to connect to the machine using SSH using the SSH private key associated with the SSH public key that was added to the cloud-init User Data.
ssh cloud-user@<ip_address>
If the connection to the rhel-bootc-ovf Virtual Machine was successful, the deployment of the OVF template and injecting template options and cloud-init configurations were a success.
Deploying OVF Templates from a vSphere Content Library
OVF templates greatly simplify what it takes to deploy Virtual Machines in a repeatable manner. One area that you might have noticed when deploying the OVF template in the prior section was the time that it took to complete the deployment. The majority of the time that it took to deploy the template was uploading the VMDK file to vSphere. Factoring in both the time that it takes to download the VMDK file from the source Virtual Machine when creating the OVF template and uploading the VMDK file when deploying the OVF template along with the connection speed between the local machine and the vSphere environment, the overall time that it takes to facilitate the management of Virtual Machines using OVF templates can be quite lengthy.
Another option that provides a number of advantages compared to deploying OVF templates directly from a source on a local machine is to deploy OVF templates from content stored within the vSphere environment. By using this approach, the overall time that it takes to deploy OVF templates is greatly reduced.
A Content Library is a feature that was introduced in VMware vSphere 6.7 Update 1 and enables the sharing and reuse of assets, including templates, and provides an ideal solution to the challenges discussed previously. An existing Content Library or a new Content Library can be created to facilitate the management of OVF templates associated with image mode for RHEL assets.
Create a new Content Library within the vSphere environment called rhel-bootc-library that will contain assets related to image mode for RHEL:
govc library.create \
-dc="${DATACENTER}" \
-ds="${DATASTORE}" \
rhel-bootc-library
Upload the OVF template from the local machine to the Content Library
govc library.import \
rhel-bootc-library \
ovf/rhel-bootc/rhel-bootc.ovf
Content stored within the Content Library can be listed by using the govc library.ls command. Running this command will confirm the OVF template imported previously is available for use.
govc library.ls \
rhel-bootc-library \
rhel-bootc-library/*/
/rhel-bootc-library
/rhel-bootc-library/rhel-bootc/rhel-bootc.ovf
/rhel-bootc-library/rhel-bootc/rhel-bootc-disk-0.vmdk
With the OVF Template available within the Content Library, deploy the OVF Template using the govc library.deploy command. The process for deploying the template from the Content Library mirrors many of the same steps that are used when deploying from a local source. To use an options file when deploying an OVF template, the content should be generated from the OVF template so that it contains values associated with the template. While we already have a usable options file for the rhel-bootc OVF template, if there is a need to regenerate the options file again or use another template within the Content Library, the OVF template must be downloaded from the Content Library. Fortunately, only the .ovf specification file needs to be retrieved instead of all of the content related to the template, such as the VMDK file.
If there was a need to download the OVF file again, the following command could be used:
govc library.export \
rhel-bootc-library/rhel-bootc/rhel-bootc.ovf \
${DESTINATION}
The govc import.spec command could then be used to generate the options file.Since an options file is already available on the local machine, there is no need to generate a new one.
Before deploying the OVF template from the Content Library, let’s remove the existing Virtual Machine created previously when deploying the OVF Template from the local machine.
govc vm.destroy \
-dc=${DATACENTER} \
rhel-bootc-ovf
Now, create a Virtual Machine called rhel-bootc-ovf by deploying the rhel-bootc OVF template from the Content Library referencing the options file, the location of the OVF template within the Content Library (name of the Content Library and path within the library), and the name of the Virtual Machine to create:
govc library.deploy \
-dc=${DATACENTER} \
-ds=${DATASTORE} \
--pool=${DATACENTER_POOL} \
-options ovf/options.json \
/rhel-bootc-library/rhel-bootc \
rhel-bootc-ovf
Since the template and its associated resources were all stored within the Content Library, the deployment will most likely have been faster than deploying from the local machine previously. And since the content is centrally located, there is additional assurance that the content does not differ regardless of who is executing the deployment process.
The remainder of the steps for preparing the Virtual Machine for use continues to be the same. The Virtual Machine is injected with cloud-init configurations to enable Operating System level configurations and then the machine can be powered on.
govc vm.change \
-dc="${DATACENTER}" \
-vm="rhel-bootc-ovf" \
-e guestinfo.metadata="$(gzip -c9 <cloud-init/metadata-ovf.yaml | { base64 -w0 2>/dev/null || base64; })" \
-e guestinfo.metadata.encoding="gzip+base64" \
-e guestinfo.userdata="$(gzip -c9 <cloud-init/user-data-ovf.yaml | { base64 -w0 2>/dev/null || base64; })" \
-e guestinfo.userdata.encoding="gzip+base64"
govc vm.power -on -dc=${DATACENTER} rhel-bootc-ovf
Obtain an IP address for the machine and then connect via SSH to confirm the configurations were successful.
govc vm.ip -v4 -dc=${DATACENTER} -wait=10m rhel-bootc-ovf
ssh cloud-user@<ip_address>
The use of OVF Templates greatly simplifies the process for deploying instances created with image mode for RHEL within a vSphere environment. By being able to leverage additional supporting components, like Content Libraries, managing content, and deploying Virtual Machines that originated from a VMDK disk created with image mode for RHEL is simplified. Each of these elements, working together, enables deploying a fleet of instances repeatedly, consistently, and most importantly, easily.
Last updated: July 24, 2024