VMFork, InstantClone, Project Fargo Oh My! Part 1: Walkthrough

One of the things in vSphere 6.0 that I really wanted to look at was the Instant Clone functionality that was included in the release. Instant Clone (AKA Project Fargo AKA VMFork) is the ability to essentially instantly create new virtual machines that are identical copies of a running parent VM by sharing the current memory and virtual disk files of that parent. The “forked” VMs are basically resumed copies of a stunned parent and the disk write/memory changes are committed down to delta VMDKs or delta memory pages while the children continue to read from any unchanged data in the parent VMDKs.

Fargo-poster

Plenty of other people have gone into more detail on this and the architecture, so instead of me re-writing all of this check out this post from Duncan Epping:

http://www.yellow-bricks.com/2014/10/07/project-fargo-aka-vmfork-what-is-it/

Or Google it.

Cool stuff. So I plan on doing a few different posts on this, tons of thoughts how this could be used, this first post though will focus on just simply setting it up.

The first thing to note is that this is not built into the Web Client or even directly into PowerCLI. It is currently just an API interface, so it is not easy to find.

Thankfully, VMware and their awesome Flings came to the rescue and the powers that be created a PowerCLI extension that easily allows you to play with this feature. There are three main posts that really helped me:

William Lam:

http://www.virtuallyghetto.com/2015/08/instant-clone-powercli-cmdlets-best-practices-troubleshooting.html

Brian Graf:

https://blogs.vmware.com/PowerCLI/2015/08/vmware-instant-clone-now-fingertips-new-powercli-extensions-fling.html

https://blogs.vmware.com/PowerCLI/2015/08/using-vmware-instant-clone-via-powercli-extensions-fling.html

If you do not want the gory details, check out this video below of the process:

Configuration/Install

Where do I get the PowerCLI extension fling? Here.

You can also download the PDF for the extensions there and it has some extra good information about Instant Clone. Especially concerning what works (is supported) and what doesn’t.

First let’s take a look at the install process for the fling.

Go ahead and download the file. It is a zip file. Unzip them to a PowerShell module folder like

C:\Program Files\WindowsPowerShell\Modules\

So the files will be in something like:

C:\Program Files\WindowsPowerShell\Modules\VMware.VimAutomation.Extensions

module

The files will be “blocked” when unzipped” so you need to first unblock them. You can either unblock them prior to being zipped (unblock the zip file) or unblock them individually by right-clicking on them going to their properties one by one and hitting “unblock”. Or use Powershell 🙂

$location = C:\Program Files\WindowsPowerShell\Modules\VMware.VimAutomation.Extensions
get-childitem $location -recurse |unblock-file

Now open a PowerCLI window and run:

Import-Module VMware.VimAutomation.Extensions

Now you are ready.

Configuring the Parent VM

I am not sure if all OSes are supported, but from what I can tell (and from my testing) standard Linux distributions and Windows work fine. Make sure it has VM hardware version 11 and has the latest VMware tools installed. Other than that it seems to support whatever you want. But I think in the end, this is geared to VDI environments, which let’s face it…is Windows.

Anyways, let’s walk through the actual process.

So I built a Windows 2012 R2 virtual machine with a mostly default standard config.

parentvm

So the next step is what do you want to make unique on the children VMs? You have DHCP? If not, you probably want to give them a new IP address as they spin up. New domain name? Other stuff?

So what this process allows you to do, besides creating new VMs, is to submit a script upon instantiating the parent VM that all of the children VMs will have and will run upon their creation. This script can do whatever you want. This could be a batch file for Windows or a shell script for Linux. I have not tested using other methods (file types) yet, but I would like to try a direct PowerShell script for Windows.

***UPDATE: so far only a batch file seems to work for Windows, PowerShell (ps1) does not***

Another thing to consider here when it comes to IP connectivity is that when the children VMs spin up, they are given a new MAC address. But since these are simply “resumed” VMs the NIC(s) in the OS do not pick up the new MAC address automatically so you need to add some intelligence into the script to force this change. Otherwise multiple identical MAC addresses will be online and this will cause issues.

The next question is how do you get some of this information into the VM? Well the new child creation process allows you to specify any variable you want to pass to the guest. Since I am doing this via the PowerCLI extensions I will show you how to do it via PowerShell.

The command to create a new child VM is below:

New-InstantCloneVM -ParentVM <parent VM object> -Name <the new child vm name> -ConfigParams $configSettings

DO NOT run this yet, this is setting the scene. Stay tuned.

The config parameter is where you can add the values that you want the guest OS (or specifically the post-clone script) to be able to read and use. This can be anything. IP address, DNS, subnet, VM name, domain to add, whatever. The syntax for the $configSettings is as such:

$configSettings = @{
 ‘ipaddress’ = “10.21.11.101”;
 'vmname' = "childvm1";
 }

This will provide a VM name to the OS and an IP address, this will allow the child VM to use the VM name as its domain name if you want to do that.

Once you have decided what you want to customize in the child, you can create your post-clone script. I am using Windows so it will be a batch file. Well…a batch file that calls a PowerShell file–because…of course.

My batch file simply contains:

powershell -Command "& c:\vmforkprepscript.ps1"

This will kick off my PowerShell script upon creation of the child. It is below:

cd "C:\Program Files\VMware\VMware Tools"
$IP =.\rpctool.exe “info-get guestinfo.fork.ipaddress”
$MAC = .\rpctool.exe “info-get guestinfo.fork.ethernet0.address"
$adapter = get-netadapter NIC0
$adapter | Remove-NetIPAddress -AddressFamily ipv4 -confirm:$false
$adapter | New-NetIPAddress –IPAddress $IP –PrefixLength 21
$adapter | Set-NetAdapter -MacAddress $MAC -confirm:$false

Let’s take this line by line.

The first line just changes into the directory for the tool I need to use to get those parameters. Those parameters that are in the “create child VM” command get stored in the VMX file of the child VM. The rpctool.exe tool can be executed from the guest and can read select information from the VMX file. When the child VM is created, it creates a new VMX file for it and adds those parameters. When the child VM is first powered on (which is really more of a resume) the script runs and the two lines (listed above) use the rpctool command  to retrieve the IP address I entered as well as the MAC address which I didn’t manually enter. The MAC address is generated and entered by ESXi automatically when the child VM is created.

So, if in that parameter variable I make the following lines:

‘ipaddress’ = “10.21.11.101”;
'vmname' = "childvm1";

To get the IP address, the command to retrieve it would be:

.\rpctool.exe “info-get guestinfo.fork.ipaddress”

To get the vmname, it would be:

.\rpctool.exe “info-get guestinfo.fork.vmname”

The next line is the PowerShell command to grab the network interface I want to alter the IP address of, in my case it is called NIC0. The next three lines then respectively:

  1. Remove any old IP addresses.
  2. Assign the new IP address from the variable we retrieved earlier from the VMX file.
  3. Assign the new MAC address from the variable we retrieved earlier from the VMX file.

So this next part is simple but easy to mix up. The post-clone script is to be saved locally on whatever machine you are running PowerCLI on. You do not need to upload it to the VM manually–the PowerCLI process will do this for you. In my case, I have a batch file which is my post clone script which then calls a PowerShell script. That PowerShell script needs to be on the parent VM first. So I will put that on there. The batch file will remain on my local machine since PowerCLI uploads it.

parentvmbefore

The first PowerCLI command you run after you have finished the above is to get the VM object you want to make the parent. This can be done by passing the name of the VM to the get-vm cmdlet:

$vm = get-vm VMForkSource

The next step is the parent VM must be enabled for forking, this process uploads the script and does a few internal config changes in the VM to clean some things up and of course quiesces/stuns the VM.

enable-instantcloneVM -vm $vm -guestUser “administrator” -GuestPassword “password" -PostCloneScript C:\vmforkbat.bat

You must pass the VM object, the credentials to the guest OS and, optionally, the post clone script. What is passed is the path to the script which must be stored locally on the machine running the PowerCLI commands.

The command then returns the VM object after successful completion, that object is needed in the next command to create the children, so the easiest thing to do is to create a variable to hold it in the same command as the enable operation. So instead of the above command, tack a variable to the start of it like so:

$parentvm =enable-instantcloneVM -vm $vm -guestUser “administrator” -GuestPassword “password" -PostCloneScript C:\vmforkbat.bat

If you do not do that, you can always just use the Get-InstantCloneVM command to find it and store it subsequently.

When you enable the parent VM to actually be a parent, not much will happen that is obvious. The VM will still be marked as powered-on, but the preview screen will blank and a lot of the menu options for the VM will disappear.

pclienable postenable

Forking a child

The next step is to create a child. I am just going to create one, and as far as customization goes, I only just need a new IP address to be passed to it. So I will create my $configSettings like so:

$configSettings = @{
‘ipaddress’ = “10.21.11.101”;
}

Then I will create the child, also storing the new child VM object in a new variable. Please note that I am using the $parentvm variable that refers to the newly created parent, not the original $vm variable. While they point to the same VM technically, they are not the same object as far as this cmdlet is concerned. Also supply a VM name. I am calling mine “ChildVM1”

$childvm = New-InstantCloneVM -ParentVM $parentvm -Name ChildVM1 -ConfigParams $configSettings

This will create a new VM in vCenter. Note that children VMs MUST be on the same host as the parent, this will be enforced so make sure you have adequate host resources. The child VM will appear as powered-off.

childvmoff

The VM creation took about two seconds, probably less, but vCenter operations are only so granular.

createchild

If you want to put it on a different datastore add the -datastore parameter, otherwise it defaults to the same as the parent. You can see what gets created on the datastore immediately:

vmfscli

If you want to use the child VM, you must turn it on. In reality, this isn’t actually a traditional power-on. This is really a resume operation, as it is resuming from the paused state of its parent. You can either power it on via the GUI or use PowerCLI.

I opted for the latter.

$childvm | Start-VM

poweron

Now that the child is powered on, the script will run and customize it. When you login to the child, you will see the exact same state the parent was in when you “enabled” it. Look familiar?

samestate

You can also see that the IP has been changed to the one that I specified in the earlier command and it indeed is pingable once the post clone script changes the IP and grabs the new MAC address.

ping

That’s it! The child can now be used as a normal OS.

If we take a look at the directory we see a lot more files have been created by the reboot.

afterboot

There are some restrictions though. You cannot edit the virtual hardware of the child with the exception of adding a new virtual disk. Everything else is not allowed.

If you restart the child from the guest OS, it will remain in the state it was prior to the restart. If you reset the child from the VMware interface (not restart guest, but reset) the child will be re-instantiated from the parent stun point-in-time moment.

The parent is also limited. It can only really be shutdown. If you shut it down, its children can remain, but no more children can be created until all of the existing children are shutdown and the parent restarted and then re-quiesced.

There is sooo much more to talk about concerning this. Just on VMFork there is tons. But when you expand to Project Photon, Project Meteor, Project Enzo… Really exciting times to be a VMware user.

Look for Part II, where I scale this up.

One thought on “VMFork, InstantClone, Project Fargo Oh My! Part 1: Walkthrough”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.