A KubeVirt add-on providing native, user-friendly templating workflows for KubeVirt virtual machines.
cat <<'EOF' | kubectl apply -f -
apiVersion: template.kubevirt.io/v1alpha1
kind: VirtualMachineTemplate
metadata:
name: fedora
spec:
parameters:
- name: NAME
required: true
- name: INSTANCETYPE
value: u1.medium
- name: PREFERENCE
value: fedora
virtualMachine:
metadata:
name: ${NAME}
spec:
runStrategy: Always
instancetype:
name: ${INSTANCETYPE}
preference:
name: ${PREFERENCE}
template:
spec:
domain:
devices: {}
terminationGracePeriodSeconds: 180
volumes:
- containerDisk:
image: quay.io/containerdisks/fedora:latest
name: containerdisk-0
- cloudInitNoCloud:
userData: |
#cloud-config
password: fedora
chpasswd: { expire: False }
ssh_pwauth: True
name: cloudinitdisk-0
EOFvirt-template enables users to create, share, and manage VM blueprints
directly within the cluster. The project provides native support for in-cluster
templating through the VirtualMachineTemplate custom resource, which allows
you to define reusable VM templates with configurable parameters that can be
substituted at runtime to create VirtualMachine instances. Additionally, the
VirtualMachineTemplateRequest custom resource enables creating templates from
existing VirtualMachines.
Developed as a separate operator outside core KubeVirt, virt-template is
influenced by OpenShift's Template CRD and designed to provide a more
traditional virtualization experience within Kubernetes.
virt-template-controller: Kubernetes controller that watches and validatesVirtualMachineTemplateandVirtualMachineTemplateRequestresourcesvirt-template-apiserver: API server providing subresource APIs for templates
- VM Blueprints: Create reusable VM templates with parameter placeholders
using
${NAME}syntax - Parameter Substitution: Define static values, generated values, or required parameters for flexible template instantiation
- Server-Side Processing: Process templates in-cluster via the
processsubresource API - Cross-Namespace Sharing: Share and reuse templates across namespaces within your cluster
- Template Creation from VMs: Create templates from existing
VirtualMachinesusingVirtualMachineTemplateRequest
For development:
- Go version v1.24.0+
- Container tool: Podman (default) or Docker
- kubectl
For deployment on Kubernetes:
- cert-manager installed in the cluster
- KubeVirt installed in the cluster
For deployment on OpenShift:
- OpenShift Virtualization installed in the cluster
Build binaries locally:
make build # Build controller binary
make build-apiserver # Build apiserver binaryRun linting and formatting:
make fmt vet lintRun unit tests:
make testThe easiest way to deploy virt-template to your existing cluster is using a
released version.
On Kubernetes (requires cert-manager):
This will deploy virt-template into the kubevirt namespace.
export VERSION=v0.1.1
kubectl apply -f "https://github.com/kubevirt/virt-template/releases/download/${VERSION}/install.yaml"On OpenShift:
This will deploy virt-template into the openshift-cnv namespace.
export VERSION=v0.1.1
kubectl apply -f "https://github.com/kubevirt/virt-template/releases/download/${VERSION}/install-openshift.yaml"See the releases page for available versions.
The easiest way to develop and test is using kubevirtci:
make cluster-up # Start local KubeVirt cluster
make cluster-sync # Build, push, and deploy to cluster
make cluster-functest # Run functional tests
make cluster-down # Stop clustervirt-template supports two deployment configurations:
config/default- Standard Kubernetes deployment (requires cert-manager)config/openshift- OpenShift deployment (uses built-in Service CA operator)
Build and push container images:
make container-build container-push \
IMG_REGISTRY=<registry> \
VERSION=<tag>The build supports multi-arch images (amd64, arm64, s390x). Use
CONTAINER_TOOL=docker or CONTAINER_TOOL=podman.
Deploy on Kubernetes:
make install
make deploy IMG_REGISTRY=<registry> VERSION=<tag>Deploy on OpenShift:
make install
make deploy-openshift IMG_REGISTRY=<registry> VERSION=<tag>Create sample resources:
kubectl apply -f config/samples/template_v1alpha1_virtualmachinetemplate.yaml
kubectl apply -f config/samples/template_v1alpha1_virtualmachinetemplaterequest.yamlUninstall from Kubernetes:
kubectl delete vmt,vmtr --all # Delete sample instances
make undeploy # Remove controllers
make uninstall # Remove CRDsUninstall from OpenShift:
kubectl delete vmt,vmtr --all # Delete sample instances
make undeploy-openshift # Remove controllers
make uninstall # Remove CRDsThe VirtualMachineTemplate custom resource allows you to define reusable VM
blueprints with parameters:
apiVersion: template.kubevirt.io/v1alpha1
kind: VirtualMachineTemplate
metadata:
name: my-template
spec:
parameters:
- name: NAME
description: Name of the VM
required: true
- name: MEMORY
description: Memory size
value: "2Gi"
- name: PASSWORD
generate: expression
from: "[a-zA-Z0-9]{16}"
virtualMachine:
metadata:
name: ${NAME}
[...]Parameters are referenced using ${PARAMETER_NAME} syntax. They can have:
- Static values: Pre-defined default values (
value: "2Gi") - Generated values: Random values from expression generator
- Required flag: Mark parameters as mandatory (
required: true)
The expression generator creates random values using regex-like syntax:
parameters:
- name: PASSWORD
generate: expression
from: "[a-zA-Z0-9]{16}" # Generates 16 random alphanumeric chars
- name: API_KEY
generate: expression
from: "[A-F0-9]{32}" # Generates 32 random hex chars (uppercase)Supported character classes:
[a-z]- lowercase letters[A-Z]- uppercase letters[0-9]- digits[a-zA-Z0-9]- alphanumeric\w- word characters (letters, digits, underscore)\d- digits\a- alphabetic characters\A- special characters
The VirtualMachineTemplateRequest custom resource allows you to create a
VirtualMachineTemplate from an existing VirtualMachine. This is useful for
a golden image scenario where you want to convert an existing VirtualMachine
into a reusable template.
apiVersion: template.kubevirt.io/v1beta1
kind: VirtualMachineTemplateRequest
metadata:
name: my-template-request
spec:
templateName: my-template # Optional: name for the created template
ttlSecondsAfterFinished: 3600 # Optional: auto-delete after 1 hour
virtualMachineRef:
namespace: my-vm-namespace # Namespace of the source VM
name: my-vm # Name of the source VM
templateLabels: # Optional: labels to apply to the created template
example.com/os: linux
example.com/workload: serverOnce created, the controller will generate a VirtualMachineTemplate based on
the referenced VirtualMachine in the namespace of the
VirtualMachineTemplateRequest.
The optional ttlSecondsAfterFinished field limits the lifetime of a
successfully completed request. After the specified number of seconds the request
is automatically deleted. Failed requests are never cleaned up by the TTL
controller so they remain available for debugging. If unset, the request is not
automatically deleted.
The templateLabels field (available in v1beta1) allows you to apply custom
labels to the created VirtualMachineTemplate. This is useful for organizing
templates, adding metadata, or enabling label-based queries and filtering.
Note: Labels with the prefix template.kubevirt.io/ are reserved for
system use. Any such labels specified in templateLabels will be rejected and
filtered out, and the system-managed values will be used instead.
When creating a VirtualMachineTemplateRequest that references a VirtualMachine
in a different namespace (cross-namespace clone), the user must have create
permission on the virtualmachinetemplaterequests/source subresource in the
namespace of the source VirtualMachine. This is enforced by a
ValidatingAdmissionPolicy and ensures that permission to use a VM as a source
across namespaces is granted deliberately. Same-namespace clones do not require
this permission.
A virtualmachinetemplaterequest-source-role ClusterRole is provided to simplify
granting this permission. It is aggregated to the Kubernetes admin and edit
roles by default and allows using all VMs in a namespace as a source. For
finer-grained control, you can create custom roles that restrict the permission
to specific VMs using resourceNames:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: allow-specific-vm-source
rules:
- apiGroups:
- template.kubevirt.io
resources:
- virtualmachinetemplaterequests/source
resourceNames:
- my-vm
verbs:
- createWait for the template to be ready by running:
kubectl wait vmt my-template --for=condition=ReadyThe created template can then be processed like any other
VirtualMachineTemplate.
The virtualmachinetemplate-admin-role and virtualmachinetemplate-editor-role
ClusterRoles grant create on virtualmachinetemplates/process and
virtualmachinetemplates/create (API group
subresources.template.kubevirt.io). The /process subresource dry-runs
template processing and does not persist a VirtualMachine. The /create
subresource processes the template and creates a VirtualMachine in the
namespace.
Authorization for these endpoints uses the subresource create verb. The
VirtualMachine is created by the virt-template apiserver service account, so
callers do not need direct kubevirt.io/virtualmachines create permission.
Granting /create therefore allows users to create VMs via templates even when
direct VM create RBAC is withheld. In default KubeVirt configurations the
aggregated admin and edit roles already include VM management permissions;
this distinction matters mainly when defining custom roles.
The virtualmachinetemplate-viewer-role grants /process only (dry-run), not
/create.
Generate a single YAML file with all resources:
For Kubernetes:
make build-installer IMG_REGISTRY=<registry> VERSION=<tag>This creates dist/install.yaml which can be deployed with:
kubectl apply -f dist/install.yamlFor OpenShift:
make build-installer-openshift IMG_REGISTRY=<registry> VERSION=<tag>This creates dist/install-openshift.yaml which can be deployed with:
kubectl apply -f dist/install-openshift.yamlRun make help to see all available make targets.
Build tool versions (controller-gen, golangci-lint, gofumpt, etc.) are
pinned in tools/go.mod and vendored in tools/vendor/. To upgrade a
tool, update its version in tools/go.mod and run make vendor — the
tool is rebuilt automatically on next use via go tool.
Kubevirtci workflows:
The project provides two kubevirtci-based development environments:
cluster-*targets: Test with a stable KubeVirt releasekubevirt-*targets: Test with KubeVirt from git main
Example workflow:
make cluster-up # Start kubevirtci cluster
make cluster-sync # Build, deploy, and test
make cluster-functest # Run functional tests
make cluster-down # Stop clusterContributions are welcome! Please ensure:
- All tests pass:
make test functest make allpasses (runs formatting, vetting, linting, and code generation)
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Copyright The KubeVirt Authors.