├── screenshot.png ├── manifests ├── service.yaml ├── pv.yaml └── deployment.yaml ├── README.md └── image └── Dockerfile /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meyskens/k8s-winnt/HEAD/screenshot.png -------------------------------------------------------------------------------- /manifests/service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: winnt-host 6 | spec: 7 | type: NodePort 8 | selector: 9 | app: winnt 10 | ports: 11 | - protocol: TCP 12 | port: 3389 13 | targetPort: rdp 14 | --- 15 | apiVersion: v1 16 | kind: Service 17 | metadata: 18 | name: winnt 19 | spec: 20 | type: NodePort 21 | selector: 22 | app: winnt 23 | ports: 24 | - protocol: TCP 25 | port: 3389 26 | targetPort: ntrdp 27 | -------------------------------------------------------------------------------- /manifests/pv.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolume 3 | metadata: 4 | name: wintnt-pv 5 | spec: 6 | capacity: 7 | storage: 100Gi 8 | volumeMode: Filesystem 9 | accessModes: 10 | - ReadWriteOnce 11 | persistentVolumeReclaimPolicy: Delete 12 | storageClassName: local-storage 13 | local: 14 | path: /mnt/disk1/winnt 15 | nodeAffinity: 16 | required: 17 | nodeSelectorTerms: 18 | - matchExpressions: 19 | - key: kubernetes.io/hostname 20 | operator: In 21 | values: 22 | - upcycle-k8s-worker-1 23 | --- 24 | apiVersion: v1 25 | kind: PersistentVolumeClaim 26 | metadata: 27 | name: wintnt-pvc 28 | spec: 29 | storageClassName: local-storage 30 | accessModes: 31 | - ReadWriteOnce 32 | resources: 33 | requests: 34 | storage: 100Gi 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Windows NT in Kubernetes 2 | 3 | Yes I am crazy. 4 | 5 | ![Screenshot of Windows NT in k8s](./screenshot.png) 6 | 7 | Old technology is always fun to play with, this one came out of the idea of building a retro computer lab. 8 | However building one requires too much space on my desk. 9 | So what if we put it inside the cloud? (well my baremetal "upcycle" cluster) 10 | 11 | ## Requirements 12 | This will not work in traditional cloud environments unless you have nested virtualisation enabled. 13 | You will also need to have root access to modify the kernel for Virtualbox, this is still the best option for Windows NT imo. 14 | 15 | ## Setup 16 | This repository has my the Docker image i used inside `image/`, it installs VirtualBox as well as create a VM configuration. 17 | The `manifests/` directory has the Kubernetes manifests I used, note that the PV one I use uses local PVs. 18 | 19 | ### The nodes 20 | You have to set up the Virtualbox kernel modules inside the nodes, on how to do so without installing Virtualbox I's like to refer to [Jess Frazelle's dockerfiles](https://github.com/jessfraz/dockerfiles/blob/master/virtualbox/Dockerfile) 21 | 22 | ### The files 23 | You will need 2 files inside your PV: 24 | * `winnt.iso`: a Windows NT ISO, I use the Terminal Server edition so I can RDP into the server 25 | * `winnt.vdi`: an empty disk, note this is Windows NT 4 it can be maximum 2GB. Can be created using `VBoxManage createhd --filename winntx.vdi --size 2000 --format VDI` 26 | 27 | ### The deployment 28 | Inside manifests first deploy `service.yaml` and `pv.yaml`, then `deployment.yaml`. 29 | 30 | You will now have 2 services `winnt-host` is a NodePort service for the Virtualbox RDP daemon. `winnt` forwards the RDP port to the VM itsef. 31 | -------------------------------------------------------------------------------- /manifests/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: winnt 5 | labels: 6 | app: winnt 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: winnt 12 | template: 13 | metadata: 14 | labels: 15 | app: winnt 16 | spec: 17 | volumes: 18 | - name: pv-storage 19 | persistentVolumeClaim: 20 | claimName: wintnt-pvc 21 | containers: 22 | - name: winnt 23 | resources: 24 | requests: 25 | memory: "64Mi" 26 | cpu: "100m" 27 | limits: 28 | memory: "265Mi" 29 | cpu: 1 30 | securityContext: 31 | privileged: true 32 | image: maartje/vbox:winnt 33 | imagePullPolicy: Always 34 | command: 35 | - /bin/bash 36 | - -c 37 | - | 38 | VBoxManage storageattach WinNT --storagectl "IDE Controller" --port 0 --device 0 --type hdd --medium /media/winnt.vdi 39 | VBoxManage storageattach WinNT --storagectl "IDE Controller" --port 0 --device 1 --type dvddrive --medium /media/winnt.iso 40 | # Forward RDP 41 | VBoxManage modifyvm "WinNT" --natpf1 "rdp,tcp,,33890,,3389" 42 | # Disable vbox's RDP 43 | VBoxManage modifyvm WinNT --vrde off 44 | # Start the VM 45 | VBoxManage startvm WinNT --type headless 46 | while [ "$(VBoxManage showvminfo WinNT | grep State | tr -s " " | cut -d " " -f 2)" == "running" ] 47 | do 48 | sleep 10 49 | done 50 | lifecycle: 51 | preStop: 52 | exec: 53 | command: ["/bin/bash","-c","VBoxManage controlvm WinNT poweroff"] 54 | volumeMounts: 55 | - mountPath: "/media/" 56 | name: pv-storage 57 | ports: 58 | - containerPort: 3389 59 | name: rdp 60 | - containerPort: 33890 61 | name: ntrdp -------------------------------------------------------------------------------- /image/Dockerfile: -------------------------------------------------------------------------------- 1 | # Credits to Jessie Frazelle ! 2 | FROM ubuntu:bionic 3 | ENV DEBIAN_FRONTEND noninteractive 4 | 5 | RUN apt-get update && apt-get install -y \ 6 | libcurl4 \ 7 | libvpx5 \ 8 | procps \ 9 | --no-install-recommends \ 10 | && rm -rf /var/lib/apt/lists/* 11 | 12 | RUN buildDeps=' \ 13 | ca-certificates \ 14 | curl \ 15 | gnupg \ 16 | ' \ 17 | && set -x \ 18 | && mkdir -p /etc/xdg/QtProject \ 19 | && apt-get update && apt-get install -y $buildDeps --no-install-recommends \ 20 | && rm -rf /var/lib/apt/lists/* \ 21 | && curl -sSL https://www.virtualbox.org/download/oracle_vbox_2016.asc | apt-key add - \ 22 | && echo "deb http://download.virtualbox.org/virtualbox/debian bionic contrib" >> /etc/apt/sources.list.d/virtualbox.list \ 23 | && apt-get update && apt-get install -y \ 24 | virtualbox-6.1 \ 25 | --no-install-recommends \ 26 | && VBoxVer=`dpkg -s virtualbox-6.1 | grep "^Version" | cut -d " " -f 2 | cut -d "-" -f 1` \ 27 | && curl --insecure https://download.virtualbox.org/virtualbox/$VBoxVer/Oracle_VM_VirtualBox_Extension_Pack-$VBoxVer.vbox-extpack --output /tmp/Oracle_VM_VirtualBox_Extension_Pack-$VBoxVer.vbox-extpack \ 28 | && mkdir -p /usr/lib/virtualbox/ExtensionPacks/Oracle_VM_VirtualBox_Extension_Pack/ \ 29 | && tar xzf /tmp/Oracle_VM_VirtualBox_Extension_Pack-$VBoxVer.vbox-extpack -C /usr/lib/virtualbox/ExtensionPacks/Oracle_VM_VirtualBox_Extension_Pack/ \ 30 | && chmod -R o-w /usr/lib/virtualbox/ExtensionPacks/Oracle_VM_VirtualBox_Extension_Pack \ 31 | && apt-get purge -y --auto-remove $buildDeps 32 | 33 | # Create a VM 34 | RUN VBoxManage createvm --name WinNT --ostype WindowsNT4 --register 35 | RUN VBoxManage modifyvm WinNT --memory 128 36 | RUN VBoxManage storagectl WinNT --name "IDE Controller" --add ide 37 | RUN VBoxManage modifyvm WinNT --boot1 disk --boot2 dvd --boot3 none --boot4 none 38 | RUN VBoxManage modifyvm WinNT --vrde on --vrdeport 3389 39 | RUN VBoxManage modifyvm WinNT --vram 32 40 | 41 | # solves vbox scripts from sending all kinds of warnings 42 | RUN apt-get install -y kmod 43 | --------------------------------------------------------------------------------