How to Setup KubeVirt with PMK
This blog post will go over how to setup KubeVirt using PMK. We will create a cluster with KubeVirt enabled, install add-ons for kubectl, and then deploy a virtual machine using the KubeVirt examples in the post. This post also overlaps with videos we have created showing the same demo, as well as an AMA session. Follow along with the post or watch the video and check out the bottom of the post for VMI and service examples.
Videos
Account Setup
There is a quick setup guide that goes over some of the setup, however we are going to choose additional options as this guide goes over installation on BareOS – https://platform9.com/docs/kubevirt/quick-setup-guide.
Cluster Creation with KubeVirt Enabled
After you have created an account we will need to deploy a cluster – this is where we can setup KubeVirt on the cluster at deployment time.
- First we need to create a cluster. Select the Add Cluster drop down and then select Create Cluster.
- Next we are going to pick our infrastructure. In our example we’re using BareOS Virtual Machines, however you can deploy other types of infrastructure. (If you run into issues or have questions please join our Slack Community.) We are going to create a single master cluster so that we can show off functionality without using a large amount of resources.
- We will name our cluster demoKubeVirt and select the latest version of K8s (at the time of this writing.)
- The most important part of the guide – we will select Enable KubeVirt. If you are running on BareOS we should also select Deploy MetalLB so that we can use LoadBalancers, however it is not required if you want to use a NodePort instead. (Our Service example assumes MetalLB is installed.) Select next and proceed to the next configuration page.
- We are setting up a single master cluster so we will need to select a master node. Pick a node and select Next.
- Now we need to select the worker nodes. In this example we are using two worker nodes. Select the nodes and select Finish and Review. There are additional options if you select Next however for the purpose of this guide we aren’t modifying any of the preconfigured options.
- Now that we have configured our cluster we can review our selections. If everything looks good then select Complete.
- After selecting complete you’ll be presenting with a screen showing the deployment status. This process will take a few minutes.
- Finally the cluster has deployed, it should show up as Connected and Healthy. At this point we can navigate to the Virtual Machines section.
- The Virtual Machines section is currently in Early Access. The UI is mostly read only, however you can view information about the Virtual Machines after they have been deployed. We are going to be using the CLI to deploy the VMs.
Kubectl Add-ons
First we need to install Krew so that we can easily install additional add-ons. Krew is a Kubernetes SIG project :
https://github.com/kubernetes-sigs/krew
Installation guides for Krew can be found here:
https://krew.sigs.k8s.io/docs/user-guide/setup/install/
After we have installed Krew we can use it to install the kubectl-virt plugin.
kubectl krew install virt
KubeVirt Virtual Machine Instance Examples
At this point we should have KubeVirt running in our cluster and the Virt add-on installed using Krew. Below are the example YAMLs that were used in the videos posted above.
The first example is a VirtualMachineInstance, which will automatically start once we create/apply with kubectl. Some of the configuration options to note:
- SSH Key is setup using a Secret. The secret will contain your public key. Another option would be to use cloud-config to setup your SSH Keys.
- The Container Image used is an Ubuntu cloud image expanded into a container image. Other options would be to create a volume and expand a cloud image into the volume and then attach it to the container instead. This will allow you to control the disk size.
- Cloud-Config is installing a couple of packages that are useful for getting information about the Virtual Machine. The information can be pulled with
kubectl virt guestosinfo
. Qemu-Guest-Agent is used to pull this information.
apiVersion: kubevirt.io/v1
kind: VirtualMachineInstance
metadata:
name: demo-vmi
labels:
vmi : demo-vmi
spec:
terminationGracePeriodSeconds: 30
domain:
resources:
requests:
memory: 1024M
devices:
disks:
- name: containerdisk
disk:
bus: virtio
- name: emptydisk
disk:
bus: virtio
- disk:
bus: virtio
name: cloudinitdisk
accessCredentials:
- sshPublicKey:
source:
secret:
secretName: mpetersen-pub-key
propagationMethod:
qemuGuestAgent:
users:
- "ubuntu"
volumes:
- name: containerdisk
containerDisk:
image: mpetason/ubuntu:20.04
- name: emptydisk
emptyDisk:
capacity: "10Gi"
- name: cloudinitdisk
cloudInitNoCloud:
userData: |-
#cloud-config
password: ubuntu
chpasswd: { expire: False }
package_update: true
package_upgrade: true
packages:
- qemu-guest-agent
runcmd:
- [ systemctl, start, qemu-guest-agent ]
Extra Example using Cloud-Config for SSH Keys, installing apache2 and qemu-guest-agent:
apiVersion: kubevirt.io/v1
kind: VirtualMachineInstance
metadata:
name: demo-vmi
labels:
vmi : demo-vmi
spec:
terminationGracePeriodSeconds: 30
domain:
resources:
requests:
memory: 1024M
devices:
disks:
- name: containerdisk
disk:
bus: virtio
- disk:
bus: virtio
name: cloudinitdisk
volumes:
- name: containerdisk
containerDisk:
image: mpetason/ubuntu:20.04
- name: cloudinitdisk
cloudInitNoCloud:
userData: |-
#cloud-config
password: ubuntu
chpasswd: { expire: False }
ssh_authorized_keys:
- YOUR PUBLIC SSH KEY
package_update: true
package_upgrade: true
packages:
- qemu-guest-agent
- apache2
runcmd:
- [ systemctl, start, qemu-guest-agent ]
If you are using either of the examples above – save the data as a yaml file, in my example I’m naming the file ubuntu-vmi.yaml
so that I can use kubectl to create it.
kubectl create -f ubuntu-vmi.yaml
After we have created the VM we need a way to communicate with it. Using an LoadBalancer or NodePort will expose the VM to external networks. In this example I’m exposing port 80 for Apache2, and port 22 for SSH. This Service example is being applied to the YAML file above, which installs apache2.
apiVersion: v1
kind: Service
metadata:
name: vmi-lb
spec:
ports:
- port: 22
name: ssh
protocol: TCP
targetPort: 22
- port: 80
name: http
protocol: TCP
targetPort: 80
selector:
vmi : demo-vmi
type: LoadBalancer
We will also need to save the service file in a separate YAML, I have named it service-ubuntu-vmi.yaml
however you could also have everything in a single YAML file with separators for each service. To create the service can we run:
kubectl create -f service-ubuntu-vmi.yaml
If you’re using MetalLB, or a cloud provider, you should be able to find the Service IP address which can be used to SSH to the VM. For this example we’re using Ubuntu so the username is ubuntu. If you’re using the example with Apache2 installed then you can also Curl the address to see it working. Assuming we’re in the default namespace we can run:
kubectl get service
ssh ubuntu@IPofLoadBalancer
curl http://IPofLoadBalancer
Conclusion
PMK makes it quick and easy to setup a cluster with KubeVirt. Once KubeVirt is running you can re-use some of the cloud images you are used to using with other Virtual Machine infrastructure such as OpenStack. There’s a decent amount of overlap in how KubeVirt works within the container which can help bridge the gap between VM infrastructure and Kubernetes.
- Using MetalLB to add the LoadBalancer Service to Kubernetes Environments - February 28, 2022
- How to Set Up Knative Serving on Kubernetes - February 2, 2022
- How to Create a Virtual Machine Using KubeVirt – A Detailed Walkthrough - December 1, 2021