Kubernetes controller that manages the lifecycle of Workspace custom resources,
built with kubebuilder and controller-runtime.
The controller watches for Workspace CRs and reconciles them into a workload
based on the workspace's spec.type:
container(default) — a StatefulSet (replicas 0 or 1) running the workspace container.vm— a KubeVirtVirtualMachine(requires KubeVirt installed; the controller detects the KubeVirt CRDs and reports aKubeVirtNotInstalledstatus condition if they are missing). The main image is a containerDisk containing a bootable guest OS;generateVirtualMachinealso attaches cloud-init user-data, injects the owner's SSH keys, pins the guest MAC, and emitsdomain.devices.gpus[]for GPU passthrough when requested.scratch— a plainDeployment(replicas 0 or 1).
Every type gets a ClusterIP Service exposing the workspace on port 80.
The controller owns the kubeworkspaces.io API group (v1alpha1):
| Kind | Scope |
|---|---|
Workspace |
Namespaced |
Image |
Cluster |
User |
Cluster |
AuthConfig |
Cluster |
PlatformConfig |
Cluster |
PodDefault |
Namespaced |
SshKey |
Namespaced |
The Workspace spec wraps a full corev1.PodSpec under spec.template.spec,
mirroring the Kubeflow Notebook CRD pattern. This gives full flexibility for
container configuration including env vars, args, volume mounts, resource
limits, etc.
The controller reports:
readyReplicas- Number of ready pods (0 or 1); forvmworkspaces this only reports 1 when the KubeVirtVirtualMachineInstanceis actually in the Running phasecontainerState- Running/waiting/terminated state of the first containerconditions- Pod conditions mirrored to the workspace (plusKubeVirtNotInstalledwhen KubeVirt CRDs are absent)
- Stop: Add annotation
kubeworkspaces.io/stopped: "true"(container/scratch scale replicas to 0;vmsetsspec.running: false, tearing the VMI down) - Start: Remove the annotation (restores replicas /
spec.running: true)
The controller watches for annotation changes and reconciles the workload accordingly.
The reconciler switches on spec.type:
container— ensure a StatefulSet exists (create or update);scratch— ensure a Deployment existsvm— ensure a KubeVirtVirtualMachineexists (generateVirtualMachine): containerDisk (or DataVolume root when the Image declarespersistentRootDisk), resources→domain.resources, ports→masquerade interfaces, pinned MAC, cloud-init user-data with owner SSH-key injection, GPUdomain.devices.gpus[]from GPU resource limits, andspec.running: !stopped- Ensure the Service exists (type-aware selector)
- Check for
kubeworkspaces.io/stoppedannotation -> set replicas /running - Update workspace status from pod/VMI state
- Ensure default container port if not specified (default: 8080)
# Generate CRD manifests
make manifests
# Generate deepcopy code
make generate
# Install CRD to cluster
make install
# Run controller locally
make rundocker build -t kube-workspaces-controller:latest -f Dockerfile .kubectl apply --server-side -f config/samples/v1alpha1_workspace.yaml
kubectl apply --server-side -f config/samples/v1alpha1_workspace_desktop.yamlNote: --server-side is required because the CRD is too large for client-side apply.
The controller requires a ClusterRole with permissions for:
workspaces.kubeworkspaces.io- all verbs + status subresourceimages,users,sshkeys,platformconfigs,authconfigs,poddefaults- read/write as applicable
apps/statefulsets+apps/deployments- create, get, list, watch, update, deletecore/services- create, get, list, watch, update, deletecore/pods- get, list, watchcore/pods/log- getcore/events- get, list, watchkubevirt.iovirtualmachines/virtualmachineinstances- read/write (VM workspaces)cdi.kubevirt.iodatavolumes- read/write (persistent VM root disks)subresources.kubevirt.iovirtualmachineinstances/console- get (serial console bridge)
RBAC is declared with kubebuilder markers in workspace_controller.go and
regenerated with make manifests into config/rbac/role.yaml; the same rules
must be mirrored into the deploy repo's Helm + Kustomize RBAC and validated
with compare-rbac.py.
| Repository | Description |
|---|---|
| kube-workspaces/api | REST API service |
| kube-workspaces/proxy | Workspace reverse proxy |
| kube-workspaces/frontend | Next.js web UI |
| kube-workspaces/deploy | Deployment manifests and documentation |
Apache License 2.0