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:
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:
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:
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¶
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:
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¶
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:
Create a manifest for a VirtualMachine with a specified name and RunStrategy Always:
Create a manifest for a VirtualMachine with a specified VirtualMachineClusterInstancetype:
Create a manifest for a VirtualMachine with a specified VirtualMachineInstancetype (namespaced):
Create a manifest for a VirtualMachine with a specified VirtualMachineClusterPreference:
Create a manifest for a VirtualMachine with a specified VirtualMachinePreference (namespaced):
Create a manifest for a VirtualMachine with specified memory and an ephemeral containerdisk volume:
Create a manifest for a VirtualMachine with a cloned DataSource in namespace and specified size:
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:
Create a manifest for a VirtualMachine using a PVC without cloning it:
Create a manifest for a VirtualMachine with a clone DataSource and a blank volume:
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:
Create a manifest for a VirtualMachine with a specified DataVolumeTemplate:
Create a manifest for a VirtualMachine with a generated cloud-init config setting the user and adding an ssh authorized key:
Create a manifest for a VirtualMachine with a generated cloud-init config setting the user and setting the password from a 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:
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:
Create a manifest for a VirtualMachine with password injected into the VM from a secret called 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