Kubernetes VM Stack v1.36.6-kubevirt1.9.1
Virtual machines on a three-node, highly available Kubernetes cluster, from images ReadyStack built with the network off, each pinned by digest and pulled only from your own registry.
Released 2026-10-29 · The bundle's release page · Docker Hub
What it is
The Kubernetes VM Stack runs virtual machines on a three-node Kubernetes cluster. Every part is a signed ReadyStack release, built with the network off from pinned upstream source and packages, and every image the cluster runs is pinned by digest in one install bundle.
- Clusterkubeadm v1.36.6, highly available: all three nodes run the control plane, with etcd v3.7.3 stacked on them, behind a kube-vip virtual IP.
- Add-onsflannel for the Pod network, Multus with a host bridge so VMs get an interface on your LAN, and KubeVirt v1.9.1, which runs VMs from static local disks.
- ImagesEvery image is a ReadyStack release pinned by digest. The hosts pull only from a local registry on your own network.
- RootEvery image runs as a non-root user by default. Where a component needs root, the bundle's Pod specs and kubeadm patches set it: root is set by the Pod, not by the image.
- The bundleAn image FROM scratch that holds the install bundle, the pin manifest (kubevirt-stack.json) and the operator runbook, with a checker, stack-bundle, that verifies every file against the bundle's SHA256SUMS.
- HostsThree Ubuntu 24.04 x86-64 hosts on one layer-2 network, with /dev/kvm on each (without it KubeVirt falls back to emulation, which is slow), a free address for the virtual IP, and a machine for the local registry. The stack was tested end to end on three Ubuntu 24.04 nodes.
- Bundle image
readystack/kubernetesvmstack:v1.36.6-kubevirt1.9.1-CE-scratch-r2 - linux/amd64 digest
sha256:0268790dadac6fbc392784cb7f77f996526f4d1b6394bb30228d19ddaae062e9 - SignatureSigned (key 04daa92344a52dbc)
- Offline rebuildRebuilt bit-for-bit on 2026-10-29 with the network off
Who installs it and why
Our pitchOur pitch: who we built it for. It is not a list of customers.
- Teams that run a fleet of virtual machines on their own hardware and want those VMs managed beside their containers: one Kubernetes API, one set of manifests, one registry.
- Sites that cannot pull from the internet, such as air-gapped, regulated and sovereign environments. Every host pulls only from a local registry on your own network, and each image can be checked against its signature, SBOM and provenance before it goes in.
- Teams that must show what they run. Every part is a signed ReadyStack release with an SPDX SBOM and SLSA v1 provenance, and the bundle's pin manifest names the upstream repository and commit of every component it pins.
What's in it
As JSONEach part is its own ReadyStack release. The names, tags, digests and grades below are read from the catalogue (/api/products) and our scans (/api/scans) when the page is served; each name opens that part's page.
| Part | Release tag | linux/amd64 digest | Grade: original → current |
|---|---|---|---|
| Host programs | |||
| Kubernetes Node v1.36.6kubelet, kubeadm, kubectl, containerd, runc, the CNI plugins and crictl. Its one layer is the node tarball the install bundle puts on each host. | v1.36.6-CE-scratch-r1 |
sha256:0a264881a0b7357fb20767b0922661bf4ba4423b3e90e595195bf18748a8d79c |
AA |
| Control plane | |||
| kube-apiserver v1.36.6The Kubernetes API server, a static Pod on each node. Root is set by a kubeadm patch. | v1.36.6-CE-ubuntu24.04-r1 |
sha256:49c4d7708668d7ab42ae0d1d3d584063f67ef87f2d746e21d6709288afdb997e |
AA |
| kube-controller-manager v1.36.6The controller manager, a static Pod on each node. Root is set by a kubeadm patch. | v1.36.6-CE-ubuntu24.04-r1 |
sha256:f832d6d6174e904cb86f178379571f02421cd5e056f112da12062aec8d2f93a2 |
AA |
| kube-scheduler v1.36.6The scheduler, a static Pod on each node. Root is set by a kubeadm patch. | v1.36.6-CE-ubuntu24.04-r1 |
sha256:db92258d58a8e98424edd20418624e6625c4360acedd4dd919443a3e538c9ef8 |
AA |
| kube-proxy v1.36.6Service routing on each node, deployed by the bundle's own DaemonSet, which sets root. | v1.36.6-CE-ubuntu24.04-r1 |
sha256:690fd8d24cd4ffbf70dbe1ba26ac48ce80a972d7183cf691948ff5ff8ca8d56c |
AA |
| pause 3.10.2The Pod sandbox image containerd starts for every Pod. | 3.10.2-CE-scratch-r1 |
sha256:6b74cfa71db2c51e1a21e3342402d3993573ea02a0c85063897eda87958dca26 |
AA |
| Cluster DNS | |||
| CoreDNS v1.14.2Cluster DNS, at exactly the version kubeadm names. | v1.14.2-CE-ubuntu24.04-r1 |
sha256:faf5d9691f306d7f318377a2db731aa843ef8ed23866e7c410cdbc001dda2c4b |
AA |
| Networking | |||
| kube-vip v1.3.1Holds the control-plane virtual IP and moves it when a node is lost. Root is set in the bundle's YAML. | v1.3.1-CE-ubuntu24.04-r1 |
sha256:74dd28c7b8af69cd7cf4684338b782d1fbf939a1dbfabeb1545d70b077cf934b |
AA |
| flannel v0.28.10The Pod network across the nodes. Root is set in the bundle's YAML. | v0.28.10-CE-ubuntu24.04-r1 |
sha256:6d3fb1140502d71df92ae2b107532acaf809aa42a94e2e6b9eec291fab4b8856 |
AA |
| flannel CNI plugin v1.9.1-flannel3flannel's CNI plugin, put on each node by the flannel DaemonSet. | v1.9.1-flannel3-CE-ubuntu24.04-r1 |
sha256:4511acd7413d1e6fd78d3d712921d794cb820a3b62973512532d7b64f2cc4e8a |
AA |
| Multus CNI v4.3.1Multus: gives Pods and VMs a second interface on the hosts' bridge. Root is set in the bundle's YAML. | v4.3.1-CE-ubuntu24.04-r1 |
sha256:f90014221243e98cf21d56dc66e3f53bf386c1c1484a633e550dadf4e39f324e |
AA |
| KubeVirt | |||
| virt-operator v1.9.1Installs and manages the KubeVirt components. | v1.9.1-CE-debian12-r1 |
sha256:78de21c348d6b5c03db14e9b14e4fe02f947114771f8897f53c2f52bf435a0a6 |
AA |
| virt-api v1.9.1KubeVirt's API server. | v1.9.1-CE-debian12-r1 |
sha256:1b50959eea78ae4db3a6037b90943ada86b9cb5426bb4790525316087d0ff582 |
AA |
| virt-controller v1.9.1KubeVirt's cluster-wide controller. | v1.9.1-CE-debian12-r1 |
sha256:4e9192b84b55aa401f992f0337ac4a76e79d25ff2519e803274a3c353b01ad12 |
AA |
| virt-exportproxy v1.9.1Serves exports of VM disks. | v1.9.1-CE-debian12-r1 |
sha256:3bb06b5880899bf2955da20fb6c47810f0a863a9057c0c9ec13f61a3a624322b |
AA |
| readystack/virthandler Not listedvirt-handler: KubeVirt's agent on each node. Root is set by the KubeVirt CR's patch.Published and signed, but not listed: it scores below A on our scan. KubeVirt builds virt-handler on its own CentOS Stream 9 package set, which carries high vulnerabilities that CentOS Stream has not fixed yet. Its Docker Hub page gives the grade and every deduction. | v1.9.1-CE-centos9-r1 |
Not in /api/products (unlisted); its Docker Hub page gives it | FF |
| readystack/virtlauncher Not listedvirt-launcher: the Pod each VM runs in. It starts libvirt and QEMU as the unprivileged qemu user.Published and signed, but not listed: it scores below A on our scan. KubeVirt builds virt-launcher, QEMU and libvirt included, on its own CentOS Stream 9 package set, which carries high vulnerabilities that CentOS Stream has not fixed yet. Its Docker Hub page gives the grade and every deduction. | v1.9.1-CE-centos9-r1 |
Not in /api/products (unlisted); its Docker Hub page gives it | FF |
| VM client | |||
| virtctl v1.9.1The VM client for the admin machine (console, start, stop): the binary and its release tarball. | v1.9.1-CE-scratch-r1 |
sha256:634431da66d601627ffc0cddd0e41d02678ff5c1a2f6407661ae9f8a85091501 |
AA |
| Reused from the catalogue | |||
| etcd v3.7.3The cluster's datastore, stacked on the three nodes: the catalogue's own etcd release, used as it is. Root is set by a kubeadm patch. | v3.7.3-CE-ubuntu24.04-r1 |
sha256:b21b8089f1957b35bfaf54647f871c1e9e56d36d20af32a2fdb9b2b6483d62f6 |
AA |
| Distribution Registry v3.1.2The local registry every host pulls from, on your own network.Not pinned by the bundle: any release of it serves. | v3.1.2-CE-ubuntu24.04-r5 |
sha256:9b7a9955779cf093257a24546a860c35f627315956b12a93b9a03f013dffc449 |
AA |
| The bundle | |||
| Kubernetes VM Stack v1.36.6-kubevirt1.9.1This stack's install bundle: the install files, the pin manifest and the operator runbook, with the stack-bundle checker. | v1.36.6-kubevirt1.9.1-CE-scratch-r2 |
sha256:0268790dadac6fbc392784cb7f77f996526f4d1b6394bb30228d19ddaae062e9 |
AA |
Grades are ReadyStack's own daily scan of each published image: a syft SBOM and grype vulnerability matches, scored with cerodeo-v1, the rubric ce.rodeo published until 2026-10-26. The original grade is the first recorded scan of the release, the current grade the latest. A part's own page explains its score. A part of the stack that does not score A on this scan is published and signed but not listed in the catalogue; it is shown here as not listed, with the reason.
How it was tested before release
Record of 2026-10-29Acceptance run, 2026-10-29, 11:03–11:55 UTC: passed
Before release, the published images were installed on three test nodes (Ubuntu 24.04 virtual machines with KVM available inside them) and checked end to end. Every check of the run passed.
- Every image was pulled from Docker Hub at its published digest into a local registry on the test network. The mirror copies an image only when its linux/amd64 digest is the one the bundle lists.
- cosign verified 60 of 60 signatures against ReadyStack's release key: the 30 names mirrored into the local registry, each by tag and by digest. The host-side kubernetesnode and virtctl releases verified too.
- Every mirrored image, and both host-side releases, carried an SPDX SBOM and SLSA v1 provenance.
- The test nodes could not reach the internet: from each node, HTTPS to public IP addresses was refused, checked at the start and again after KubeVirt was installed.
- On every node, every image ran at exactly its published digest, with none failing the check. No image defaulted to root: uid 0 came only where the bundle's files set it.
- Pods reached each other across the nodes and through a Service, and the Multus bridge gave a Pod a second interface.
- Failover: the control-plane node holding the virtual IP was switched off. The API answered on the virtual IP again after 17 s, from another node, and a write was accepted. Started again, the node was Ready after 68 s.
- KubeVirt became Available from the published images. A CirrOS VM booted from a static local disk ran under KVM, gave a console login prompt through the published virtctl, and took an address on the hosts' LAN.
- Two failures in the test's own scripts were fixed during the run. The record keeps both, and neither was a defect of a published image.
Also checked
- The bundle image, checked the same way the same day: cosign verified it by index and by linux/amd64 digest, its SBOM and SLSA v1 provenance were attached, its own check verified 26 files, and its 23 install files were byte-identical to the files the acceptance run used. (release
v1.36.6-kubevirt1.9.1-CE-scratch-r2) - etcd restore, 2026-10-29, 13:41–13:44 UTC: the runbook's restore of every etcd member from a kept backup was checked live on the same cluster, and 13 of 13 checks passed. Afterwards a marker written after the backup was gone, and the VM was still Running. The record of these checks ships in the bundle, as runbook/RUNBOOK_EVIDENCE.json.
- The operator runbook was checked against the stack's test cluster: 69 of 69 of its checks passed, as the release notes record. (release
v1.36.6-kubevirt1.9.1-CE-scratch-r2)
Source: ReadyStack's integration report for the stack, its acceptance run and the evidence file of every check.
How to get it
The image is free on Docker Hub1. Pull the bundle and verify it. cosign checks the image against ReadyStack's release key; then the image's own check verifies every file of the bundle against its SHA256SUMS. The image has no shell, so the bundle is copied out of a container that is created but never started, and the copy is checked again on your machine.
KEY=https://readystack.dev/keys/cosign.pub IMAGE=readystack/kubernetesvmstack:v1.36.6-kubevirt1.9.1-CE-scratch-r2@sha256:0268790dadac6fbc392784cb7f77f996526f4d1b6394bb30228d19ddaae062e9 cosign verify --key "$KEY" "$IMAGE" docker run --rm "$IMAGE" # prints "Kubernetes VM Stack v1.36.6-kubevirt1.9.1: 26 files verified", or names each problem and exits 1 docker create --name kvs-bundle "$IMAGE" # the image has no shell docker cp kvs-bundle:/kubernetesvmstack . docker rm kvs-bundle (cd kubernetesvmstack && sha256sum --quiet -c SHA256SUMS)
2. Unpack it. kubernetesvmstack/install/ is the install bundle, with its README.md, the full order of operations; kubernetesvmstack/runbook/RUNBOOK.md is the operator runbook, with the checks to repeat on your own cluster; kubernetesvmstack/kubevirt-stack.json is the pin manifest.
3. Install, in this order (each step in full in install/README.md):
- The local registry. Run readystack/registry on a machine the hosts reach, with TLS from a CA the hosts trust.
- The registry config. Put the registry's address, CA and credential on every host, in a root-only file.
- The host bridge. On each host, move the uplink onto a bridge (br0) with the bundle's netplan example.
- Mirror the images. mirror-images.sh copies every image by digest into the local registry, signatures and attestations included; then check each with cosign.
- The hosts. install-node.sh installs the host programs from the Kubernetes Node bundle and points containerd at the local registry, with no public fallback.
- The first node. The kubeadm patches, kube-vip, then kubeadm init.
- The other two nodes. The same patches and kube-vip, then kubeadm join as control-plane nodes.
- Add-ons. kube-proxy, flannel and Multus, then spread CoreDNS over the nodes.
- KubeVirt. The operator, then the KubeVirt CR; wait until it is Available.
- VMs. A VM from an existing disk on a static local volume, with a NIC on the host bridge; then virtctl console.
Known limits
- A VM on a local volume is pinned to its node: it cannot live-migrate, and it stops while that node is down.
- Kubernetes 1.37 waits for a KubeVirt release that supports it. KubeVirt 1.9 supports Kubernetes 1.34 to 1.36, so we hold the stack on the 1.36 line.
- containerd reads the registry credential from its deprecated registry.configs setting. The runbook says why, and the stack keeps containerd on a release that still reads it.
- The OCI licences labels of the pause and kubernetesnode images understate their licences: they leave out glibc, which is linked into them statically and is LGPL-2.1-or-later. Their Docker Hub pages and SBOMs say so, and each image's next revision corrects the label.
- virt-handler and virt-launcher are published and signed but not listed, because they score below A on our scan (see the table above).
- readystack/registry's health check probes 127.0.0.1, so with the registry bound to another address and TLS on, Docker reports it unhealthy while it serves.
- Built for x86-64 (linux/amd64) only.
Ask for another stack
Need a different platform built this way? Tell us the platform, its components and the machines; we check the licence and feasibility first. $250 when it ships. Your card is saved, not charged, and if we cannot take it on we remove it.