Run 350 Nano Server Virtual Machines on a Lenovo ThinkPad P50 with Hyper-V in Windows 10

If you're a frequent reader of my blog articles on this site, then you're already aware that I recently purchased a Lenovo ThinkPad P50 with a Xeon CPU, 64 GB of RAM, and upgraded it to SSD hard drives.

I tweeted that it wouldn't be complete without a few PowerShell stickers:


I received a response from Jeffrey Snover wanting to know how many Nano server VM's could be run on it:


I took that as a challenge and decided to spin up as many Nano server VM's as possible to find out. I added the DSC package to each VM and the storage package to one of them so it could be used as a SMB based DSC pull server. I also added all of them to my test domain and gave each of them a meaningful computer name.

I ran into a few issues along the way that you wouldn't normally run into on a single machine used for a test environment. The network (a Hyper-V internal virtual switch) for my test environment was designed with a class C subnet (254 IPv4 addresses) which clearly wasn't enough IP addresses. That was easy enough to fix though.

The second problem I ran into is that Hyper-V only has a default of 256 MAC addresses so once I reached that threshold, I was unable to boot any more VM's:

1Get-VM -Name nano* | Start-VM


This was also easily resolved by changing the defaults in Hyper-V manager:


My initial assumption was that I'd run out of disk space before I maxed out the amount of RAM in the machine since each Nano server VM uses an average of 135 MB of RAM when idle:

1Get-VM -Name nano* |
2Where-Object state -eq running |
3Measure-Object -Property MemoryAssigned -Average |
4Select-Object -Property Count, @{label='AverageMemoryRAM(MB)';expression={$_.Average / 1MB -as [int]}}


What I didn't realize is how small the Nano server footprint is on disk. Each Nano server VM uses an average of 540 MB of disk space:

1Get-ChildItem -Path 'D:\Hyper-V\Virtual Hard Disks\nano*.vhd' |
2Measure-Object -Property Length -Average |
3Select-Object -Property Count, @{label='AverageSize(MB)';expression={$_.Average / 1MB -as [int]}}


I was able to max out the RAM by running 350 Nano Server VM's, 3 Windows Server 2012 R2 (server core) VM's, and a Windows 10 client VM (to manage the server VM's with). The Windows Server 2012 R2 VM's run Active Directory, SQL Server, and one is a Web Server. The total number of VM's running on this one physical laptop computer is 354:

1(Get-VM | Where-Object state -eq running).count


Here's a list of the VM's that are running:

1Get-VM | Where-Object state -eq running | Format-Wide -Column 12


How much memory was available with all of those VM's running? 1.5 GB available with 62.4 GB in use:


When I tried to push beyond 350 Nano Server VM's, I started receiving the sad face, but only on new VM's that I tried to spin up. This was probably due to the lack of available resources (specifically memory if I had to guess):


Believe it or not, the base machine and VM's were very responsive even with all of those resources in use. I actually wrote this blog article on the base machine while all of those VM's were running in the background and honestly didn't see any performance problems.

The testing in this blog article was performed using Windows 10 Enterprise Edition (1511) with Hyper-V and the 350 VM's run Windows Server 2016 Technical Preview 4 using the Nano Server installation option.