Using virt-install/KVM and kickstart to create lots of identical VMs quickly

In preparation for an upcoming talk about Oracle 12.2 I am planning on getting my feet wet with the Oracle 12.2 Sharding option. It seems to be a very interesting subject to get into, but like all new subjects, they can be intimidating at first due to their complexity. So why not use the instructions someone has already written down?

Oracle has a nice series of articles about Sharding. I found the Sharding landing page in the Maximum Availability Architecture section on OTN. For the purpose of this blog post I’m intending to follow the “Oracle Sharded Database Deployment with Active Data Guard using CREATE SHARD method for On-Premises – Cookbook”, available from the aforementioned landing page.

About those hardware requirements

Well that’s what I initially had planned. What I hadn’t expected was the number of VMs to be created. On page 7 in the aforementioned PDF, the author explains the pre-requisites. Copying verbally from the document:

You must acquire brand new 7 VMs which do not have any pre-existing Oracle database or listeners running on them.

Well, that’s 7 VMs. Not an awful lot of fun if you have to install all of them manually. Thankfully I don’t have to! In my lab environments I run KVM plus libvirt to make my life easier. There are many useful aspects of this combination, and one of them is named virt-install. The tool allows you to create a VM plus storage, networking etc entirely on the command line. But that would still require the administrator to navigate the anaconda screens, something I’d like to avoid. For quite some time administrators have deployed systems using an automation option. On Red Hat Linux and clones that mechanism is called “Kickstart”. Kickstart – documented in the Red Hat Installation Guide chapter 23 – is an immensely powerful way of deploying systems in a consistent, and always correct (or wrong :) way. In this article I’d like to share how you could run virt-install to install VMs with minimum effort.

Say hello to virt-install

virt-install is beautifully documented making it easy to create VMs. The syntax however takes a little while to understand. I have previously written about virt-install but those posts are now showing their age, and a new example seems in order.

Before presenting the command to create the VM let’s think about the machine’s capabilities first.

  • VM to host a single instance Oracle database and some auxiliary software
  • Should probably have at least two vcpus
  • Eight GB of DRAM should be the minimum
  • I like to separate the root file system from the application data, e.g. I want two volume groups: rootvg and oraclevg

Let’s translate that to virt-install; this works on virt-install 1.4.0 which is the current version on my Oracle Linux 7.3 host.

# virt-install --name shard0 --memory 8192 --memorybacking hugepages=yes \
--vcpus 2 --metadata description=shard0_vm --location /path/to/OL7.3.iso \
--initrd-inject=/tmp/shard0.ks --os-variant=rhel7.3 \
--extra-args="ks=file:/shard0.ks console=tty0 console=ttyS0,115200n8"  \
--disk size=12,pool=capacitypool --disk size=50,pool=latencypool \
--network network=public --nographics

This worked for me: the virt-install command (sourcing the kickstart file) creates and configures a fresh VM with all the required packages for Oracle 12c. I couldn’t reference the 12.2 preinstall RPM because it’s not part of the Oracle Linux 7.3 ISO. That’s ok for me, I can wait for the 7.4 ISO when this might be part of the standard distribution. As a workaround you could install the 12.2 preinstall RPM once the new VM is installed, the RPM can be found in the OL7 “latest” yum channel.

virt-install what?

The virt-install command might require an explanation or two. All of these parameters are explained in the man-page, the ones that stick out a bit are covered here.

This is the name the VM gets. You can manage it using virsh, the libvirt command line interface or it’s GUI cousin, virt-manager
Using this command I instruct the VM to use large pages in the hope that it simplifies the hypervisor’s job of memory management. Obviously this requires large pages to be set up and enough of them available
As explained in the docs you can make an ISO available to virt-install that serves as the installation source. Doing so requires you to run virt-install as root
initrd-inject and extra-args
Using these together in combination with the location flag allows me to stick a kickstart file through to the VM. In the kickstart file I configured partitioning, networking, firewall/selinux settings as well as packages. I can even have a %post section in which I can run arbitrary shell commands. The other parameters are taken from the Red Hat documentation and allow me to install the VM in console mode. Requires the “text” setting in the kickstart file, and the nographics flag
Using the disk directive I request 2 qcow2 virtual disk images to be created. I place the O/S on the capacity pool (backed by hard disk – a lot of capacity but dog slow) and the Oracle related data on a virtual disk backed by the SSDs in the machine.
In a similar way I am instructing the VM to connect to the network I defined beforehand, named public.
If you want to make sure you don’t need X11 at all to install the VM, you can use nographics. You have to provide a “text” directive in your kickstart file and most likely set the console to something sensible, see above for an example

I have said it before and I say it again: libvirt is a fantastic tool, and so easy to use. If you spend a little bit of time preparing your environment, it gets even simpler. Here are a couple of examples:

Before creating VMs on my host I created a couple of storage pools, namely capacity and latency. That’s where I instruct the storage to be used. This way I can simply instruct libvirt to create a volume of x GB in the pool and assign it to the VM. The order matters, the 12 GB disk will become /dev/vda (KVM uses virtio drivers), the second one /dev/vdb. The partitioning scheme is defined in the kickstart file.

Likewise, I can create a network that all my VMs can connect to. On the back-end, libvirt created iptables rules, and a network bridge:

# virsh net-info public
Name:        public
UUID:        some long identifier
Active:      yes
Persistent:  yes
Autostart:   yes
Bridge:      virbr1

VMs that are part of this network – including the host (x.x.x.1) can communicate with each other.

I hope I could get you a little interested in libvirt. Have a look at the documentation, it is very good and explains these topics in more detail.

If you haven’t used virt-install previously this might look uninspiring. However using the commands above I don’t need to set up the installation source via NFS, SMB or HTTP. Neither do I need to provide the kickstart file via a web server, keeping setup requirements very low.

What about the kickstart file? Where do I get one

I had the same question when I first started with the tool. The documentation is quite good, but a working example would be nice. Turns out you have one, it’s created by default in /root/anaconda-ks.cfg and just like an Oracle response file, contains a recording of the options you entered in the GUI. Have a look at it, and adjust to your needs.


1 thought on “Using virt-install/KVM and kickstart to create lots of identical VMs quickly

Comments are closed.