One of my favourite up stream Open Source communities is KubeVirt, origionally from Red Hat, it become a CNCF sandbox project in 2019. For those unfamilar with KubeVirt, it essentially has a focus on providing a capability to run virtual images inside containers, this has a number of benefits including the opportunity to have a single approach to managing their application platform. In this post, I’d like to provide an overview for those, like myself who are Apple MacOS users / developer, wanting to contribute to KubeVirt.
There are some pre-requisites that must be met:
- You must install a local Kubernetes cluster, typically this would involve installing kind or minikube . There is a very good quickstart guide for both on the KubeVirt site.
- Next, ensure the kubectl command line tool is installed and is pointing at the local cluster.
- I then recommend installing the virtctl tool, which will be used to create / manage virtual images – the tool can be deployed as a kubectl plugin, which I prefer as it provides consistency for kubernetes management (one tool to use).
- You must have the GO language installed.
- You need a container management app, such as Docker or Podman.
To simply how I meet the pre-requisites, I decided to use Homebrew, and with the help of my AI tools, generated a script to automate my setup (which has the added benefit of having a repeatable process if I decide to remove KubeVirt etc).
The script looks like this :
#!/usr/bin/env bash
set -euo pipefail
CLUSTER_NAME="kubevirt-dev"
REPO_DIR="${HOME}/src/kubevirt"
GOPATH_DEFAULT="${HOME}/go"
echo "==> KubeVirt macOS dev bootstrap starting..."
# --- Helper functions --------------------------------------------------------
need() {
if ! command -v "$1" >/dev/null 2>&1; then
return 1
fi
return 0
}
brew_install_if_missing() {
local pkg="$1"
if ! brew list --formula "$pkg" >/dev/null 2>&1; then
echo "==> Installing ${pkg} with Homebrew..."
brew install "$pkg"
else
echo "==> ${pkg} already installed."
fi
}
# --- Homebrew ----------------------------------------------------------------
if ! need brew; then
echo "!! Homebrew is required but not installed."
echo " Install from https://brew.sh and re-run this script."
exit 1
fi
# --- Core tools --------------------------------------------------------------
brew_install_if_missing git
brew_install_if_missing go
brew_install_if_missing make
brew_install_if_missing jq
brew_install_if_missing yq
brew_install_if_missing kubectl
brew_install_if_missing kind
# Docker is special: usually via Docker Desktop
if ! need docker; then
echo "!! Docker is not installed or not in PATH."
echo " Install Docker Desktop for Mac, start it, then re-run this script."
exit 1
fi
echo "==> Verifying Docker daemon..."
if ! docker info >/dev/null 2>&1; then
echo "!! Docker daemon not reachable. Start Docker Desktop and try again."
exit 1
fi
# --- Go env ------------------------------------------------------------------
echo "==> Configuring Go environment (temporary for this session)..."
export GOPATH="${GOPATH:-$GOPATH_DEFAULT}"
export PATH="${GOPATH}/bin:${PATH}"
echo " GOPATH=${GOPATH}"
# --- Clone KubeVirt repo -----------------------------------------------------
if [ -d "${REPO_DIR}" ]; then
echo "==> KubeVirt repo already exists at ${REPO_DIR}, pulling latest..."
git -C "${REPO_DIR}" fetch --all --prune
git -C "${REPO_DIR}" checkout main || true
git -C "${REPO_DIR}" pull --ff-only || true
else
echo "==> Cloning KubeVirt repo to ${REPO_DIR}..."
mkdir -p "$(dirname "${REPO_DIR}")"
git clone https://github.com/kubevirt/kubevirt.git "${REPO_DIR}"
fi
cd "${REPO_DIR}"
# --- Build (local dev binaries) ---------------------------------------------
echo "==> Running: make build"
make build
echo "==> (Optional) Running unit tests: make test"
if make test; then
echo "==> Unit tests succeeded."
else
echo "!! Some unit tests failed. You can investigate later; continuing with cluster setup..."
fi
# --- Create kind cluster -----------------------------------------------------
if kind get clusters | grep -q "^${CLUSTER_NAME}$"; then
echo "==> kind cluster '${CLUSTER_NAME}' already exists."
else
echo "==> Creating kind cluster '${CLUSTER_NAME}'..."
kind create cluster --name "${CLUSTER_NAME}"
fi
# Point kubectl at this cluster
kubectl cluster-info --context "kind-${CLUSTER_NAME}" >/dev/null 2>&1 || {
echo "!! Could not switch kubectl context to kind-${CLUSTER_NAME}"
exit 1
}
# --- Install KubeVirt (stable release) --------------------------------------
echo "==> Fetching latest stable KubeVirt release version..."
RELEASE="$(curl -s https://storage.googleapis.com/kubevirt-prow/release/kubevirt/kubevirt/stable.txt)"
if [ -z "${RELEASE}" ]; then
echo "!! Failed to get stable KubeVirt release version."
exit 1
fi
echo "==> Using KubeVirt release: ${RELEASE}"
echo "==> Applying KubeVirt operator..."
kubectl apply -f "https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-operator.yaml"
echo "==> Applying KubeVirt CR..."
kubectl apply -f "https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/kubevirt-cr.yaml"
echo "==> Waiting for KubeVirt to become Available..."
kubectl -n kubevirt wait kv kubevirt --for condition=Available --timeout=5m
# --- Enable emulation mode ---------------------------------------------------
echo "==> Enabling emulation mode (no hardware KVM on macOS)..."
kubectl -n kubevirt patch kv kubevirt \
--type merge \
-p '{"spec": {"configuration": {"developerConfiguration": {"useEmulation": true}}}}' || {
echo "!! Failed to patch KubeVirt for emulation. Check the kubevirt CR."
}
# --- Install virtctl for macOS ----------------------------------------------
echo "==> Installing virtctl client for macOS..."
ARCH="$(uname -m)"
case "${ARCH}" in
x86_64) ARCH="amd64" ;;
arm64) ARCH="arm64" ;;
esac
VIRTCTL_BIN="/usr/local/bin/virtctl"
TMP_VIRTCTL="$(mktemp)"
curl -L -o "${TMP_VIRTCTL}" \
"https://github.com/kubevirt/kubevirt/releases/download/${RELEASE}/virtctl-${RELEASE}-darwin-${ARCH}"
chmod +x "${TMP_VIRTCTL}"
sudo mv "${TMP_VIRTCTL}" "${VIRTCTL_BIN}"
echo "==> virtctl installed to ${VIRTCTL_BIN}"
# --- Smoke test: create a tiny VM -------------------------------------------
echo "==> Applying sample VM manifest (cirros test VM)..."
kubectl apply -f https://kubevirt.io/labs/manifests/vm.yaml || {
echo "!! Failed to apply sample VM, skipping smoke test."
echo " You can manually add workloads later."
exit 0
}
echo "==> Listing VM objects..."
kubectl get vm
echo "==> You can now start the VM with:"
echo " virtctl start testvm"
echo " virtctl console testvm"
echo
echo "==> All done."
echo " Repo: ${REPO_DIR}"
echo " Cluster: kind-${CLUSTER_NAME}"
echo " Emulation: enabled (useEmulation=true)"
echo
echo "Tip: Add this to your shell config for Go:"
echo " export GOPATH=\"${GOPATH}\""
To use the script :
- Save the script as
myKubeVirt-Setup.sh - Make the file executable –
chmod +x myKubeVirt-Setup.sh - Run the script
When it finishes, you’ll have:
- A KubeVirt git checkout under
~/src/kubevirt - A working Go build + tests locally
- A kind cluster named kubevirt-dev with KubeVirt installed
- Emulation mode enabled so VMs can run without /dev/kvm
- virtctl installed for managing VMs
Enjoy 👨🏻💻😃







