Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save sickdyd/18363addb996408cd62fcbadb1d18d5e to your computer and use it in GitHub Desktop.
Save sickdyd/18363addb996408cd62fcbadb1d18d5e to your computer and use it in GitHub Desktop.

This steps will allow you to run a Windows Server 2012 R2 VirtualMachine in Minikube, which is a tool that allows you running a Kubernetes cluster on your local machine.

Tested on:

Macbook Pro
2 GHz Quad-Core Intel Core i5
16Gb of RAM

Install Docker Desktop

Minikube will use Docker (if installed) to create a container that acts as the Kubernetes cluster.

https://docs.docker.com/desktop/install/mac-install/

Install kubectl

This is the commandline tool to manage the Kubernetes cluster.

brew install kubectl

Install Minikube

This is the tool that allows creating a Kubernetes cluster on your local machine.

brew install minikube

Create the cluster

Minikube will by default use the docker driver. This means that it will create a Docker container that will act as the cluster. To successfully run the below command, you will need to allocate at least 4cpus and more than 8GB (I used 12GB) of RAM in the Docker desktop app (Settings -> Resources).

image

Technically it should work also with less memory and cpus, but I had some issues. Once you are happy with the resources allocations, execute:

minikube start --memory="8G" --cpus=4

Add the KubeVirt operator and Custom Resource Definition (CRI)

KubeVirt is an extension for Kubernetes that allow handling Virtual Machines within Kubernetes.

The KubeVirt CRIs provide the necessary constructs to describe and manage virtual machines in a Kubernetes-native way.

The Minikube command to add the kubevirt addon is currently bugged (as per 13/09/2023) and we need to do it manually:

export VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases | grep tag_name | grep -v -- '-rc' | sort -r | head -1 | awk -F': ' '{print $2}' | sed 's/,//' | xargs)
echo $VERSION
# at the time of this doc, VERSION=v1.0.0-beta.0
kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/$VERSION/kubevirt-operator.yaml
# the below command will install the kubevirt CRIs
kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/$VERSION/kubevirt-cr.yaml

Enable nested virtualization:

We are essentially running a VM inside a VM: in this scenario, we need to enable nested virtualization.

kubectl -n kubevirt patch kubevirt kubevirt --type=merge --patch '{"spec":{"configuration":{"developerConfiguration":{"useEmulation":true}}}}'

Create Containerized Data Importer (CDI)

The CDI is a utility designed for use with KubeVirt. It provides facilities to enable users to import, upload, and clone Virtual Machine disks into their KubeVirt environment.

export TAG=$(curl -s -w %{redirect_url} https://github.com/kubevirt/containerized-data-importer/releases/latest)
export VERSION=$(echo ${TAG##*/})
echo $VERSION
# at the time of this doc, VERSION=v1.57.0
kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-operator.yaml
kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-cr.yaml

Create PersistentVolume (PV) for uploading image

Imagine a PV as an hard drive somewhere. This one will be used for the ISO and later will be placed in the CD drive in the VM. Just copy paste it in the shell and hit return:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-win2012-iso
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 5Gi
  hostPath:
    path: /data/pv-win2012-iso/
EOF

Download the Windows 2012 ISO image

Rename the downloaded image to win2012.iso:

https://www.microsoft.com/en-us/evalcenter/download-windows-server-2012-R2

Use port forward to allow uploading the Windows ISO image through the upload proxy

This will forward the local port 8443 to the service/cdi-uploadproxy: this allows us to upload an image to the cluster by uploading it to our local address https://127.0.0.1:8443 (done in the following command).

kubectl port-forward -n cdi service/cdi-uploadproxy 8443:443

Upload ISO file

This will automatically create a PeristentVolumeClaim called win2012cd-pvc. A PVC is essentially a request to Kubernetes saying "please give me this much space", and Kubernetes will look into the various PVs trying to find an "hard drive" that can provide that space.

Change --image-path=win2012.iso to the ISO filename you downloaded (or leave it like that if you renamed it):

kubectl virt image-upload pvc pvc-win2012-iso --size 5Gi --image-path=win2012.iso --uploadproxy-url=https://127.0.0.1:8443 --insecure

Once the upload is done, you can close the port forwarding with CTRL + C.

Create the PV for the Windows drive

This is the PV that will be used to install the OS:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-win2012-hd
  labels:
    type: local
spec:
  storageClassName: standard
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/var/hostImages/pv-win2012-hd"
EOF

Create the PVC for the drive

This will claim the space from the PV pv-win2012-hd, used for the OS installation:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-win2012-hd
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
  storageClassName: standard
EOF

Create the VM

The reason I had to add inputs / tablets is because (the mouse is not working properly without it)[wavezhang/virtVNC#5].

Note that the harddrive needs to use the virtio bus driver in order to function.

cat <<EOF | kubectl apply -f -
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: win2012
spec:
  running: false
  template:
    metadata:
      labels:
        kubevirt.io/domain: win2012
    spec:
      domain:
        cpu:
          cores: 2
        devices:
          inputs:
            - type: tablet
              bus: virtio
              name: tablet1
          interfaces:
            - masquerade: {}
              model: e1000
              name: default
          disks:
            - bootOrder: 1
              cdrom:
                bus: sata
              name: cdromiso
            - bootOrder: 2
              disk:
                bus: virtio
              name: harddrive
            - bootOrder: 3
              cdrom:
                bus: sata
              name: virtiocontainerdisk
        machine:
          type: q35
        resources:
          requests:
            memory: 4G
      networks:
        - name: default
          pod: {}
      volumes:
        - name: cdromiso
          persistentVolumeClaim:
            claimName: pvc-win2012-iso
        - name: harddrive
          persistentVolumeClaim:
            claimName: pvc-win2012-hd
        - name: virtiocontainerdisk
          containerDisk:
            image: quay.io/kubevirt/virtio-container-disk
EOF

Start the VM

This can take some time, check the status of the pods:

kubectl virt start win2012

Install vnc app and create account

In order to connect to the VM and controlling the graphical interface, we will use a tool called VNC.

You will have to create a free account to use it:

https://www.realvnc.com/en/connect/download/viewer/

Connect to the VM via VNC

kubectl virt vnc win2012

If everything goes well, you should see the setup initial screen.

Once the setup gets to the step where you need to choose where to install the OS, you will not see the hd. In order to see it, you'll have to install the virtio drivers, which can be found by browsing in CD Drive (E:) virtio-win-0.1.1/amd64/2k8. After the installation you will see the drive and you can continue the setup.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment