- Creating VirtualMachines by using virtctl
Creating VirtualMachines by using virtctl
The virtctl sub command create vm
allows easy creation of VirtualMachine manifests from the command line. It leverages instance types and preferences and inference by default (see Using instance types and preferences) and it provides several flags to control details of the created virtual machine.
For example there are flags to specify the name or run strategy of a virtual machine or flags to add volumes to a virtual machine. Instance types and preferences can either be specified directly or it is possible to let KubeVirt infer those from the volume used to boot the virtual machine.
For a full set of flags and their description use the following command:
virtctl create vm -h
Creating VirtualMachines on a cluster
The output of virtctl create vm
can be piped directly into kubectl
to create a VirtualMachine on a cluster, e.g.:
# Create a VM with name my-vm on the cluster
virtctl create vm --name my-vm | kubectl create -f -
virtualmachine.kubevirt.io/my-vm created
Using instance types and preferences
Instance types and preferences can be used with the appropriate flags. If they are not otherwise specified, instance types and preferences are inferred from the boot volume of a virtual machine by default. For more information about inference, see below.
The following example creates a VM specifying an instance type and preference by using the appropriate flags:
virtctl create vm --instancetype my-instancetype --preference my-preference
The type of the instance type or preference (namespaced or cluster scope) can be controlled by prefixing the instance type or preference name with the corresponding CRD name, e.g.:
# Using a cluster scoped instance type and a namespaced preference
virtctl create vm \
--instancetype virtualmachineclusterinstancetype/my-instancetype \
--preference virtualmachinepreference/my-preference
If a prefix was not supplied the cluster scoped resources will be used by default.
Inference of instance type and/or preference
To explicitly infer instance types and/or preferences from the volume used to boot the virtual machine add the following flags:
virtctl create vm --infer-instancetype --infer-preference
The implicit default is to always try to infer an instance type and preference from the boot volume. This feature makes use of the IgnoreInferFromVolumeFailure
policy, which suppresses failures on inference of instance types and preferences. If one of the above switches has been explicitly specified, the RejectInferFromVolumeFailure
policy is used instead. This way users are made aware of potential issues during the virtual machine creation.
To infer an instance type or preference from another volume than the volume used to boot the virtual machine, use the --infer-instancetype-from
and --infer-preference-from
flags to specify any of the virtual machine’s volumes.
# This virtual machine will boot from volume-a, but the instance type and
# preference are inferred from volume-b.
virtctl create vm \
--volume-import=type:pvc,src:my-ns/my-pvc-a,name:volume-a \
--volume-import=type:pvc,src:my-ns/my-pvc-b,name:volume-b \
--infer-instancetype-from volume-b \
--infer-preference-from volume-b
Boot order of added volumes
Please note that volumes of different kinds currently have the following fixed boot order regardless of the order their flags were specified on the command line:
- Containerdisks
- Directly used PVCs
- DataSources
- Cloned PVCs
- Blank volumes
- Imported volumes (through the
--volume-import
flag)
If multiple volumes of the same kind were specified their order is determined by the order in which their flags were specified.
Generating cloud-init user data
To generate cloud-init user data with virtctl create vm
the following flags can be used.
Note
Generating cloud-init user data is mutually exclusive with specifying custom cloud-init user data, as explained below.
--user
flag
Specify the main user of the virtual machine that is created by cloud-init. It sets the user
parameter in the generated cloud-init user data.
--password-file
flag
Specify a file to read the password for the virtual machine’s main user from. In the generated cloud-init user data, it sets the value of the password
parameter to the read in value and the value of the chpasswd
parameter to { expire: False }
.
--ssh-key
flag
Specify one or more SSH authorized keys for the virtual machine’s main user. It sets the ssh_authorized_keys
parameter in the generated cloud-init user data.
--ga-manage-ssh
flag
When this flag is set, a command enabling the qemu-guest-agent
to manage SSH authorized keys is added to the generated cloud-init user data. The command is added to the runcmd
parameter which is required on SELinux enabled distributions that would otherwise not allow the qemu-guest-agent
to manage SSH authorized keys in the home directories of users.
Example
$ virtctl create vm --user myuser --access-cred=src:my-keys --ga-manage-ssh
This command will generate the following cloud-init user data:
volumes:
- cloudInitNoCloud:
userData: |-
#cloud-config
user: myuser
runcmd:
- [ setsebool, -P, 'virt_qemu_ga_manage_ssh', 'on' ]
name: cloudinitdisk
By passing the --ga-manage-ssh
flag explicitly, the qemu-guest-agent
is able to manage the credentials read from the Secret my-keys
specified as source parameter to the --access-cred
flag. Note that if --ga-manage-ssh
was not explicitly set to false
, this is also the default behavior.
Specifying custom cloud-init user data
To pass custom cloud-init user data to virtctl it needs to be encoded into a base64 string.
Note
Specifying custom cloud-init user data is mutually exclusive with generating cloud-init user data, as explained above.
Here is an example how to do it:
# Put your cloud-init user data into a file.
# This will add an authorized key to the default user.
# To get the default username read the documentation for the cloud image
$ cat cloud-init.txt
#cloud-config
ssh_authorized_keys:
- ssh-rsa AAAA...
# Base64 encode the contents of the file without line wraps and store it in a variable
$ CLOUD_INIT_USERDATA=$(base64 -w 0 cloud-init.txt)
# Show the contents of the variable
$ echo $CLOUD_INIT_USERDATA
I2Nsb3VkLWNvbmZpZwpzc2hfYXV0aG9yaXplZF9rZXlzOgogIC0gc3NoLXJzYSBBQUFBLi4uCg==
You can now use this variable as an argument to the --cloud-init-user-data
flag:
virtctl create vm --cloud-init-user-data $CLOUD_INIT_USERDATA
Adding access credentials to a virtual machine
By using the --access-cred
flag, the virtctl create vm
command can configure access credentials in a created virtual machine. It supports SSH authorized key and password access credentials and can configure them to be injected either through the qemu-guest-agent
or through cloud-init metadata. The supported parameters of the flag depend on the chosen type
and method
. The flag can be passed multiple times to configure more than one access credential.
This flag interacts with the flags used to generate cloud-init user data, namely it inherits the same --user
for SSH key injection, and it enables qemu-guest-agent
to manage SSH authorized keys (--ga-manage-ssh
), if it is not explicitly disabled by the user.
Example
$ virtctl create vm --user myuser --access-cred=src:my-keys
This command will generate the following access credentials and cloud-init user data:
[...]
accessCredentials:
- sshPublicKey:
propagationMethod:
qemuGuestAgent:
users:
- myuser
source:
secret:
secretName: my-keys
volumes:
- cloudInitNoCloud:
userData: |-
#cloud-config
user: myuser
runcmd:
- [ setsebool, -P, 'virt_qemu_ga_manage_ssh', 'on' ]
name: cloudinitdisk
Adding a sysprep volume
A sysprep volume can be added to created virtual machines by passing the --volume-sysprep
flag to the virtctl create vm
command.
The flag supports adding a sysprep volume from both a ConfigMap
or a Secret
.
See the examples on how to do it.
Short examples
Create a manifest for a VirtualMachine with a random name:
virtctl create vm
Create a manifest for a VirtualMachine with a specified name and RunStrategy Always:
virtctl create vm --name=my-vm --run-strategy=Always
Create a manifest for a VirtualMachine with a specified VirtualMachineClusterInstancetype:
virtctl create vm --instancetype=my-instancetype
Create a manifest for a VirtualMachine with a specified VirtualMachineInstancetype (namespaced):
virtctl create vm --instancetype=virtualmachineinstancetype/my-instancetype
Create a manifest for a VirtualMachine with a specified VirtualMachineClusterPreference:
virtctl create vm --preference=my-preference
Create a manifest for a VirtualMachine with a specified VirtualMachinePreference (namespaced):
virtctl create vm --preference=virtualmachinepreference/my-preference
Create a manifest for a VirtualMachine with specified memory and an ephemeral containerdisk volume:
virtctl create vm --memory=1Gi \
--volume-containerdisk=src:my.registry/my-image:my-tag
Create a manifest for a VirtualMachine with a cloned DataSource in namespace and specified size:
virtctl create vm --volume-import=type:ds,src:my-ns/my-ds,size:50Gi
Create a manifest for a VirtualMachine with a cloned DataSource and inferred instance type and preference:
virtctl create vm --volume-import=type:ds,src:my-annotated-ds \
--infer-instancetype --infer-preference
Create a manifest for a VirtualMachine with multiple volumes and specified boot order:
virtctl create vm --volume-containerdisk=src:my.registry/my-image:my-tag \
--volume-import=type:ds,src:my-ds,bootorder:1
Create a manifest for a VirtualMachine with multiple volumes and inferred instance type and preference with specified volumes:
virtctl create vm --volume-import=type:ds,src:my-annotated-ds \
--volume-pvc=my-annotated-pvc --infer-instancetype=my-annotated-ds \
--infer-preference=my-annotated-pvc
Create a manifest for a VirtualMachine with a cloned PVC:
virtctl create vm --volume-import=type:pvc,src:my-ns/my-pvc
Create a manifest for a VirtualMachine using a PVC without cloning it:
virtctl create vm --volume-pvc=src:my-pvc
Create a manifest for a VirtualMachine with a clone DataSource and a blank volume:
virtctl create vm --volume-import=type:ds,src:my-ns/my-ds \
--volume-import=type:blank,size:50Gi
Create a manifest for a VirtualMachine with a specified VirtualMachineCluster{Instancetype,Preference} and cloned DataSource:
virtctl create vm --instancetype=my-instancetype --preference=my-preference \
--volume-import=type:ds,src:my-ds
Create a manifest for a VirtualMachine with a specified VirtualMachineCluster{Instancetype,Preference} and two cloned DataSources (flag can be provided multiple times):
virtctl create vm --instancetype=my-instancetype --preference=my-preference \
--volume-import=type:ds,src:my-ds1 --volume-import=type:ds,src:my-ds2
Create a manifest for a VirtualMachine with a specified VirtualMachineCluster{Instancetype,Preference} and directly used PVC:
virtctl create vm --instancetype=my-instancetype --preference=my-preference \
--volume-pvc=my-pvc
Create a manifest for a VirtualMachine with a specified DataVolumeTemplate:
virtctl create vm \
--volume-import=type:pvc,name:my-pvc,namespace:default,size:256Mi
Create a manifest for a VirtualMachine with a generated cloud-init config setting the user and adding an ssh authorized key:
virtctl create vm --user=cloud-user --ssh-key="ssh-ed25519 AAAA...."
Create a manifest for a VirtualMachine with a generated cloud-init config setting the user and setting the password from a file:
virtctl create vm --user=cloud-user --password-file=/path/to/file
Create a manifest for a VirtualMachine with SSH public keys injected into the VM from a secret called my-keys to the user also specified in the cloud-init config:
virtctl create vm --user=cloud-user --access-cred=type:ssh,src:my-keys
Create a manifest for a VirtualMachine with SSH public keys injected into the VM from a secret called my-keys to a user specified as param:
virtctl create vm --access-cred=type:ssh,src:my-keys,user:myuser
Create a manifest for a VirtualMachine with password injected into the VM from a secret called my-pws:
virtctl create vm --access-cred=type:password,src:my-pws
Create a manifest for a VirtualMachine with a Containerdisk and a Sysprep volume (source ConfigMap needs to exist):
virtctl create vm --memory=1Gi \
--volume-containerdisk=src:my.registry/my-image:my-tag --sysprep=src:my-cm
Complex examples
These examples show how virtctl create vm
can be used in more complex scenarios.
First example
Creating a VirtualMachine with the following settings:
- Run strategy:
Manual
- Termination grace period:
123
seconds - Instancetype:
u1.small
- Prefernce:
fedora
- Using the
quay.io/containerdisks/fedora
containerdisk as first volume - Adding a second blank volume with a size of
1Gi
- The main user is named
myuser
- Logins with the main user are possible with the specified authorized key
virtctl create vm --run-strategy=Manual --termination-grace-period=123 \
--instancetype=u1.small --preference=fedora \
--volume-containerdisk=src:quay.io/containerdisks/fedora \
--volume-import=type:blank,size:1Gi \
--user=myuser --ssh-key='ssh-ed25519 AAAA...'
Second example
Creating a VirtualMachine with the following settings and using a secret for configuring access credentials:
- Instancetype:
u1.small
- Prefernce:
fedora
- Using the
quay.io/containerdisks/fedora
containerdisk as first volume - Adding a second blank volume with a size of
1Gi
- The main user is named
myuser
- Logins with the main user are possible with the specified authorized key in the access credentials
# First create the secret with the public key:
kubectl create secret generic my-keys --from-file=$HOME/.ssh/id_ed25519.pub
# Then create the VM on the cluster
virtctl create vm --name my-vm --instancetype=u1.small --preference=fedora \
--volume-containerdisk=src:quay.io/containerdisks/fedora \
--volume-import=type:blank,size:1Gi --user=myuser \
--access-cred=src:my-keys | kubectl create -f -
# Login via SSH once the VM is ready
virtctl ssh -i $HOME/.ssh/id_ed25519 myuser@my-vm