---
title: "Using Kubernetes to orchestrate VMs"
source: "https://wordpress-1075849-4005834.cloudwaysapps.com/blog/using-kubernetes-to-orchestrate-vms/"
description: "Learn how to add KubeVirt to your cluster, using Calico networking, and then use Calico network policy to secure the VMs."
---

[Technical Blog](https://wordpress-1075849-4005834.cloudwaysapps.com/category/technical-blog/)

# Using Kubernetes to orchestrate VMs

By [Reza Ramezanpour](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/author/rezar/) on Sep 16, 2020 • 5 min read



The benefits of containers and using Kubernetes for container orchestration are very well known. But what do you do if you have a workload that is not amenable to being containerized? Perhaps you have a third-party VM-based workload that you yourself can’t easily containerize, or perhaps requires a different kernel or base OS than your Kubernetes platform is running. 






What you would really want is a way for Kubernetes to orchestrate VMs alongside standard container based pods, in a way that looks and feels just like an ordinary pod. Two recent projects that aim to allow you to do just this are [KubeVirt](http://kubevirt.io/) and OpenShift [CNV](http://www.openshift.com/blog/openshift-4-3-creating-virtual-machines-on-kubernetes-with-openshifts-cnv).






In this blog I’ll get hands on with KubeVirt in a step-by-step guide that you can follow yourself to add KubeVirt to your cluster, using Calico networking, and then use Calico network policy to secure the VMs.






## Before we begin






I’m using Ubuntu 20.04 and two bare metal servers for my development cluster. Although I have an explanation on how to create a similar development cluster in “Step 1”, you can safely skip it if you already have a different Kubernetes or OpenShift environment of choice.






Requirements:








- At least one host with 2 CPUs, 4GB Ram and 20GB of storage

- kubectl command line utility

- SSH client






## Step 1: Create a cluster






Before we begin creating a cluster let’s make our host suitable for Kubernetes. Check out this excellent [tutorial](http://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/) and prepare your host.






Let’s create a Kubernetes Cluster






```
`sudo kubeadm init --pod-network-cidr=192.168.0.0/16`
```






Execute the following commands to configure kubectl:






```
`mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config`
```






Remove the taints on the master so that you can schedule pods on it.






```
`kubectl taint nodes --all node-role.kubernetes.io/master-`
```






It should return the following:






```
`node/<your-hostname> untainted`
```






## Step 2: Install Calico






Install Calico using latest manifest






```
`kubectl apply -f http://docs.projectcalico.org/manifests/calico.yaml`
```






## Step 3: Install KubeVirt






Using namespaces, we can isolate resources to logical blocks and manage them easier.






```
`kubectl create namespace kubevirt`
```






It is recommended to use a host that can support hardware virtualization, to ensure your host(s) are capable you can use `virt-host-validate` binary.






```
`virt-host-validate qemu QEMU: Checking for hardware virtualization :PASS`
```






If your host is missing this command you can install it using your distro package manager or simply check if the kvm folder is available using  `ls /dev/kvm`.






By default, KubeVirt tries to leverage hardware emulation. However, this feature is not available in all environments in this case you can enable software emulation using:






```
`kubectl create configmap -n kubevirt kubevirt-config --from-literal debug.useEmulation=true`
```






Apply these manifests and run the KubeVirt operator to automatically install all the required resources.






```
`kubectl apply -f http://github.com/kubevirt/kubevirt/releases/download/v0.32.0/kubevirt-operator.yaml kubectl apply -f http://github.com/kubevirt/kubevirt/releases/download/v0.32.0/kubevirt-cr.yaml`
```






You can check KubeVirt installation progress using this command.






```
`kubectl -n kubevirt wait kv kubevirt --for condition=Available`
```






## Step 4: Create a simple VM






First let’s create a namespace to isolate our resources for this demo.






```
`kubectl create namespace kv-policy-demo`
```






Using Virtual Machine Instance (VMI) custom resources we can now create VMs that are fully integrated with Kubernetes.






```
`kubectl create -f - <<EOF apiVersion: kubevirt.io/v1alpha3 kind: VirtualMachineInstance metadata: name: vmi-cirros namespace: kv-policy-demo labels: special: l-vmi-cirros spec: domain: devices: disks: - disk: bus: virtio name: containerdisk resources: requests: memory: 64M volumes: - name: containerdisk containerDisk: image: kubevirt/cirros-registry-disk-demo:latest EOF`
```






**Note: If you are using software emulation then starting up a VM can be very slow and it might take 5-6 minutes for VM to finishing coming up with an IP address**.






Create a service to map to the SSH port:






```
`kubectl create -f - <<EOF apiVersion: v1 kind: Service metadata: name: vmi-cirros-ssh-svc namespace: kv-policy-demo spec: ports: - name: crrios-ssh-svc nodePort: 30000 port: 27017 protocol: TCP targetPort: 22 selector: special: l-vmi-cirros type: NodePort EOF`
```






Confirm we can access VMs using SSH by accessing via the service node port using your node’s IP address. The default password is `gocubsgo`.






```
`ssh cirros@10.1.2.3 -p 30000`
```






Confirm that the VM can access the outside world by pinging google from your new VM.






```
`ping www.google.com -c 5`
```






## Step 5: Add network security






Apply the following policy to isolate the VM in its namespace. This locks down all incoming connects to SSH only, and prevents the VM from making outgoing connections. (Depending on your VM, you’ll want a different policy, but this simple policy is good for this tutorial.)






```
`kubectl create -f - <<EOF apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: only-allow-ingress-ssh-to-vm namespace: kv-policy-demo spec: podSelector: matchLabels: special: l-vmi-cirros policyTypes: - Ingress - Egress ingress: - from: ports: - port: 22 EOF`
```






SSH into the VM and try to ping google again. 






You will not be able to since the policy will prevent all communication originated from the pod to the outside world. This is pretty powerful – you can secure your VMs using the same paradigms as securing pods!






## Cleanup






To cleanup the namespace and VM I used in this guide, you can run this command






```
`kubectl delete namespace kv-policy-demo`
```








**If you enjoyed this blog then you may also like:**








- Learn more about KubeVirt: [how to access VM console](http://kubevirt.io/user-guide/#/usage/graphical-and-console-access) and [how to install a Windows VM](http://kubevirt.io/user-guide/#/creation/virtio-win)

- Free online training at [projectcalico.org/events](http://projectcalico.org/events) or subscribe to [Calico Essentials](https://info.tigera.io/rs/805-GFH-732/images/Calico-Essentials-Datasheet.pdf) for personalized training & workshops

- Learn about [Calico Enterprise](http://docs.projectcalico.org/calico-enterprise/)



[How-To](https://wordpress-1075849-4005834.cloudwaysapps.com/tags/how-to/)[Open Source](https://wordpress-1075849-4005834.cloudwaysapps.com/tags/open-source/)[Project Calico](https://wordpress-1075849-4005834.cloudwaysapps.com/tags/project-calico/)

Add Tigera as a preferred source on Google to see more of our content in your search results.

[![Add as a preferred source on Google](https://wordpress-1075849-4005834.cloudwaysapps.com/app/themes/tigera2021/dist/img/google-preferred-source-light.png)](https://www.google.com/preferences/source?q=tigera.io)

## Related posts

[![AI Assistant for Calico: Troubleshooting at the Speed of Thought](https://wordpress-1075849-4005834.cloudwaysapps.com/app/uploads/2026/03/Blog-Mar-20-AI-Assistant-for-Calico.png)](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/ai-assistant-for-calico-troubleshooting-at-the-speed-of-thought/)

#### [AI Assistant for Calico: Troubleshooting at the Speed of Thought](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/ai-assistant-for-calico-troubleshooting-at-the-speed-of-thought/)

By [Veronika Smolik](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/author/veronika-smolik/)
on Mar 19, 2026

Despite the wealth of data available, distilling a coherent narrative from a Kubernetes cluster remains a challenge for modern infrastructure teams. Even with powerful visualization tools like the Policy Board, Service Graph, and specialized dashboards,...

[Read more](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/ai-assistant-for-calico-troubleshooting-at-the-speed-of-thought/)

[![What Your EKS Flow Logs Aren’t Telling You](https://wordpress-1075849-4005834.cloudwaysapps.com/app/uploads/2026/03/Blog-Mar-18-What-Your-EKS-Flow-Logs-Arent-Telling-You.png)](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/what-your-eks-flow-logs-arent-telling-you/)

#### [What Your EKS Flow Logs Aren’t Telling You](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/what-your-eks-flow-logs-arent-telling-you/)

By [Phil DiCorpo](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/author/phil-dicorpo/)
on Mar 18, 2026

If you’re running workloads on Amazon EKS, there’s a good chance you already have some form of network observability in place. VPC Flow Logs have been a staple of AWS networking for years, and AWS...

[Read more](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/what-your-eks-flow-logs-arent-telling-you/)

[![What’s New in Calico: Winter 2026 Release](https://wordpress-1075849-4005834.cloudwaysapps.com/app/uploads/2026/03/What-is-new-in-Calico-winter-2026.png)](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/whats-new-in-calico-winter-2026-release/)

[Company Blog](https://wordpress-1075849-4005834.cloudwaysapps.com/category/company-blog/)

#### [What’s New in Calico: Winter 2026 Release](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/whats-new-in-calico-winter-2026-release/)

By [Veronika Smolik](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/author/veronika-smolik/)
on Mar 4, 2026

AI Powered Intelligence, Unified Traffic Observability and Scalable Infrastructure Management As anyone managing one or more Kubernetes clusters knows by now, scaling can introduce an exponentially growing number of problems. The sheer volume of metrics,...

[Read more](https://wordpress-1075849-4005834.cloudwaysapps.com/blog/whats-new-in-calico-winter-2026-release/)

<!-- plugin=object-cache-pro client=phpredis metric#hits=6186 metric#misses=17 metric#hit-ratio=99.7 metric#bytes=2189389 metric#prefetches=0 metric#store-reads=418 metric#store-writes=14 metric#store-hits=430 metric#store-misses=6 metric#sql-queries=31 metric#ms-total=991.93 metric#ms-cache=64.52 metric#ms-cache-avg=0.1497 metric#ms-cache-ratio=6.5 sample#redis-hits=75550472 sample#redis-misses=9080366 sample#redis-hit-ratio=89.3 sample#redis-ops-per-sec=565 sample#redis-evicted-keys=0 sample#redis-used-memory=123726688 sample#redis-used-memory-rss=111775744 sample#redis-memory-fragmentation-ratio=0.9 sample#redis-connected-clients=1 sample#redis-tracking-clients=0 sample#redis-rejected-connections=0 sample#redis-keys=36059 -->
