|
| 1 | +--- |
| 2 | +title: "KubeVirt VMs Made Simple: VM Disk and VM Instance in Cozystack" |
| 3 | +slug: kubevirt-vm-disk-vm-instance |
| 4 | +date: 2026-06-19 |
| 5 | +author: "Timur Tukaev" |
| 6 | +description: "KubeVirt makes running virtual machines on Kubernetes powerful but complex. Cozystack collapses VirtualMachine, DataVolume, and PVC into two clean primitives — VM Disk and VM Instance — with independent lifecycles for golden images, cloning, and fast provisioning." |
| 7 | +images: |
| 8 | + - "social-card.png" |
| 9 | +article_types: |
| 10 | + - how-to |
| 11 | +topics: |
| 12 | + - kubevirt |
| 13 | + - platform |
| 14 | +--- |
| 15 | + |
| 16 | + |
| 17 | + |
| 18 | +If you've used KubeVirt directly, you know the pain: VirtualMachine, VirtualMachineInstance, DataVolume, PVC — a maze of resources just to run a simple VM. And if you want to clone a VM, share a base image, or migrate storage independently of compute? Good luck wiring that together yourself. |
| 19 | + |
| 20 | +Cozystack collapses that into two custom resources: **VMDisk** and **VMInstance**. They have independent lifecycles, and that's the whole point — delete the VM, the disk stays; attach the same disk to a beefier VM later; clone a golden image once and reuse it for every new VM. Immutable infrastructure and fast provisioning fall out for free. |
| 21 | + |
| 22 | +{{< figure src="vmdisk-vminstance.png" alt="VM Disks attach to a VM Instance; when the VM is deleted, the disks survive" width="720" >}} |
| 23 | + |
| 24 | +## Side by side |
| 25 | + |
| 26 | +| | VMDisk | VMInstance | |
| 27 | +|-----------------|-----------------------------------------|-------------------------------------------------------| |
| 28 | +| What it is | Persistent block device | Running virtual machine | |
| 29 | +| Lifecycle | Independent, survives VM deletion | Ephemeral — recreate any time without losing data | |
| 30 | +| KubeVirt analog | DataVolume + PVC | VirtualMachine + VirtualMachineInstance | |
| 31 | +| You configure | Source image, size, storageClass | Instance type, disks, SSH keys, cloud-init, GPU | |
| 32 | +| Used for | Golden images, data disks, pre-provisioning | Compute, networking, user data | |
| 33 | + |
| 34 | +## Create a VM Disk |
| 35 | + |
| 36 | +**Via Dashboard:** **Catalog** -> **VM Disk** -> set name, pick source image (Ubuntu, Windows, etc.), set size and storageClass -> **Deploy**. |
| 37 | + |
| 38 | +**Via kubectl:** |
| 39 | + |
| 40 | +```yaml |
| 41 | +apiVersion: apps.cozystack.io/v1alpha1 |
| 42 | +kind: VMDisk |
| 43 | +metadata: |
| 44 | + name: ubuntu-base |
| 45 | + namespace: tenant-team1 |
| 46 | +spec: |
| 47 | + source: |
| 48 | + image: |
| 49 | + name: ubuntu |
| 50 | + storage: 50Gi |
| 51 | + storageClass: replicated |
| 52 | +``` |
| 53 | +
|
| 54 | +Sources also include `http.url` (download from a URL) and `disk.name` (clone an existing VMDisk for golden-image workflows). |
| 55 | + |
| 56 | +## Create a VM Instance |
| 57 | + |
| 58 | +**Via Dashboard:** **Catalog** -> **VM Instance** -> name, instance type (e.g., `u1.medium`), attach the VMDisk, add SSH key and optional cloud-init -> **Deploy**. |
| 59 | + |
| 60 | +**Via kubectl:** |
| 61 | + |
| 62 | +```yaml |
| 63 | +apiVersion: apps.cozystack.io/v1alpha1 |
| 64 | +kind: VMInstance |
| 65 | +metadata: |
| 66 | + name: dev-server |
| 67 | + namespace: tenant-team1 |
| 68 | +spec: |
| 69 | + instanceType: u1.medium |
| 70 | + instanceProfile: ubuntu |
| 71 | + disks: |
| 72 | + - name: ubuntu-base |
| 73 | + sshKeys: |
| 74 | + - "ssh-ed25519 AAAA... user@workstation" |
| 75 | + cloudInit: | |
| 76 | + #cloud-config |
| 77 | + packages: |
| 78 | + - nginx |
| 79 | +``` |
| 80 | + |
| 81 | +The `disks[].name` field is the `metadata.name` of an existing VMDisk in the same namespace. |
| 82 | + |
| 83 | +## Access your VM |
| 84 | + |
| 85 | +```bash |
| 86 | +# Serial console |
| 87 | +virtctl console dev-server |
| 88 | +
|
| 89 | +# SSH |
| 90 | +virtctl ssh ubuntu@dev-server |
| 91 | +
|
| 92 | +# VNC (graphical) |
| 93 | +virtctl vnc dev-server |
| 94 | +``` |
| 95 | + |
| 96 | +## Why these are separate CRs (and not Helm releases) |
| 97 | + |
| 98 | +Under the hood Cozystack still uses Flux and Helm to roll resources out, but the user-facing API is the `apps.cozystack.io/v1alpha1` group. You write a `VMDisk` or `VMInstance`, the Cozystack operator handles the HelmRelease/KubeVirt/DataVolume plumbing for you. Same applies to every managed service in the catalog — Postgres, Kubernetes, VPC, OpenBao all have their own native CRs. |
| 99 | + |
| 100 | +## Documentation |
| 101 | + |
| 102 | +- [VM Instance](https://cozystack.io/docs/v1/virtualization/vm-instance/) |
| 103 | +- [VM Disk](https://cozystack.io/docs/v1/virtualization/vm-disk/) |
| 104 | +- [GPU Passthrough](https://cozystack.io/docs/v1/virtualization/gpu-passthrough/) |
| 105 | + |
| 106 | +## Join the community |
| 107 | + |
| 108 | +* GitHub: [cozystack/cozystack](https://github.com/cozystack/cozystack) |
| 109 | +* Telegram: [@cozystack](https://t.me/cozystack) |
| 110 | +* Slack: [#cozystack](https://kubernetes.slack.com/archives/C06L3CPRVN1) on the Kubernetes workspace ([invite](https://slack.kubernetes.io)) |
| 111 | +* [Subscribe to our community meetings calendar](https://zoom-lfx.platform.linuxfoundation.org/meetings/cozystack) |
| 112 | +* [Add meetings to your calendar](https://webcal.prod.itx.linuxfoundation.org/lfx/lfsixxnFWxbvsyEuC2) |
0 commit comments