In some of environments, simetime we need a way to run a image inside kubernetes, and not to install qemu/kvm on Host itself.
so I prepard a pod manifest to run mikrotik qcow2 image to having all mikrotik feature inside a pod
I have KVM Enabled baremetal nodes and hence I used -enable-kvm option
I created a docker image name mrtzfrpr/qemu:8.2.2 in my docker hub to make qemu-system command the entry point in container
its a simple Ubuntu 24 Noble version image and installed latest qemu-system package inside, below you can see my Docker file:
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y --no-install-recommends \
qemu-system-x86 \
qemu-utils \
iproute2 \
bridge-utils \
socat \
procps \
busybox \
&& \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
ENTRYPOINT ["/usr/bin/qemu-system-x86_64"]
CMD ["--version"]
Now its time to run a image by a pod, I've used initcontainer to creating brdige mode needed file and puts my qcow2 image in a host path, you may copy it to a longhorn persist volume and make it replica and highly available
to access this machine console you can telnet to host port 127.0.0.1 2323 and login normally into you router os env by telnet 127.0.0.1 2323
to make access from outside to router you can use kubernetes service + endpoint to emulate this vm is a outside cluster workload and reach it by a loadbalancer service which I bring the manifest at the end. by the way, the kind of endpoint object in kubernetes is deprecating soon and should use endpintslice
apiVersion: v1
kind: Pod
metadata:
name: routeros
namespace: default
spec:
restartPolicy: Never
nodeName: kube1
hostNetwork: true
initContainers:
- name: setup-qemu-bridge
image: mrtzfrpr/qemu:8.2.2
securityContext:
privileged: true
command: ["/bin/sh", "-c"]
args:
- |
set -e
# Create the directory and config file
mkdir -p /etc/qemu
cat > /etc/qemu/bridge.conf <<EOF
allow br0
EOF
# Optional: verify
ls -l /etc/qemu/bridge.conf
echo "Bridge config ready"
volumeMounts:
- mountPath: /etc/qemu
name: qemu-etc
containers:
- name: qemu
image: mrtzfrpr/qemu:8.2.2
securityContext:
privileged: true
resources:
requests:
cpu: "1"
memory: "512Mi"
limits:
cpu: "1"
memory: "512Mi"
args:
- -enable-kvm
- -cpu
- host
- -m
- "512"
- -smp
- "1"
- -drive
- file=/images/mikrotik-routeros-kvm-disk.qcow2,format=qcow2,if=ide,cache=none,aio=native
- -netdev
- bridge,id=net0,br=br0
- -device
- virtio-net-pci,netdev=net0
- -display
- none
- -serial
- telnet:127.0.0.1:2323,server,nowait
volumeMounts:
- mountPath: /images/mikrotik-routeros-kvm-disk.qcow2
name: qemu-disk
- mountPath: /etc/qemu
name: qemu-etc
volumes:
- name: qemu-disk
hostPath:
path: /opt/vms/routeros/mikrotik-routeros-kvm-disk.qcow2
type: File
- name: qemu-etc
emptyDir: {}
apiVersion: v1
kind: Service
metadata:
name: routeros-winbox
spec:
ports:
- port: 63763
targetPort: 8291
externalIPs:
- YOUR_PUBLIC_IP_OR_LEAVE_IT_IF_YOU_ARE_IN_CLOUD_PROVIDER
type: LoadBalancer
---
apiVersion: v1
kind: Endpoints
metadata:
name: routeros-winbox
subsets:
- addresses:
- ip: 172.16.16.2
ports:
- port: 8291