
VirtualBox and Friends on Windows 8.1
VirtualBox, Vagrant, Test Kitchen, Docker Machine, Minikube
Introduction
Across macOS, Windows, and Linux, you’ll find these two popular tools of awesomeness: Vagrant and VirtualBox.

Vagrant allows you to automate creation and provisioning of disposable systems and infrastructure with ease, using a variety of backend virtualization solutions, with the free open source VirtualBox.
You can provision a system using CFEngine, CAPS (Chef, Ansible, Puppet, Salt Stack), Docker, shell scripts, etc. Vagrant supports them all, and more through rich a plug-in community.

As you develop change configuration scripts, you may want to validate the results using test automation scripts. There’s a tool just for this, that can orchestrate Vagrant and run tests: Test Kitchen.

If you use some immutable production patterns, where instead of configuring systems, you run pre-configured disposable Linux containers with Docker, using a tool called Docker Machine. This tool will create a sandboxed Docker environment using a small Linux guest system created on VirtualBox.

For orchestrating Docker containers, Kubernetes is now the most popular platform for this. You can run a Kubernetes cluster using Minikube, which in the background using Docker Machine.
This is a tutorial that demonstrates how to install and use on a Windows 8.1 host. The instructions will run in PowerShell console running as Administrator mode.
Required Prerequisite
Microsoft Windows does not have a package management system for installing FOSS (free and open-source software).

We can work around this limitation by installing Chocolatey. This will require administrative access to your computer, and you need run PowerShell with Run an Administrator option. If you have PowerShell pinned to your task bar, you can right click and access the option:

When you bring PowerShell with Run as Administrator mode, type this to get Chocolatey:
# Set privilege for running scripts
Set-ExecutionPolicy Bypass -Scope Process -Force# variables for readibility
$scripturl = 'https://chocolatey.org/install.ps1'
$wc = New-Object System.Net.WebClient# Install Chocolately
Invoke-Expression ($wc.DownloadString($scripturl))
When installing Chocolatey packages, you will need to update the environment to get access to the newly installed packages. Instead of closing and re-opening PowerShell windows, here’s a convenience function for updating the environment:
Function Update-Environment
{
$m = [System.Environment]::GetEnvironmentVariable("Path","Machine")
$u = [System.Environment]::GetEnvironmentVariable("Path","User") $env:Path = $m + ";" + $u
}
If you open up a new PowerShell window for any reason, make sure to use this function again to easily update the environment after installing a Chocolatey package.
Virtualbox

The central cross platform tool (Linux, Windows, macOS) to make all of this magic work is VirtualBox.
Installing VirtualBox
With Chocolatey, you can install VirtualBox by running this
choco install -y virtualbox
Update-Environment
Afterward, we can check to see if it is installed:
# Test Version
vboxmanage --version
5.2.16r123759
Vagrant

Vagrant automates virtual machines and containers. It is essentially an orchestrator to juggle running different systems and quickly provision them with your favorite change configuration solution, like shell, CFEngine or CAPS (Chef, Ansible, Puppet, Salt Stack).
With Vagrant, we can easily download and run system images from Vagrant Cloud or other sources, or even run images you created locally with a tool like Packer).
Installing Vagrant
We can install Vagrant easily with:
choco install -y vagrant
Using Vagrant: Manjaro Linux on Windows
In this demo, let’s run a popular Linux distro called Manjaro. The box will be downloaded from the Vagrant Cloud.
mkdir $home/mymanjaro
cd $home/mymanjarovagrant init mloskot/manjaro-i3-17.0-minimal
vagrant up
Now let’s do something a little more colorful, and download and install screenFetch on our virtual guest:
$url = 'https://github.com/KittyKatt/screenFetch/archive/master.zip'
vagrant ssh --command "curl -OL $url"
vagrant ssh --command 'sudo pacman -S unzip'
vagrant ssh --command 'unzip master.zip'
vagrant ssh --command './screenFetch-master/screenfetch-dev'
This will display something like following:

Using Vagrant: Windows on Windows
We can run through this same process with another image built by Matt Wrock’s Windows Packer scripts:
# add recently build vagrant box to Vagrant (path varies)
$winboxpath = 'path\to\windows2016min-virtualbox.box'
vagratbox add $winboxpath --name 'my/win2016'# create staging area
mkdir $home\mywindows
cd $home\mywindows# create local copy and start instance
vagrant init my/win2016
vagrant up
From here, we need to be able to log into an interactive bash shell to run screenFetch. We can get a bash shell by installing MSYS2. And we can install MSYS2, which we can install using Chocolatey package management system on our guest system.
On a Windows host, we can remote into the system through winrm
mechanism (make sure to do this from PowerShell console in Run As Administrator mode):
vagrant powershell
Afterward, we can run a few commands to investigate our guest environment:
cmd /c verMicrosoft Windows [Version 10.0.14393]$PSVersionTable.PSVersionMajor Minor Build Revision
----- ----- ----- --------
5 1 14393 0
In the same remote PowerShell session on the guest, type these commands:
Function Update-Environment
{
$m = [System.Environment]::GetEnvironmentVariable("Path","Machine")
$u = [System.Environment]::GetEnvironmentVariable("Path","User") $env:Path = $m + ";" + $u
}Set-ExecutionPolicy Bypass -Scope Process -Force$scripturl = 'https://chocolatey.org/install.ps1'
$wc = New-Object System.Net.WebClient
Invoke-Expression ($wc.DownloadString($scripturl))
Update-Environmentchoco install -y bitvise-ssh-server
Start-Service BvSshServerchoco install -y msys2
Now that SSH server is running, we can log into through SSH and get a command shell prompt, and start up a bash session:
vagrant ssh # user/password = vagrant# start bash session
c:\tools\msys64\usr\bin\bash.exe
From bash shell, we can now install and run screenFetch:
# install unzip package
PATH=/usr/bin:$PATH
pacman -S unzip# install screenfetch
URL=https://github.com/KittyKatt/screenFetch/archive/master.zip
curl -OL $URL
unzip master.zip# run screenfetch
./screenFetch-master/screenfetch-dev
This will give us:

Test Kitchen

Test Kitchen is a test harness, and similar to Vagrant, in that it orchestrates several systems, provisions them, and then facilitates running tests on them. Test Kitchen in fact uses Vagrant as the backend driver to create the virtual guest systems, but can be configured to use Docker or other backends.
Installing Test Kitchen
For demonstration purposes, and easy scaffolding, we’ll install Test Kitchen using ChefDK set of tools:
choco install -y chefdk
Using Test Kitchen with ChefDK
For this small demo, we can use the Chef to auto-generate a cookbook, which includes a default Test Kitchen configuration:

To get started, we generate a cookbook, and bring up the environment.
cd $home
# Generate example
chef generate cookbook helloworld
cd helloworld# Create Ubuntu and CentOS systems
kitchen create
This will create Ubuntu and CentOS systems using Vagrant as the backend driver. We can then view the running systems with kitchen list
:

Run Something on Test Systems
Let’s download a screenFetch shell script locally:
$path = "$home\.kitchen\cache"# Download Archive
$url = 'https://github.com/KittyKatt/screenFetch/archive/master.zip'
$wc = New-Object System.Net.WebClient
[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"
$wc.DownloadFile($url, "$path\master.zip")# Unzip Archive
Add-Type -AssemblyName System.IO.Compression.FileSystem
function Unzip
{
param([string]$zip, [string]$out)
[System.IO.Compression.ZipFile]::ExtractToDirectory($zip, $out)
}Unzip "$path\master.zip" "$path\"
The $home\.kitchen\cache
is a global shared directory for all Vagrant guest systems managed by Test Kitchen. We can exchange files between the host and virtual guest systems using this mechanism.
With screenFetch script available from the shared directory, let’s use it across all systems.
# Install pciutils on CentOS (required by screenfetch)
kitchen exec centos --command='sudo yum -y install pciutils'
# Install a snap on Ubuntu (avoids warnings w/ screenfetch)
kitchen exec ubuntu --command='sudo snap install hello-world'# Run screenfetch script on all systems
kitchen exec default* `
--command='sudo /tmp/omnibus/cache/screenFetch-master/screenfetch-dev'
This will print something pretty for all clients:

Docker Machine

Docker Machine is an automation tool that can spin up a virtual system for facilitating Docker. Specifically on Windows, you have to run Docker on a virtual guest, as Linux containers automated by Docker only run on Linux. Docker Machine automates this process.
Install Docker Toolbox

We can get a recent version of Docker Machine from Docker Toolboxpackage. This will also install the Docker client as well.
choco install -y docker-toolbox
Update-Environment
Using Docker
With these tools installed, let’s run some containers, using Docker client on the host after starting a Docker daemon running on a virtual system:
# Create a docker machine environment called default
docker-machine create --driver virtualbox 'default'# Tell docker engine to use machine's docker (defaulting to default)
& docker-machine env default | Invoke-Expression# Run a container fetched from docker hub
docker run docker/whalesay cowsay Hello World
_____________
< Hello World >
-------------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
Minikube

Minikube allows you to run Kubernetes cluster locally. It leverages off of Docker Machine to create a single-node Kubernetes cluster.
Installing Minikube and Kubectle Client
Install Minikube and kubectl
using Chocolatey:
choco install -y minikube
Update-Environment
Using MiniKube
We can now start up our cluster and deploy some containers on our cluster. When we start up Minikube, it will make the necessary client configurations needed for kubectl
.
# Start minikube environment
minikube start --vm-driver=virtualbox# Deploy Something
kubectl run hello-minikube `
--image=k8s.gcr.io/echoserver:1.4 `
--port=8080
kubectl expose deployment hello-minikube `
--type=NodePort
We check to see if the pod(s) are running.
kubectl get pod
NAME READY STATUS RESTARTS AGE
hello-minikube-6c47c66d8-k4vlc 1/1 Running 0 11m
Once the pods are ready, we can connect to the running service’s endpoint:
$url = & minikube service hello-minikube --url
(New-Object System.Net.WebClient).DownloadString($url)
CLIENT VALUES:
client_address=172.17.0.1
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://192.168.99.101:8080/SERVER VALUES:
server_version=nginx: 1.10.0 - lua: 10001HEADERS RECEIVED:
connection=Keep-Alive
host=192.168.99.101:31559
BODY:
-no body in request-
Conclusion
Tools Installed
In total, we have installed 7 tools (1 virtual management platform, 4 x orchestration systems, and 2 client tools):
"`nVirtualBox $(vboxmanage --version)`n" + `
"$(vagrant --version)`n" + `
"$(kitchen --version)`n" + `
"$(docker-machine --version)`n" + `
"$(docker --version)`n" + `
"$(minikube version)`n" + `
"Kubectl Client: " + `
"$(kubectl version | Select-string "Client")".Split('"')[5] + `
"`n"VirtualBox 5.2.16r123759
Vagrant 2.1.2
Test Kitchen version 1.22.0
docker-machine.exe version 0.14.0, build 89b8332
Docker version 18.03.0-ce, build 0520e24302
minikube version: v0.28.2
Kubectl Client: v1.11.1
We installed these piece by piece, but if you wanted to install these all in one command, you could create a Package.config
manifest and install them all at once with choco install -y choco.config
.

From Powershell, you can create and run using this:
@'
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="virtualbox" />
<package id="vagrant" />
<package id="chefdk" />
<package id="docker-toolbox" />
<package id="kubernetes-cli" />
<package id="minikube" />
</packages>
'@ | Out-File -Encoding "UTF8" $home/choco.configchoco install -y $home/choco.config
Virtual Guest Systems Created
With these 4 orchestration tools, we have created 6 virtual guests on VirtualBox:
vboxmanage list runningvms | ForEach-Object {$_.Split('"')[1]}
default
minikube
default-ubuntu-1604_default_1533101176498_15519
default-centos-7_default_1533101311605_33025
mywindows_default_1533247865771_48942
mymanjaro_default_1533248064205_34202
And with the graphical Virtualbox Manager console, we can see the same thing:

Cleaning Up
Now that we are finish, we can stop the running virtual machines hosting our development and test solutions, and optionally remove them completely.
######## vagrant w/ manjaro cleanup ########
cd $home\mymanjaro
vagrant halt # stop running vm guest
vagrant destroy # delete vm guest entirely######## vagrant w/ win2016 cleanup ########
cd $home\mywindows
vagrant halt # stop running vm guest
vagrant destroy # delete vm guest entirely######## testkitchen cleanup ########
cd $home\helloworld
kitchen destroy # destroys all test systems######## dockermachine cleanup ########
docker-machine stop # stop vm hosting docker
docker-machine rm default # remove vm entirely######## minkube cleanup ########
minikube stop # stop kubernetes cluster
minikube rm # remove vm hosting cluster and kubectl config entries
After stopping the virtual guests, vboxmanage list runningvms
will show an empty list. If we removed them as well, then vboxmanage list vms
will also show an empty list.
Final Thoughts
The main goal of this is to show you what is possible and create some interest and passion around these set of tools. I wanted to show that the same tools that work well on a Linux host or macOS host can also work on a Windows host as well.
Using these cross platform tools, we can easily facilitate experimentation and learning activities, and drive DevOps patterns from local development and test into a continuous integration and continuous delivery pipeline.
Resources
Here are some links for these tools.
Virtualbox
- Main Site: https://www.virtualbox.org/
Vagrant
Vagrant supports has many backend provider solutions besides Virtualboxand has built in provisioner support for popular change configuration solutions.
- Main Site: https://www.vagrantup.com/
- Vagrant Providers: Docker, Hyper-V, VMWare, libvirt (KVM), AWS,Google Cloud, Azure, vSphere, LXC
- Vagrant Provisioners: Shell, Ansible, Ansible Local, CFEngine, Chef Solo, Chef Zero, Chef Client, Docker, Puppet Apply, Puppet Agent, Salt Stack, Docker-Compose
- Popular Vagrant Plugins: Cachier, HostManager, DNSMasq, Triggers, Notify
Test Kitchen
Test Kitchen test harness has rich community support for a variety of backend driver support, provisioner support, and verifier support:
- Main Site: https://kitchen.ci/
- Kitchen Test Drivers: Shell, Kitchen-Docker (docker w/ ssh), Kitchen-Dokken (docker w/ docker exec), Kitchen-Kubernetes, Kitchen-Google, Kitchen-EC2, Kitchen-vSphere, Kitchen-AzureRM, Kitchen-Hyper-V
- Kitchen Test Provisioners: Kitchen-CFEngine, Kitchen-Ansible, Kitchen-Puppet, Kitchen-Salt (Salt Stack), Kitchen-DSC (PowerShell DSC)
- Kitchen Test Verifiers: Busser-ServerSpec, Busser-BATS, Busser-Cucumber, Busser-RSpec, Busser-Minitest, Kitchen-Verifier-ServerSpec, Kitchen-Inspec, Kitchen-Pester
Docker Machine
Docker Machine has a few options for backend providers outside of Virtualbox:
- Docker Machine Overview
- Docker Toolbox (which includes Docker Machine)
- Docker Machine Drivers: AWS, GCE, vSphere, Hyper-V, HyperKit (or xhyve), KVM
Minikube
- Running Kubernetes Locally via Minikube
- Source: https://github.com/kubernetes/minikube
- Minikube drivers: https://github.com/kubernetes/minikube#quickstart
Vagrant Boxen
- Building Images: Packer, VeeWee, Vagrant
- Getting Images: Vagrant Cloud, Vagrantbox.es, Bento Boxes, Microsoft Windows Images
Change Configuration
- Agent Pull-Based: CFEngine, Chef, Puppet
- Push-Based, Remote Execution: Ansible, Salt Stack
Systems Integration Testing
- Test Verifiers: ServerSpec, InSpec, BATS, TestInfra, GOSS
- Test Harness: Test Kitchen, Molecule, Beaker
- Test Script Projects: Simp Project (The System Integrity Management Platform), Dev Sec (Security + DevOps: Automatic Server Hardening)