In the end you’ll have parallels VM template which later you can use to create virtual machines for a single or multi node kubernetes cluster with high availability feature on or off. Let’s begin.

  • Download ubuntu server ISO image

    wget https://cdimage.ubuntu.com/releases/24.04/release/ubuntu-24.04.2-live-server-arm64.iso
    
  • Create, configure and start a new virtual machine vm-template using prlctl command line tool provided by Parallels.

    prlctl create vm-template --ostype linux --distribution ubuntu
    prlctl set vm-template --device-set cdrom0 --image ~/Downloads/ubuntu-24.04.2-live-server-arm64.iso --connect
    prlctl start vm-template
    
  • Find vm-template Parallels Control Center, double-click to connect and proceed with installation. During installation set user cka, name vm-template, enable ssh. You can keep the rest of parameters as is. Reboot after installation is finished.

  • To be able to execute commands in VM without ssh install parallels tools

    prlctl set vm-template --device-set cdrom0 --image /Applications/Parallels\ Desktop.app/Contents/Resources/Tools/prl-tools-lin-arm.iso --connect
    
  • Parallels updates /etc/hosts on your host MacOS by adding virtual machine name and IP every time that VM is started. Therefore you can use machine name and/or IP to ssh into a virtual machine from MacOS terminal. Run ssh cka@vm-template and execute the following commands to install Parallels Tools.

    sudo apt install gcc make -y
    sudo mkdir -p /media/cdrom
    sudo mount /dev/cdrom /media/cdrom
    cd /media/cdrom
    sudo ./install
    exit
    
  • Now you can run prlctl execute followed by any linux command without ssh. Run the following to install and configure containerd, runc, kubelet, kubeadm, kubectl. These tools are required on every kubernetes node.

    # disable swap
    prlctl exec vm-template "swapoff -a"
    # permanently disable swap
    prlctl exec vm-template "sed -i 's/\/swap/#\/swap/' /etc/fstab"
    # install required packages
    prlctl exec vm-template "apt update"
    prlctl exec vm-template "apt upgrade -y"
    prlctl exec vm-template "apt install -y wget make gcc linux-libc-dev libseccomp-dev pkg-config git apt-transport-https ca-certificates curl gpg"
    # enable IPv4 packet forwarding
    prlctl exec vm-template "cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
    net.ipv4.ip_forward = 1
    net.bridge.bridge-nf-call-iptables  = 1
    net.bridge.bridge-nf-call-ip6tables  = 1
    EOF
    "
    prlctl exec vm-template "sysctl --system"
    # install containerd
    prlctl exec vm-template "wget https://github.com/containerd/containerd/releases/download/v2.0.4/containerd-2.0.4-linux-arm64.tar.gz"
    prlctl exec vm-template "tar Cxzvf /usr/local/ containerd-2.0.4-linux-arm64.tar.gz"
    # configure containerd
    prlctl exec vm-template "mkdir -p /etc/containerd"
    prlctl exec vm-template "cat <<- TOML | sudo tee /etc/containerd/config.toml
    version = 2
      [plugins]
        [plugins.\"io.containerd.grpc.v1.cri\"]
          [plugins.\"io.containerd.grpc.v1.cri\".containerd]
            discard_unpacked_layers = true
            [plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes]
              [plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.runc]
                runtime_type = \"io.containerd.runc.v2\"
                [plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.runc.options]
                  SystemdCgroup = true
    TOML
    "
    # install runc
    prlctl exec vm-template "wget https://github.com/opencontainers/runc/releases/download/v1.2.6/runc.arm64"
    prlctl exec vm-template "install -m 755 runc.arm64 /usr/local/sbin/runc"
    # confure containerd as a service
    prlctl exec vm-template "wget https://raw.githubusercontent.com/containerd/containerd/main/containerd.service"
    prlctl exec vm-template "mv containerd.service /usr/lib/systemd/system/"
    prlctl exec vm-template "systemctl daemon-reload"
    prlctl exec vm-template "systemctl enable --now containerd"
    # 
    prlctl exec vm-template "ln -s /etc/apparmor.d/runc /etc/apparmor.d/disable/"
    prlctl exec vm-template "apparmor_parser -R /etc/apparmor.d/runc"
    # install kubectl, kubelet, kubeadm
    prlctl exec vm-template "cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
    br_netfilter
    EOF
    "
    prlctl exec vm-template "curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg"
    prlctl exec vm-template "echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list"
    prlctl exec vm-template "apt-get update"
    prlctl exec vm-template "apt-get install -y kubelet kubeadm kubectl"
    prlctl exec vm-template "apt-mark hold kubelet kubeadm kubectl"
    prlctl exec vm-template "crictl config --set runtime-endpoint=unix:///run/containerd/containerd.sock"
    
  • Convert virtual machine vm-template into a parallels VM template k8s-vm-template

    prlctl stop vm-template
    prlctl clone vm-template --template --name k8s-vm-template