<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matheus Thurler</title>
    <description>The latest articles on DEV Community by Matheus Thurler (@matheus_thurler_cea17574b).</description>
    <link>https://dev.to/matheus_thurler_cea17574b</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4203334%2F75cab1b7-c767-42ac-92df-007854635aa8.jpg</url>
      <title>DEV Community: Matheus Thurler</title>
      <link>https://dev.to/matheus_thurler_cea17574b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/matheus_thurler_cea17574b"/>
    <language>en</language>
    <item>
      <title>KubeVirt does not run on Apple Silicon, so I built KubeSilicon</title>
      <dc:creator>Matheus Thurler</dc:creator>
      <pubDate>Fri, 23 Oct 2026 19:59:45 +0000</pubDate>
      <link>https://dev.to/matheus_thurler_cea17574b/kubevirt-does-not-run-on-apple-silicon-so-i-built-kubesilicon-3ce2</link>
      <guid>https://dev.to/matheus_thurler_cea17574b/kubevirt-does-not-run-on-apple-silicon-so-i-built-kubesilicon-3ce2</guid>
      <description>&lt;p&gt;&lt;strong&gt;KubeVirt does not run on a Mac with Apple Silicon.&lt;/strong&gt; It needs KVM, and macOS has no KVM.&lt;/p&gt;

&lt;p&gt;I maintain &lt;a href="https://matheusthurler.com.br/posts/leaving-proxmox-kubernetes-native-private-cloud/" rel="noopener noreferrer"&gt;VirtFoundry&lt;/a&gt;, a private cloud operator built on KubeVirt. That means every time I wanted to test something that creates VMs, I needed a Linux server. My M5 Pro could run the cluster, but not the VMs.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;&lt;a href="https://github.com/Matheus-Thurler/KubeSilicon" rel="noopener noreferrer"&gt;KubeSilicon&lt;/a&gt;&lt;/strong&gt;: you declare a &lt;code&gt;SiliconVM&lt;/code&gt; object, and a daemon on the Mac boots a Linux ARM64 VM with Apple's &lt;a href="https://developer.apple.com/documentation/virtualization" rel="noopener noreferrer"&gt;&lt;code&gt;Virtualization.framework&lt;/code&gt;&lt;/a&gt;. Pods in your local cluster reach the VM by IP or DNS name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Matheus-Thurler/KubeSilicon#readme" rel="noopener noreferrer"&gt;Watch the 3.5 minute tutorial video&lt;/a&gt; (plays in the README).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;From-scratch install, 3.5 minutes: kind cluster, install, first VM, SSH, pod to VM, stop/start.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; kind (Docker Desktop VM)              macOS host
 ┌──────────────────────┐              ┌────────────────────────────────────┐
 │ SiliconVM objects    │◄─ API watch ─┤ kubesilicond                        │
 │ (CRD kubesilicon.io) │── status ───►│   download + convert image          │
 │                      │              │   cloud-init ISO                    │
 │ pod ──────── ping/ssh ─────────────►│   Virtualization.framework  ──► VM  │
 └──────────────────────┘              └────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The daemon runs on the Mac, outside the cluster. It watches &lt;code&gt;SiliconVM&lt;/code&gt; objects, starts one detached process per VM, and writes &lt;code&gt;status.phase&lt;/code&gt; and &lt;code&gt;status.ip&lt;/code&gt; back. It also publishes a headless Service, so &lt;code&gt;demo.default.svc.cluster.local&lt;/code&gt; resolves from any pod. The daemon can stop or crash and the VMs keep running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kind create cluster &lt;span class="nt"&gt;--name&lt;/span&gt; kubesilicon
make &lt;span class="nb"&gt;install &lt;/span&gt;&lt;span class="nv"&gt;CTX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kind-kubesilicon
kubectl &lt;span class="nt"&gt;--context&lt;/span&gt; kind-kubesilicon apply &lt;span class="nt"&gt;-f&lt;/span&gt; examples/vm.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kubesilicon.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SiliconVM&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;demo&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2Gi&lt;/span&gt;
  &lt;span class="na"&gt;disk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://cloud-images.ubuntu.com/releases/noble/release/ubuntu-24.04-server-cloudimg-arm64.img&lt;/span&gt;
    &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10Gi&lt;/span&gt;
  &lt;span class="na"&gt;cloudInit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;userData&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;#cloud-config&lt;/span&gt;
      &lt;span class="s"&gt;users:&lt;/span&gt;
        &lt;span class="s"&gt;- name: ubuntu&lt;/span&gt;
          &lt;span class="s"&gt;sudo: ALL=(ALL) NOPASSWD:ALL&lt;/span&gt;
          &lt;span class="s"&gt;ssh_authorized_keys: [ssh-ed25519 AAAA... you@host]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my tests the VM reaches &lt;code&gt;Running&lt;/code&gt; in about 6 seconds once the image is cached, and a busybox pod pings it in 1 to 2 ms.&lt;/p&gt;

&lt;h2&gt;
  
  
  kind, minikube, and others
&lt;/h2&gt;

&lt;p&gt;The daemon only needs two things: the Kubernetes API of your cluster, and a network path between the pods and the VM (the VMs get a NAT address on the Mac, &lt;code&gt;192.168.64.x&lt;/code&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tested:&lt;/strong&gt; kind on Docker Desktop. This is the only setup I have validated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Should work, not tested:&lt;/strong&gt; minikube, Colima, OrbStack, k3d. Anything where the cluster runs in a VM or container on the same Mac and can reach that NAT range.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does not apply:&lt;/strong&gt; a cluster in the cloud. The VMs live on your Mac.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you try another one, tell me what happened. I will add it to the validation notes either way.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it relates to KubeVirt and VirtFoundry
&lt;/h2&gt;

&lt;p&gt;KubeSilicon is &lt;strong&gt;not&lt;/strong&gt; KubeVirt and does not use its CRDs. It has its own &lt;code&gt;kubesilicon.io/v1&lt;/code&gt; API, shaped like KubeVirt's, because KubeVirt's launcher is built around KVM and QEMU.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;KubeVirt&lt;/th&gt;
&lt;th&gt;KubeSilicon&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hypervisor&lt;/td&gt;
&lt;td&gt;KVM + QEMU&lt;/td&gt;
&lt;td&gt;Apple Virtualization.framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Where VMs run&lt;/td&gt;
&lt;td&gt;Inside pods, on Linux nodes&lt;/td&gt;
&lt;td&gt;Processes on the Mac, outside the cluster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guests&lt;/td&gt;
&lt;td&gt;Linux, Windows, more&lt;/td&gt;
&lt;td&gt;Linux ARM64 only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Live migration, hotplug, snapshots&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runs on Apple Silicon&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maturity&lt;/td&gt;
&lt;td&gt;CNCF incubating&lt;/td&gt;
&lt;td&gt;Early, one Mac, one maintainer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;KubeVirt is the right choice on Linux servers. KubeSilicon is for the laptop: development, demos, and CI on your own Mac.&lt;/p&gt;

&lt;p&gt;VirtFoundry sits one layer above. It gives you tenants, VPCs, IAM, and a UI on top of the hypervisor. Mapping which KubeVirt resources VirtFoundry uses, so it could drive &lt;code&gt;SiliconVM&lt;/code&gt; on a Mac, is the idea I want to explore next. It is &lt;strong&gt;not built yet&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  An honest note on stability
&lt;/h2&gt;

&lt;p&gt;Early on, guests crashed at random: kernel Oops and &lt;code&gt;SIGILL&lt;/code&gt; in 3 of 4 boots with Apple's default disk mode. Switching the disk attachment to cached with fsync gave 0 crashes in 9 boots. The sample is small and I do not know the cause below the framework, so treat it as strong evidence, not proof. The numbers are in &lt;a href="https://github.com/Matheus-Thurler/KubeSilicon/blob/main/docs/validation.md" rel="noopener noreferrer"&gt;docs/validation.md&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits today
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;One Mac, one worker. Multiple Macs as nodes is a design goal, not a feature.&lt;/li&gt;
&lt;li&gt;The Service has no ports. Use the VM IP or ping.&lt;/li&gt;
&lt;li&gt;A VM whose launcher process died is not restarted automatically.&lt;/li&gt;
&lt;li&gt;Linux ARM64 guests only. macOS guests are out of scope.&lt;/li&gt;
&lt;li&gt;API &lt;code&gt;v1&lt;/code&gt; in name only. It will change.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/Matheus-Thurler/KubeSilicon" rel="noopener noreferrer"&gt;github.com/Matheus-Thurler/KubeSilicon&lt;/a&gt;, Apache-2.0.&lt;/li&gt;
&lt;li&gt;Needs an Apple Silicon Mac, Go, &lt;code&gt;qemu-img&lt;/code&gt;, a running kind cluster, and &lt;code&gt;kubectl&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Issues and pull requests are welcome, especially reports from other cluster tools.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>opensource</category>
      <category>macos</category>
      <category>go</category>
    </item>
  </channel>
</rss>
